2
0
mirror of https://github.com/openvswitch/ovs synced 2025-08-22 09:58:01 +00:00

Import from old repository commit 61ef2b42a9c4ba8e1600f15bb0236765edc2ad45.

This commit is contained in:
Ben Pfaff 2009-07-08 13:19:16 -07:00
commit 064af42167
387 changed files with 75535 additions and 0 deletions

43
.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
#*#
*.a
*.d
*.ko
*.la
*.lo
*.loT
*.mod.c
*.o
*.o
*.pyc
*.so
*~
.#*
.*.cmd
.*.swp
.deps
.libs
.tmp_versions
/Makefile
/Makefile.in
/aclocal.m4
/autom4te.cache
/build-arch-stamp
/build-aux
/build-indep-stamp
/compile
/config.guess
/config.h
/config.h.in
/config.log
/config.status
/config.sub
/configure
/configure-stamp
/depcomp
/install-sh
/missing
/stamp-h1
Module.symvers
TAGS
cscope.*
tags

29
COPYING Normal file
View File

@ -0,0 +1,29 @@
This file is a summary of the licensing of files in this distribution.
Some files may be marked specifically with a different license, in
which case that license applies to the file in question.
Files under the debian, doc, include, lib, m4, secchan, tests,
third-party, and utilities directories are licensed under the ISC
license:
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
Files under the datapath directory are licensed under the GNU General
Public License, version 2.
Files under the extras and vswitchd directories are licensed under the
GNU General Public License, version 3 or later.
Files under the xenserver directory are licensed on a file-by-file
basis. Some files are under an uncertain license that may not be
DFSG-compliant or GPL-compatible. Refer to each file for details.

504
CodingStyle Normal file
View File

@ -0,0 +1,504 @@
Open vSwitch Coding Style
=========================
This file describes the coding style used in most C files in the Open
vSwitch distribution. However, Linux kernel code datapath directory
follows the Linux kernel's established coding conventions.
BASICS
Limit lines to 79 characters.
Use form feeds (control+L) to divide long source files into logical
pieces. A form feed should appear as the only character on a line.
Do not use tabs for indentation.
Avoid trailing spaces on lines.
NAMING
Use names that explain the purpose of a function or object.
Use underscores to separate words in an identifier: multi_word_name.
Use lowercase for most names. Use uppercase for macros, macro
parameters, and members of enumerations.
Give arrays names that are plural.
Pick a unique name prefix (ending with an underscore) for each
module, and apply that prefix to all of that module's externally
visible names. Names of macro parameters, struct and union members,
and parameters in function prototypes are not considered externally
visible for this purpose.
Do not use names that begin with _. If you need a name for
"internal use only", use __ as a suffix instead of a prefix.
Avoid negative names: "found" is a better name than "not_found".
In names, a "size" is a count of bytes, a "length" is a count of
characters. A buffer has size, but a string has length. The length
of a string does not include the null terminator, but the size of the
buffer that contains the string does.
COMMENTS
Comments should be written as full sentences that start with a
capital letter and end with a period. Put two spaces between
sentences.
Write block comments as shown below. You may put the /* and */ on
the same line as comment text if you prefer.
/*
* We redirect stderr to /dev/null because we often want to remove all
* traffic control configuration on a port so its in a known state. If
* this done when there is no such configuration, tc complains, so we just
* always ignore it.
*/
Each function and each variable declared outside a function, and
each struct, union, and typedef declaration should be preceded by a
comment. See FUNCTION DEFINITIONS below for function comment
guidelines.
Each struct and union member should each have an inline comment that
explains its meaning. structs and unions with many members should be
additionally divided into logical groups of members by block comments,
e.g.:
/* An event that will wake the following call to poll_block(). */
struct poll_waiter {
/* Set when the waiter is created. */
struct list node; /* Element in global waiters list. */
int fd; /* File descriptor. */
short int events; /* Events to wait for (POLLIN, POLLOUT). */
poll_fd_func *function; /* Callback function, if any, or null. */
void *aux; /* Argument to callback function. */
struct backtrace *backtrace; /* Event that created waiter, or null. */
/* Set only when poll_block() is called. */
struct pollfd *pollfd; /* Pointer to element of the pollfds array
(null if added from a callback). */
};
Use XXX or FIXME comments to mark code that needs work.
Don't use // comments.
Don't comment out or #if 0 out code. Just remove it. The code that
was there will still be in version control history.
FUNCTIONS
Put the return type, function name, and the braces that surround the
function's code on separate lines, all starting in column 0.
Before each function definition, write a comment that describes the
function's purpose, including each parameter, the return value, and
side effects. References to argument names should be given in
single-quotes, e.g. 'arg'. The comment should not include the
function name, nor need it follow any formal structure. The comment
does not need to describe how a function does its work, unless this
information is needed to use the function correctly (this is often
better done with comments *inside* the function).
Simple static functions do not need a comment.
Within a file, non-static functions should come first, in the order
that they are declared in the header file, followed by static
functions. Static functions should be in one or more separate pages
(separated by form feed characters) in logical groups. A commonly
useful way to divide groups is by "level", with high-level functions
first, followed by groups of progressively lower-level functions.
This makes it easy for the program's reader to see the top-down
structure by reading from top to bottom.
All function declarations and definitions should include a
prototype. Empty parentheses, e.g. "int foo();", do not include a
prototype (they state that the function's parameters are unknown);
write "void" in parentheses instead, e.g. "int foo(void);".
Prototypes for static functions should either all go at the top of
the file, separated into groups by blank lines, or they should appear
at the top of each page of functions. Don't comment individual
prototypes, but a comment on each group of prototypes is often
appropriate.
In the absence of good reasons for another order, the following
parameter order is preferred. One notable exception is that data
parameters and their corresponding size parameters should be paired.
1. The primary object being manipulated, if any (equivalent to the
"this" pointer in C++).
2. Input-only parameters.
3. Input/output parameters.
4. Output-only parameters.
5. Status parameter.
Example:
/* Stores the features supported by 'netdev' into each of '*current',
* '*advertised', '*supported', and '*peer' that are non-null. Each value
* is a bitmap of "enum ofp_port_features" bits, in host byte order.
* Returns 0 if successful, otherwise a positive errno value. On failure,
* all of the passed-in values are set to 0. */
int
netdev_get_features(struct netdev *netdev,
uint32_t *current, uint32_t *advertised,
uint32_t *supported, uint32_t *peer)
{
...
}
FUNCTION PROTOTYPES
Put the return type and function name on the same line in a function
prototype:
static const struct option_class *get_option_class(int code);
Omit parameter names from function prototypes when the names do not
give useful information, e.g.:
int netdev_get_mtu(const struct netdev *);
STATEMENTS
Indent each level of code with 4 spaces. Use BSD-style brace
placement:
if (a()) {
b();
d();
}
Put a space between "if", "while", "for", etc. and the expressions
that follow them.
Enclose single statements in braces:
if (a > b) {
return a;
} else {
return b;
}
Use comments and blank lines to divide long functions into logical
groups of statements.
Avoid assignments inside "if" and "while" conditions.
Do not put gratuitous parentheses around the expression in a return
statement, that is, write "return 0;" and not "return(0);"
Write only one statement per line.
Indent "switch" statements like this:
switch (conn->state) {
case S_RECV:
error = run_connection_input(conn);
break;
case S_PROCESS:
error = 0;
break;
case S_SEND:
error = run_connection_output(conn);
break;
default:
NOT_REACHED();
}
"switch" statements with very short, uniform cases may use an
abbreviated style:
switch (code) {
case 200: return "OK";
case 201: return "Created";
case 202: return "Accepted";
case 204: return "No Content";
default: return "Unknown";
}
Use "for (;;)" to write an infinite loop.
In an if/else construct where one branch is the "normal" or "common"
case and the other branch is the "uncommon" or "error" case, put the
common case after the "if", not the "else". This is a form of
documentation. It also places the most important code in sequential
order without forcing the reader to visually skip past less important
details. (Some compilers also assume that the "if" branch is the more
common case, so this can be a real form of optimization as well.)
MACROS
Don't define an object-like macro if an enum can be used instead.
Don't define a function-like macro if a "static inline" function
can be used instead.
If a macro's definition contains multiple statements, enclose them
with "do { ... } while (0)" to allow them to work properly in all
syntactic circumstances.
Do use macros to eliminate the need to update different parts of a
single file in parallel, e.g. a list of enums and an array that gives
the name of each enum. For example:
/* Logging importance levels. */
#define VLOG_LEVELS \
VLOG_LEVEL(EMER, LOG_ALERT) \
VLOG_LEVEL(ERR, LOG_ERR) \
VLOG_LEVEL(WARN, LOG_WARNING) \
VLOG_LEVEL(INFO, LOG_NOTICE) \
VLOG_LEVEL(DBG, LOG_DEBUG)
enum vlog_level {
#define VLOG_LEVEL(NAME, SYSLOG_LEVEL) VLL_##NAME,
VLOG_LEVELS
#undef VLOG_LEVEL
VLL_N_LEVELS
};
/* Name for each logging level. */
static const char *level_names[VLL_N_LEVELS] = {
#define VLOG_LEVEL(NAME, SYSLOG_LEVEL) #NAME,
VLOG_LEVELS
#undef VLOG_LEVEL
};
SOURCE FILES
Each source file should state its license in a comment at the very
top, followed by a comment explaining the purpose of the code that is
in that file. The comment should explain how the code in the file
relates to code in other files. The goal is to allow a programmer to
quickly figure out where a given module fits into the larger system.
The first non-comment line in a .c source file should be:
#include <config.h>
#include directives should appear in the following order:
1. #include <config.h>
2. The module's own headers, if any. Including this before any
other header (besides <config.h>) ensures that the module's
header file is self-contained (see HEADER FILES) below.
3. Standard C library headers and other system headers, preferably
in alphabetical order. (Occasionally one encounters a set of
system headers that must be included in a particular order, in
which case that order must take precedence.)
4. Open vSwitch headers, in alphabetical order. Use "", not <>,
to specify Open vSwitch header names.
HEADER FILES
Each header file should start with its license, as described under
SOURCE FILES above, followed by a "header guard" to make the header
file idempotent, like so:
#ifndef NETDEV_H
#define NETDEV_H 1
...
#endif /* netdev.h */
Header files should be self-contained; that is, they should #include
whatever additional headers are required, without requiring the client
to #include them for it.
Don't define the members of a struct or union in a header file,
unless client code is actually intended to access them directly or if
the definition is otherwise actually needed (e.g. inline functions
defined in the header need them).
Similarly, don't #include a header file just for the declaration of
a struct or union tag (e.g. just for "struct <name>;"). Just declare
the tag yourself. This reduces the number of header file
dependencies.
TYPES
Use typedefs sparingly. Code is clearer if the actual type is
visible at the point of declaration. Do not, in general, declare a
typedef for a struct, union, or enum. Do not declare a typedef for a
pointer type, because this can be very confusing to the reader.
A function type is a good use for a typedef because it can clarify
code. The type should be a function type, not a pointer-to-function
type. That way, the typedef name can be used to declare function
prototypes. (It cannot be used for function definitions, because that
is explicitly prohibited by C89 and C99.)
You may assume that "char" is exactly 8 bits and that "int" and
"long" are at least 32 bits.
Don't assume that "long" is big enough to hold a pointer. If you
need to cast a pointer to an integer, use "intptr_t" or "uintptr_t"
from <stdint.h>.
Use the int<N>_t and uint<N>_t types from <stdint.h> for exact-width
integer types. Use the PRId<N>, PRIu<N>, and PRIx<N> macros from
<inttypes.h> for formatting them with printf() and related functions.
Use %zu to format size_t with printf().
Use bit-fields sparingly. Do not use bit-fields for layout of
network protocol fields or in other circumstances where the exact
format is important.
Declare bit-fields to be type "unsigned int" or "signed int". Do
*not* declare bit-fields of type "int": C89 allows these to be either
signed or unsigned according to the compiler's whim. (A 1-bit
bit-field of type "int" may have a range of -1...0!) Do not declare
bit-fields of type _Bool or enum or any other type, because these are
not portable.
Try to order structure members such that they pack well on a system
with 2-byte "short", 4-byte "int", and 4- or 8-byte "long" and pointer
types. Prefer clear organization over size optimization unless you
are convinced there is a size or speed benefit.
Pointer declarators bind to the variable name, not the type name.
Write "int *x", not "int* x" and definitely not "int * x".
EXPRESSIONS
Put one space on each side of infix binary and ternary operators:
* / %
+ -
<< >>
< <= > >=
== !=
&
^
|
&&
||
?:
= += -= *= /= %= &= ^= |= <<= >>=
Avoid comma operators.
Do not put any white space around postfix, prefix, or grouping
operators:
() [] -> .
! ~ ++ -- + - * &
Exception 1: Put a space after (but not before) the "sizeof" keyword.
Exception 2: Put a space between the () used in a cast and the
expression whose type is cast: (void *) 0.
Break long lines before binary operators and the ternary operators ?
and :, rather than after them, e.g.
if (first_long_condition() || second_long_condition()
|| third_long_condition())
and
return (out_port != VIGP_CONTROL_PATH
? alpheus_output_port(dp, skb, out_port)
: alpheus_output_control(dp, skb, fwd_save_skb(skb),
VIGR_ACTION));
Do not parenthesize the operands of && and || unless operator
precedence makes it necessary, or unless the operands are themselves
expressions that use && and ||. Thus:
if (!isdigit(s[0]) || !isdigit(s[1]) || !isdigit(s[2])) {
printf("string %s does not start with 3-digit code\n", s);
}
but
if (rule && (!best || rule->priority > best->priority)) {
best = rule;
}
Do parenthesize a subexpression that must be split across more than
one line, e.g.:
*idxp = ((l1_idx << PORT_ARRAY_L1_SHIFT)
| (l2_idx << PORT_ARRAY_L2_SHIFT)
| (l3_idx << PORT_ARRAY_L3_SHIFT));
Try to avoid casts. Don't cast the return value of malloc().
The "sizeof" operator is unique among C operators in that it accepts
two very different kinds of operands: an expression or a type. In
general, prefer to specify an expression, e.g. "int *x =
xmalloc(sizeof *x);". When the operand of sizeof is an expression,
there is no need to parenthesize that operand, and please don't.
Use the ARRAY_SIZE macro from lib/util.h to calculate the number of
elements in an array.
When using a relational operator like "<" or "==", put an expression
or variable argument on the left and a constant argument on the
right, e.g. "x == 0", *not* "0 == x".
BLANK LINES
Put one blank line between top-level definitions of functions and
global variables.
C DIALECT
Try to avoid using GCC extensions where possible.
Some C99 extensions are OK:
* Flexible array members (e.g. struct { int foo[]; }).
* "static inline" functions (but no other forms of "inline", for
which GCC and C99 have differing interpretations).
* "long long"
* <stdint.h> and <inttypes.h>.
* bool and <stdbool.h>, but don't assume that bool or _Bool can
only take on the values 0 or 1, because this behavior can't be
simulated on C89 compilers.
Don't use other C99 extensions, and especially:
* Don't use // comments.
* Don't use designated initializers (e.g. don't write "struct foo
foo = {.a = 1};" or "int a[] = {[2] = 5};").
* Don't mix declarations and code within a block.
* Don't use declarations in iteration statements (e.g. don't write
"for (int i = 0; i < 10; i++)").
* Don't put a trailing comma in an enum declaration (e.g. don't
write "enum { x = 1, };").

514
INSTALL Normal file
View File

@ -0,0 +1,514 @@
Open vSwitch Installation Instructions
This document describes how to build, install, and execute
Open vSwitch.
Open vSwitch implements an Ethernet switch with MAC learning that may
be configured with any of the following features:
* NIC bonding with automatic fail-over and source MAC-based TX
load balancing ("SLB").
* 802.1Q VLAN support.
* Port mirroring, with optional VLAN tagging.
* NetFlow v5 flow logging.
* Connectivity to an external OpenFlow controller, such as
NOX.
The current version of this distribution requires a kernel module to
be built and loaded. An (optional) entirely userspace switch is on
the roadmap for future versions.
The distribution also contains a number of related utilities.
Build Methods
=============
There are two principal ways to build and install this distribution:
- Using "configure" and "make" in the ordinary way. See
Building Conventionally below for detailed instructions.
- As a set of Debian packages. Refer to Building Debian
Packages, below, for instructions.
Base Prerequisites
------------------
Regardless of how it is built, Open vSwitch has a common set of
prerequisites. To compile the userspace programs in the OpenFlow
reference distribution, you will need the following software:
- A make program, e.g. GNU make
(http://www.gnu.org/software/make/). BSD make should also work.
- The GNU C compiler (http://gcc.gnu.org/). We generally test
with version 4.2 or 4.3.
- libssl, from OpenSSL (http://www.openssl.org/), is optional but
recommended if you plan to connect the Open vSwitch to an
OpenFlow controller. libssl is required to establish
confidentiality and authenticity in the connections from an
Open vSwitch to an OpenFlow controller. To enable, configure
with --enable-ssl=yes.
To compile the kernel module, you must also install the following:
- A supported Linux kernel version. Please refer to README for a
list of supported versions.
The OpenFlow datapath requires bridging support (CONFIG_BRIDGE)
to be built as a kernel module. (This is common in kernels
provided by Linux distributions.) The bridge module must not be
loaded or in use. If the bridge module is running (check with
"lsmod | grep bridge"), you must remove it ("rmmod bridge")
before starting the datapath.
- To build a kernel module, you need the same version of GCC that
was used to build that kernel (usually version 4.0 or later).
- A kernel build directory corresponding to the Linux kernel image
the module is to run on. Under Debian and Ubuntu, for example,
each linux-image package containing a kernel binary has a
corresponding linux-headers package with the required build
infrastructure.
If you are working from a Git tree or snapshot (instead of from a
distribution tarball), or if you modify the Open vSwitch build system,
you will also need the following software:
- Autoconf version 2.60 or later (http://www.gnu.org/software/autoconf).
- Automake version 1.10 or later (http://www.gnu.org/software/automake).
- pkg-config (http://pkg-config.freedesktop.org/wiki/). We test
with version 0.22.
Debian Prerequisites
--------------------
To build Debian packages from the Open vSwitch distribution, you will
need to install a number of Debian packages in addition to the base
prerequisites listed above. These additional prerequisites may be
found listed as "Build-Depends" in debian/control in the source tree.
To check that they are installed, first install the dpkg-dev package,
then run dpkg-checkbuilddeps from the top level of the OpenFlow source
tree.
To build Debian packages without being root, also install the
"fakeroot" package.
Building Conventionally
=======================
This section explains how to build and install the Open vSwitch
distribution in the ordinary way using "configure" and "make".
0. Check that you have installed all the prerequisites listed above in
the Base Prerequisites section.
1. In the top source directory, configure the package by running the
configure script. You can usually invoke configure without any
arguments:
% ./configure
To use a specific C compiler for compiling OpenFlow user programs,
also specify it on the configure command line, like so:
% ./configure CC=gcc-4.2
To build the Linux kernel module, so that you can run the
kernel-based switch, pass the location of the kernel build
directory on --with-l26. For example, to build for a running
instance of Linux 2.6:
% ./configure --with-l26=/lib/modules/`uname -r`/build
If you wish to build the kernel module for an architecture other
than the architecture of the machine used for the build, you may
specify the kernel architecture string using the KARCH variable
when invoking the configure script. For example, to build for MIPS
with Linux 2.6:
% ./configure --with-l26=/path/to/linux-2.6 KARCH=mips
The configure script accepts a number of other options and honors
additional environment variables. For a full list, invoke
configure with the --help option.
2. Run make in the top source directory:
% make
The following main binaries will be built:
- Virtual switch daemon: vswitchd/ovs-vswitchd
- Bridge compatibility daemon: vswitchd/ovs-brcompatd
- Datapath administration utility: utilities/ovs-dpctl.
Some less important binaries will be built also:
- Runtime configuration utility: utilities/ovs-appctl.
- Simple OpenFlow controller: utilities/ovs-controller.
- Secure channel executable: secchan/secchan.
- Miscellaneous utilities: utilities/ovs-discover,
utilities/ovs-kill.
- ANSI terminal support for EZIO 16x2 LCD panel:
extras/ezio/ezio-term (only if the proper libraries are
installed).
- Switch monitoring UI for small text displays:
extras/ezio/ovs-switchui (only if the proper libraries are
installed).
- Tests: various binaries in tests/.
If you passed --with-l26 to configure, "make" will also build the
following kernel modules:
- datapath/linux-2.6/brcompat_mod.ko
- datapath/linux-2.6/openflow_mod.ko
3. Run "make install" to install the executables and manpages into the
running system, by default under /usr/local.
4. If you built kernel modules, you may load them with "insmod", e.g.:
% insmod datapath/linux-2.6/openflow_mod.ko
The insmod program must be run as root. You may need to specify a
full path to insmod, e.g. /sbin/insmod. To verify that the modules
have been loaded, run "/sbin/lsmod" and check that openflow_mod is
listed.
5. Test the virtuaal switch, as described under Testing the Virtual
Switch below.
Building Debian Packages
========================
Follow these instructions to build Debian packages for OpenFlow.
0. Check that you have installed all the prerequisites listed above in
the Base Prerequisites and Debian Prerequisites sections above.
1. In the top source directory, run the following command, as root:
% dpkg-buildpackage
Alternatively, if you installed the "fakeroot" package, you may run
dpkg-buildpackage as an ordinary user with the following syntax:
% dpkg-buildpackage -rfakeroot
The following packages will be built in the directory above the
source tree:
- openflow-controller: The OpenFlow controller. Depends on
openflow-pki (see below).
- openflow-switch: Install this package on a machine that acts
as an OpenFlow kernel switch.
- openflow-datapath-source: Source code for OpenFlow's Linux
kernel module.
- openflow-pki: Public-key infrastructure for OpenFlow. Install
this package on a machine that acts as an OpenFlow PKI server
(see "Establishing a Public Key Infrastructure" below).
- openflow-common: Files and utilities required by more than one
of the above packages.
2. To set up an OpenFlow controller, install the openflow-controller
package and its dependencies. You may configure it by editing
/etc/default/openflow-controller, e.g. to enable non-SSL
connections, which are disabled by default. If you change the
default settings, you will need to restart the controller by
running:
% /etc/init.d/openflow-controller restart
3. To set up an OpenFlow switch, install the openflow-switch package
and its dependencies. If it is to be a kernel-based switch, also
install openflow-datapath-source, then follow the instructions in
/usr/share/doc/openflow-datapath-source/README.Debian to build and
install the kernel module.
You may configure the switch one of the following ways:
- Completely by hand, as described under the Testing section
below.
For the userspace datapath-based switch, this is the only
supported form of configuration.
- By editing /etc/default/openflow-switch. You must at least
configure some network devices, by uncommenting NETDEVS and
adding the appropriate devices to the list, e.g. NETDEVS="eth0
eth1".
After you edit this file, you will need to start the switch by
running:
% /etc/init.d/openflow-switch restart
This form of configuration is not supported for the userspace
datapath-based switch.
- By running the ovs-switch-setup program. This interactive
program will walk you through all the steps of configuring an
OpenFlow switch, including configuration of SSL certificates.
Run it without arguments, as root:
% ovs-switch-setup
This form of configuration is not supported for the userspace
datapath-based switch.
Installation
============
This section explains how to install Open vSwitch in a network with one
controller and one or more switches, each of which runs on a separate
machine. Before you begin, you must decide on one of two ways for
each switch to reach the controller over the network:
- Use a "control network" that is completely separate from the
"data network" to be controlled ("out-of-band control"). The
location of the controller must be configured manually in this
case.
- Use the same network for control and for data ("in-band
control"). When in-band control is used, the location of the
controller may be configured manually or discovered
automatically. We will assume manual configuration here;
please refer to secchan(8) for instructions on setting up
controller discovery.
Controller Setup
----------------
On the machine that is to be the OpenFlow controller, start the
"ovs-controller" program listening for connections from switches on
TCP port 6633 (the default), as shown below.
# ovs-controller -v ptcp:
(See ovs-controller(8) for more details)
Make sure the machine hosting the controller is reachable by the
switch.
Testing the Virtual Switch
--------------------------
The Open vSwitch kernel module must be loaded, as described under
"Building Conventionally", before it may be used.
0. The commands below must run as root, so log in as root, or use a
program such as "su" to become root temporarily.
1. Create a datapath instance. The command below creates a datapath
identified as dp0 (see ovs-dpctl(8) for more detailed usage
information).
# ovs-dpctl add-dp dp0
(dp0 is the first datapath within a host. openvswitch_mod supports
multiple datapaths within the same host, which would be identified
as dp1, dp2, etc.)
Creating datapath dp0 creates a new network device, also named dp0.
This network device, called the datapath's "local port", will be
bridged to the physical switch ports by the secchan, for use in
in-band control.
2. Use ovs-dpctl to attach the datapath to physical interfaces on the
machine. Say, for example, you want to create a trivial 2-port
switch using interfaces eth1 and eth2, you would issue the
following commands:
# ovs-dpctl add-if dp0 eth1
# ovs-dpctl add-if dp0 eth2
You can verify that the interfaces were successfully added by asking
ovs-dpctl to print the current status of datapath dp0:
# ovs-dpctl show dp0
3. Arrange so that the switch can reach the controller over the
network.
- If you are using out-of-band control, at this point make sure
that the switch machine can reach the controller over the
network.
- If you are using in-band control, then at this point you must
configure the dp0 network device created in step 1. This
device is not yet bridged to any physical network (because
secchan does that, and it is not yet running), so the next
step depends on whether connectivity is required to configure
the device's IP address:
* If the switch has a static IP address, you may configure
its IP address now, e.g.:
# ifconfig dp0 192.168.1.1
* If the switch does not have a static IP address, e.g. its
IP address is obtained dynamically via DHCP, then proceed
to step 4. The DHCP client will not be able to contact
the DHCP server until the secure channel has started up.
- If you are using in-band control with controller discovery, no
configuration is required at this point. You may proceed to
step 4.
4. Run secchan to start the secure channel connecting the datapath to
a remote controller. If the controller is running on host
192.168.1.2 port 6633 (the default port), the secchan invocation
would look like this:
# secchan dp0 tcp:192.168.1.2
- If you are using in-band control with controller discovery, omit
the second argument to the secchan command.
- If you are using out-of-band control, add --out-of-band to the
command line.
5. If you are using in-band control with manual configuration, and the
switch obtains its IP address dynamically, then you may now obtain
the switch's IP address, e.g. by invoking a DHCP client. The
secure channel will only be able to connect to the controller after
an IP address has been obtained.
6. The secure channel should connect to the controller within a few
seconds. It may take a little longer if controller discovery is in
use, because the switch must then also obtain its own IP address
and the controller's location via DHCP.
Configuration
=============
Secure operation over SSL
-------------------------
The instructions above set up Open vSwitch for operation over a
plaintext TCP connection. Production use of Open vSwitch should use
SSL[*] to ensure confidentiality and authenticity of traffic among
switches and controllers. The source must be configured with
--enable-ssl=yes to build with SSL support.
To use SSL with Open vSwitch, you must set up a public-key infrastructure
(PKI) including a pair of certificate authorities (CAs), one for
controllers and one for switches. If you have an established PKI,
Open vSwitch can use it directly. Otherwise, refer to "Establishing a
Public Key Infrastructure" below.
To configure the controller to listen for SSL connections on port 6633
(the default), invoke it as follows:
# ovs-controller -v pssl: --private-key=PRIVKEY --certificate=CERT \
--ca-cert=CACERT
where PRIVKEY is a file containing the controller's private key, CERT
is a file containing the controller CA's certificate for the
controller's public key, and CACERT is a file containing the root
certificate for the switch CA. If, for example, your PKI was created
with the instructions below, then the invocation would look like:
# ovs-controller -v pssl: --private-key=ctl-privkey.pem \
--certificate=ctl-cert.pem --ca-cert=pki/switchca/cacert.pem
To configure a switch to connect to a controller running on port 6633
(the default) on host 192.168.1.2 over SSL, invoke secchan as follows:
# secchan -v DATAPATH ssl:192.168.1.2 --private-key=PRIVKEY \
--certificate=CERT --ca-cert=CACERT
where DATAPATH is the datapath to connect to (e.g. dp0 or
unix:/var/run/dp0.sock), PRIVKEY is a file containing the switch's
private key, CERT is a file containing the switch CA's certificate for
the switch's public key, and CACERT is a file containing the root
certificate for the controller CA. If, for example, your PKI was
created with the instructions below, then the invocation would look
like:
# secchan -v DATAPATH ssl:192.168.1.2 --private-key=sc-privkey.pem \
--certificate=sc-cert.pem --ca-cert=pki/controllerca/cacert.pem
[*] To be specific, Open vSwitch uses TLS version 1.0 or later (TLSv1), as
specified by RFC 2246, which is very similar to SSL version 3.0.
TLSv1 was released in January 1999, so all current software and
hardware should implement it.
Establishing a Public Key Infrastructure
----------------------------------------
If you do not have a PKI, the ovs-pki script included with Open vSwitch
can help. To create an initial PKI structure, invoke it as:
% ovs-pki init
which will create and populate a new PKI directory. The default
location for the PKI directory depends on how the Open vSwitch tree was
configured (to see the configured default, look for the --dir option
description in the output of "ovs-pki --help").
The pki directory contains two important subdirectories. The
controllerca subdirectory contains controller certificate authority
related files, including the following:
- cacert.pem: Root certificate for the controller certificate
authority. This file must be provided to secchan with the
--ca-cert option to enable it to authenticate valid controllers.
- private/cakey.pem: Private signing key for the controller
certificate authority. This file must be kept secret. There is
no need for switches or controllers to have a copy of it.
The switchca subdirectory contains switch certificate authority
related files, analogous to those in the controllerca subdirectory:
- cacert.pem: Root certificate for the switch certificate
authority. This file must be provided to the controller program
with the --ca-cert option to enable it to authenticate valid
switches.
- private/cakey.pem: Private signing key for the switch
certificate authority. This file must be kept secret. There is
no need for switches or controllers to have a copy of it.
After you create the initial structure, you can create keys and
certificates for switches and controllers with ovs-pki. To create a
controller private key and certificate in files named ctl-privkey.pem
and ctl-cert.pem, for example, you could run:
% ovs-pki req+sign ctl controller
ctl-privkey.pem and ctl-cert.pem would need to be copied to the
controller for its use at runtime (they could then be deleted from
their original locations). The --private-key and --certificate
options of ovs-controller, respectively, would point to these files.
Analogously, to create a switch private key and certificate in files
named sc-privkey.pem and sc-cert.pem, for example, you could run:
% ovs-pki req+sign sc switch
sc-privkey.pem and sc-cert.pem would need to be copied to the switch
for its use at runtime (they could then be deleted from their original
locations). The --private-key and --certificate options,
respectively, of secchan would point to these files.
Bug Reporting
-------------
Please report problems to ovs-bugs@openvswitch.org.

74
Makefile.am Normal file
View File

@ -0,0 +1,74 @@
AUTOMAKE_OPTIONS = foreign subdir-objects
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = datapath
if ENABLE_USERSPACE
if HAVE_DPKG_BUILDPACKAGE
distcheck-hook:
cd $(srcdir) && dpkg-buildpackage -rfakeroot -us -uc
cd $(srcdir) && fakeroot ./debian/rules clean
else
distcheck-hook:
endif
AM_CPPFLAGS = $(SSL_CFLAGS)
AM_CPPFLAGS += $(NCURSES_CFLAGS)
AM_CPPFLAGS += $(PCRE_CFLAGS)
AM_CPPFLAGS += -I $(top_srcdir)/include
AM_CPPFLAGS += -I $(top_srcdir)/lib
AM_CFLAGS = -Wstrict-prototypes
if NDEBUG
AM_CPPFLAGS += -DNDEBUG
AM_CFLAGS += -fomit-frame-pointer
else
AM_LDFLAGS = -export-dynamic
endif
CLEANFILES =
DISTCLEANFILES =
EXTRA_DIST =
TESTS =
TESTS_ENVIRONMENT =
bin_PROGRAMS =
sbin_PROGRAMS =
bin_SCRIPTS =
dist_commands_DATA =
dist_man_MANS =
dist_pkgdata_SCRIPTS =
dist_sbin_SCRIPTS =
man_MANS =
noinst_HEADERS =
noinst_LIBRARIES =
noinst_PROGRAMS =
noinst_SCRIPTS =
EXTRA_DIST += soexpand.pl
ro_c = echo '/* -*- mode: c; buffer-read-only: t -*- */'
SUFFIXES = .in
.in:
$(PERL) $(srcdir)/soexpand.pl -I$(srcdir) < $< | \
sed -e 's,[@]LOGDIR[@],$(LOGDIR),g' \
-e 's,[@]PKIDIR[@],$(PKIDIR),g' \
-e 's,[@]RUNDIR[@],$(RUNDIR),g' \
-e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \
-e 's,[@]PERL[@],$(PERL),g' > $@
include lib/automake.mk
include secchan/automake.mk
include utilities/automake.mk
include tests/automake.mk
include include/automake.mk
include third-party/automake.mk
include debian/automake.mk
include vswitchd/automake.mk
include xenserver/automake.mk
if HAVE_CURSES
if HAVE_PCRE
include extras/ezio/automake.mk
endif
endif
endif # ENABLE_USERSPACE

74
README Normal file
View File

@ -0,0 +1,74 @@
Open vSwitch <http://openvswitch.org>
What is Open vSwitch?
---------------------
Open vSwitch is an Ethernet switch for virtual servers with the
following features:
* NIC bonding with automatic fail-over and source MAC-based TX
load balancing ("SLB").
* 802.1Q VLAN support.
* Port mirroring, with optional VLAN tagging.
* NetFlow v5 flow logging.
* Connectivity to an external OpenFlow controller, such as
NOX.
What's here?
------------
The most important components of this distribution are:
- A Linux kernel module for flow-based switching, in the
datapath directory.
- ovs-vswitchd, a daemon that implements the virtual switch.
- ovs-dpctl, a tool for configuring the kernel module and
controlling OpenFlow switches.
This distribution includes some additional software as well:
- secchan, a program that implements a simple OpenFlow switch
(without the special features provided by ovs-vswitchd) using
the same kernel module as ovs-vswitchd.
- ovs-controller, a simple OpenFlow switch
- ovs-ofctl, a utility for querying and controlling OpenFlow
switches and controllers.
- vlog-appctl, a utility that can control Open vSwitch daemons,
adjusting their logging levels among other uses.
- ovs-pki, a utility for creating and managing the public-key
infrastructure for OpenFlow switches.
- A patch to tcpdump that enables it to parse OpenFlow
messages.
For installation instructions, read INSTALL. Each userspace program
is also accompanied by a manpage.
Platform support
----------------
Our primary test environment is Debian GNU/Linux. Ports to other
platforms are welcome. Please contact us with portability-related bug
reports or patches.
The testing of the kernel module has focused on version 2.6.18 from
Xen and version 2.6.26 from kernel.org. Linux 2.6 releases from
2.6.15 onward should also work.
GCC is the expected compiler.
Contact
-------
ovs-bugs@openvswitch.org
http://openvswitch.org/

195
acinclude.m4 Normal file
View File

@ -0,0 +1,195 @@
# -*- autoconf -*-
# Copyright (c) 2008, 2009 Nicira Networks.
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
dnl Checks for --disable-userspace.
AC_DEFUN([OVS_CHECK_USERSPACE],
[AC_ARG_ENABLE(
[userspace],
[AC_HELP_STRING([--disable-userspace],
[Disable building userspace components.])],
[case "${enableval}" in
(yes) build_userspace=true ;;
(no) build_userspace=false ;;
(*) AC_MSG_ERROR([bad value ${enableval} for --enable-userspace]) ;;
esac],
[build_userspace=true])
AM_CONDITIONAL([ENABLE_USERSPACE], [$build_userspace])])
dnl OVS_CHECK_LINUX(OPTION, VERSION, VARIABLE, CONDITIONAL)
dnl
dnl Configure linux kernel source tree
AC_DEFUN([OVS_CHECK_LINUX], [
AC_ARG_WITH([$1],
[AC_HELP_STRING([--with-$1=/path/to/linux-$2],
[Specify the linux $2 kernel sources])],
[path="$withval"], [path=])dnl
if test -n "$path"; then
path=`eval echo "$path"`
AC_MSG_CHECKING([for $path directory])
if test -d "$path"; then
AC_MSG_RESULT([yes])
$3=$path
AC_SUBST($3)
else
AC_MSG_RESULT([no])
AC_ERROR([source dir $path doesn't exist])
fi
AC_MSG_CHECKING([for $path kernel version])
patchlevel=`sed -n 's/^PATCHLEVEL = //p' "$path/Makefile"`
sublevel=`sed -n 's/^SUBLEVEL = //p' "$path/Makefile"`
AC_MSG_RESULT([2.$patchlevel.$sublevel])
if test "2.$patchlevel" != '$2'; then
AC_ERROR([Linux kernel source in $path is not version $2])
fi
if ! test -e "$path"/include/linux/version.h || \
! test -e "$path"/include/linux/autoconf.h; then
AC_MSG_ERROR([Linux kernel source in $path is not configured])
fi
m4_if($2, [2.6], [OVS_CHECK_LINUX26_COMPAT])
fi
AM_CONDITIONAL($4, test -n "$path")
])
dnl OVS_GREP_IFELSE(FILE, REGEX, IF-MATCH, IF-NO-MATCH)
dnl
dnl Greps FILE for REGEX. If it matches, runs IF-MATCH, otherwise IF-NO-MATCH.
AC_DEFUN([OVS_GREP_IFELSE], [
AC_MSG_CHECKING([whether $2 matches in $1])
grep '$2' $1 >/dev/null 2>&1
status=$?
case $status in
0)
AC_MSG_RESULT([yes])
$3
;;
1)
AC_MSG_RESULT([no])
$4
;;
*)
AC_MSG_ERROR([grep exited with status $status])
;;
esac
])
dnl OVS_DEFINE(NAME)
dnl
dnl Defines NAME to 1 in kcompat.h.
AC_DEFUN([OVS_DEFINE], [
echo '#define $1 1' >> datapath/linux-2.6/kcompat.h.new
])
AC_DEFUN([OVS_CHECK_VETH], [
AC_MSG_CHECKING([whether to build veth module])
if test "$sublevel" = 18; then
AC_MSG_RESULT([yes])
AC_SUBST([BUILD_VETH], 1)
else
AC_MSG_RESULT([no])
fi
])
AC_DEFUN([OVS_CHECK_LOG2_H], [
AC_MSG_CHECKING([for $KSRC26/include/linux/log2.h])
if test -e $KSRC26/include/linux/log2.h; then
AC_MSG_RESULT([yes])
OVS_DEFINE([HAVE_LOG2_H])
else
AC_MSG_RESULT([no])
fi
])
dnl OVS_CHECK_LINUX26_COMPAT
dnl
dnl Runs various Autoconf checks on the Linux 2.6 kernel source in
dnl the directory in $KSRC26.
AC_DEFUN([OVS_CHECK_LINUX26_COMPAT], [
rm -f datapath/linux-2.6/kcompat.h.new
mkdir -p datapath/linux-2.6
: > datapath/linux-2.6/kcompat.h.new
OVS_GREP_IFELSE([$KSRC26/include/linux/skbuff.h], [skb_transport_header],
[OVS_DEFINE([HAVE_SKBUFF_HEADER_HELPERS])])
OVS_GREP_IFELSE([$KSRC26/include/linux/skbuff.h], [raw],
[OVS_DEFINE([HAVE_MAC_RAW])])
OVS_GREP_IFELSE([$KSRC26/include/linux/skbuff.h],
[skb_copy_from_linear_data_offset],
[OVS_DEFINE([HAVE_SKB_COPY_FROM_LINEAR_DATA_OFFSET])])
OVS_GREP_IFELSE([$KSRC26/include/net/netlink.h], [NLA_NUL_STRING],
[OVS_DEFINE([HAVE_NLA_NUL_STRING])])
OVS_GREP_IFELSE([$KSRC26/include/linux/err.h], [ERR_CAST],
[OVS_DEFINE([HAVE_ERR_CAST])])
OVS_CHECK_LOG2_H
OVS_CHECK_VETH
if cmp -s datapath/linux-2.6/kcompat.h.new \
datapath/linux-2.6/kcompat.h >/dev/null 2>&1; then
rm datapath/linux-2.6/kcompat.h.new
else
mv datapath/linux-2.6/kcompat.h.new datapath/linux-2.6/kcompat.h
fi
])
dnl Checks for net/if_packet.h.
AC_DEFUN([OVS_CHECK_IF_PACKET],
[AC_CHECK_HEADER([net/if_packet.h],
[HAVE_IF_PACKET=yes],
[HAVE_IF_PACKET=no])
AM_CONDITIONAL([HAVE_IF_PACKET], [test "$HAVE_IF_PACKET" = yes])
if test "$HAVE_IF_PACKET" = yes; then
AC_DEFINE([HAVE_IF_PACKET], [1],
[Define to 1 if net/if_packet.h is available.])
fi])
dnl Checks for dpkg-buildpackage. If this is available then we check
dnl that the Debian packaging is functional at "make distcheck" time.
AC_DEFUN([OVS_CHECK_DPKG_BUILDPACKAGE],
[AC_CHECK_PROG([HAVE_DPKG_BUILDPACKAGE], [dpkg-buildpackage], [yes], [no])
AM_CONDITIONAL([HAVE_DPKG_BUILDPACKAGE],
[test $HAVE_DPKG_BUILDPACKAGE = yes])])
dnl ----------------------------------------------------------------------
dnl These macros are from GNU PSPP, with the following original license:
dnl Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
dnl with or without modifications, as long as this notice is preserved.
dnl OVS_CHECK_CC_OPTION([OPTION], [ACTION-IF-ACCEPTED], [ACTION-IF-REJECTED])
dnl Check whether the given C compiler OPTION is accepted.
dnl If so, execute ACTION-IF-ACCEPTED, otherwise ACTION-IF-REJECTED.
AC_DEFUN([OVS_CHECK_CC_OPTION],
[
m4_define([ovs_cv_name], [ovs_cv_[]m4_translit([$1], [-], [_])])dnl
AC_CACHE_CHECK([whether $CC accepts $1], [ovs_cv_name],
[ovs_save_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $1"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,)], [ovs_cv_name[]=yes], [ovs_cv_name[]=no])
CFLAGS="$ovs_save_CFLAGS"])
if test $ovs_cv_name = yes; then
m4_if([$2], [], [;], [$2])
else
m4_if([$3], [], [:], [$3])
fi
])
dnl OVS_ENABLE_OPTION([OPTION])
dnl Check whether the given C compiler OPTION is accepted.
dnl If so, add it to CFLAGS.
dnl Example: OVS_ENABLE_OPTION([-Wdeclaration-after-statement])
AC_DEFUN([OVS_ENABLE_OPTION],
[OVS_CHECK_CC_OPTION([$1], [CFLAGS="$CFLAGS $1"])])
dnl ----------------------------------------------------------------------

2
boot.sh Executable file
View File

@ -0,0 +1,2 @@
#! /bin/sh
autoreconf --install --force

89
configure.ac Normal file
View File

@ -0,0 +1,89 @@
# Copyright (c) 2008, 2009 Nicira Networks
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
AC_PREREQ(2.60)
AC_INIT(openvswitch, 0.90.0, ovs-bugs@openvswitch.org)
NX_BUILDNR
AC_CONFIG_SRCDIR([datapath/datapath.c])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CPP
AC_PROG_RANLIB
AC_PROG_MKDIR_P
AC_ARG_VAR([PERL], [path to Perl interpreter])
AC_PATH_PROG([PERL], perl, no)
if test "$PERL" = no; then
AC_MSG_ERROR([Perl interpreter not found in $PATH or $PERL.])
fi
AC_USE_SYSTEM_EXTENSIONS
AC_C_BIGENDIAN
AC_SYS_LARGEFILE
OVS_CHECK_USERSPACE
OVS_CHECK_NDEBUG
OVS_CHECK_NETLINK
OVS_CHECK_OPENSSL
OVS_CHECK_LOGDIR
OVS_CHECK_CURSES
OVS_CHECK_LINUX_VT_H
OVS_CHECK_PCRE
OVS_CHECK_IF_PACKET
OVS_CHECK_DPKG_BUILDPACKAGE
if $build_userspace; then
OVS_CHECK_PKIDIR
OVS_CHECK_RUNDIR
OVS_CHECK_MALLOC_HOOKS
OVS_CHECK_VALGRIND
OVS_CHECK_TTY_LOCK_DIR
OVS_CHECK_SOCKET_LIBS
OVS_CHECK_FAULT_LIBS
AC_CHECK_FUNCS([strsignal])
OVS_ENABLE_OPTION([-Wall])
OVS_ENABLE_OPTION([-Wno-sign-compare])
OVS_ENABLE_OPTION([-Wpointer-arith])
OVS_ENABLE_OPTION([-Wdeclaration-after-statement])
OVS_ENABLE_OPTION([-Wformat-security])
OVS_ENABLE_OPTION([-Wswitch-enum])
OVS_ENABLE_OPTION([-Wunused-parameter])
OVS_ENABLE_OPTION([-Wstrict-aliasing])
OVS_ENABLE_OPTION([-Wbad-function-cast])
OVS_ENABLE_OPTION([-Wcast-align])
OVS_ENABLE_OPTION([-Wstrict-prototypes])
OVS_ENABLE_OPTION([-Wold-style-definition])
OVS_ENABLE_OPTION([-Wmissing-prototypes])
OVS_ENABLE_OPTION([-Wmissing-field-initializers])
OVS_ENABLE_OPTION([-Wno-override-init])
fi
AC_ARG_VAR(KARCH, [Kernel Architecture String])
AC_SUBST(KARCH)
OVS_CHECK_LINUX(l26, 2.6, KSRC26, L26_ENABLED)
AC_CONFIG_FILES([Makefile
datapath/Makefile
datapath/linux-2.6/Kbuild
datapath/linux-2.6/Makefile
datapath/linux-2.6/Makefile.main])
AC_OUTPUT

7
datapath/.gitignore vendored Normal file
View File

@ -0,0 +1,7 @@
/Makefile
/Makefile.in
*.cmd
*.ko
*.mod.c
Module.symvers

12
datapath/Makefile.am Normal file
View File

@ -0,0 +1,12 @@
SUBDIRS =
if L26_ENABLED
SUBDIRS += linux-2.6
endif
EXTRA_DIST = $(dist_headers) $(dist_sources)
# Suppress warnings about GNU extensions in Modules.mk files.
AUTOMAKE_OPTIONS = -Wno-portability
include Modules.mk
include linux-2.6/Modules.mk

32
datapath/Modules.mk Normal file
View File

@ -0,0 +1,32 @@
# Some modules should be built and distributed, e.g. openvswitch.
#
# Some modules should be distributed but not built, e.g. we do not build
# veth if the kernel in question already has it.
#
# Some modules should be built but not distributed, e.g. third-party
# hwtable modules.
both_modules = openvswitch
build_modules = $(both_modules) # Modules to build
dist_modules = $(both_modules) # Modules to distribute
openvswitch_sources = \
actions.c \
datapath.c \
dp_dev.c \
dp_notify.c \
flow.c \
table.c
openvswitch_headers = \
actions.h \
compat.h \
datapath.h \
dp_dev.h \
flow.h
dist_sources = $(foreach module,$(dist_modules),$($(module)_sources))
dist_headers = $(foreach module,$(dist_modules),$($(module)_headers))
build_sources = $(foreach module,$(build_modules),$($(module)_sources))
build_headers = $(foreach module,$(build_modules),$($(module)_headers))
build_links = $(notdir $(build_sources))
build_objects = $(notdir $(patsubst %.c,%.o,$(build_sources)))

421
datapath/actions.c Normal file
View File

@ -0,0 +1,421 @@
/*
* Distributed under the terms of the GNU GPL version 2.
* Copyright (c) 2007, 2008, 2009 Nicira Networks.
*/
/* Functions for executing flow actions. */
#include <linux/skbuff.h>
#include <linux/in.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/in6.h>
#include <linux/if_vlan.h>
#include <net/ip.h>
#include <net/checksum.h>
#include "datapath.h"
#include "dp_dev.h"
#include "actions.h"
#include "openvswitch/datapath-protocol.h"
struct sk_buff *
make_writable(struct sk_buff *skb, gfp_t gfp)
{
if (skb_shared(skb) || skb_cloned(skb)) {
struct sk_buff *nskb = skb_copy(skb, gfp);
if (nskb) {
kfree_skb(skb);
return nskb;
}
} else {
unsigned int hdr_len = (skb_transport_offset(skb)
+ sizeof(struct tcphdr));
if (pskb_may_pull(skb, min(hdr_len, skb->len)))
return skb;
}
kfree_skb(skb);
return NULL;
}
static struct sk_buff *
vlan_pull_tag(struct sk_buff *skb)
{
struct vlan_ethhdr *vh = vlan_eth_hdr(skb);
struct ethhdr *eh;
/* Verify we were given a vlan packet */
if (vh->h_vlan_proto != htons(ETH_P_8021Q))
return skb;
memmove(skb->data + VLAN_HLEN, skb->data, 2 * VLAN_ETH_ALEN);
eh = (struct ethhdr *)skb_pull(skb, VLAN_HLEN);
skb->protocol = eh->h_proto;
skb->mac_header += VLAN_HLEN;
return skb;
}
static struct sk_buff *
modify_vlan_tci(struct datapath *dp, struct sk_buff *skb,
struct odp_flow_key *key, const union odp_action *a,
int n_actions, gfp_t gfp)
{
u16 tci, mask;
if (a->type == ODPAT_SET_VLAN_VID) {
tci = ntohs(a->vlan_vid.vlan_vid);
mask = VLAN_VID_MASK;
key->dl_vlan = htons(tci & mask);
} else {
tci = a->vlan_pcp.vlan_pcp << 13;
mask = VLAN_PCP_MASK;
}
skb = make_writable(skb, gfp);
if (!skb)
return ERR_PTR(-ENOMEM);
if (skb->protocol == htons(ETH_P_8021Q)) {
/* Modify vlan id, but maintain other TCI values */
struct vlan_ethhdr *vh = vlan_eth_hdr(skb);
vh->h_vlan_TCI = htons((ntohs(vh->h_vlan_TCI) & ~mask) | tci);
} else {
/* Add vlan header */
/* Set up checksumming pointers for checksum-deferred packets
* on Xen. Otherwise, dev_queue_xmit() will try to do this
* when we send the packet out on the wire, and it will fail at
* that point because skb_checksum_setup() will not look inside
* an 802.1Q header. */
skb_checksum_setup(skb);
/* GSO is not implemented for packets with an 802.1Q header, so
* we have to do segmentation before we add that header.
*
* GSO does work with hardware-accelerated VLAN tagging, but we
* can't use hardware-accelerated VLAN tagging since it
* requires the device to have a VLAN group configured (with
* e.g. vconfig(8)) and we don't do that.
*
* Having to do this here may be a performance loss, since we
* can't take advantage of TSO hardware support, although it
* does not make a measurable network performance difference
* for 1G Ethernet. Fixing that would require patching the
* kernel (either to add GSO support to the VLAN protocol or to
* support hardware-accelerated VLAN tagging without VLAN
* groups configured). */
if (skb_is_gso(skb)) {
struct sk_buff *segs;
segs = skb_gso_segment(skb, 0);
kfree_skb(skb);
if (unlikely(IS_ERR(segs)))
return ERR_CAST(segs);
do {
struct sk_buff *nskb = segs->next;
int err;
segs->next = NULL;
segs = __vlan_put_tag(segs, tci);
err = -ENOMEM;
if (segs) {
struct odp_flow_key segkey = *key;
err = execute_actions(dp, segs,
&segkey, a + 1,
n_actions - 1,
gfp);
}
if (unlikely(err)) {
while ((segs = nskb)) {
nskb = segs->next;
segs->next = NULL;
kfree_skb(segs);
}
return ERR_PTR(err);
}
segs = nskb;
} while (segs->next);
skb = segs;
}
/* The hardware-accelerated version of vlan_put_tag() works
* only for a device that has a VLAN group configured (with
* e.g. vconfig(8)), so call the software-only version
* __vlan_put_tag() directly instead.
*/
skb = __vlan_put_tag(skb, tci);
if (!skb)
return ERR_PTR(-ENOMEM);
}
return skb;
}
static struct sk_buff *strip_vlan(struct sk_buff *skb,
struct odp_flow_key *key, gfp_t gfp)
{
skb = make_writable(skb, gfp);
if (skb) {
vlan_pull_tag(skb);
key->dl_vlan = htons(ODP_VLAN_NONE);
}
return skb;
}
static struct sk_buff *set_dl_addr(struct sk_buff *skb,
const struct odp_action_dl_addr *a,
gfp_t gfp)
{
skb = make_writable(skb, gfp);
if (skb) {
struct ethhdr *eh = eth_hdr(skb);
memcpy(a->type == ODPAT_SET_DL_SRC ? eh->h_source : eh->h_dest,
a->dl_addr, ETH_ALEN);
}
return skb;
}
/* Updates 'sum', which is a field in 'skb''s data, given that a 4-byte field
* covered by the sum has been changed from 'from' to 'to'. If set,
* 'pseudohdr' indicates that the field is in the TCP or UDP pseudo-header.
* Based on nf_proto_csum_replace4. */
static void update_csum(__sum16 *sum, struct sk_buff *skb,
__be32 from, __be32 to, int pseudohdr)
{
__be32 diff[] = { ~from, to };
if (skb->ip_summed != CHECKSUM_PARTIAL) {
*sum = csum_fold(csum_partial((char *)diff, sizeof(diff),
~csum_unfold(*sum)));
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
skb->csum = ~csum_partial((char *)diff, sizeof(diff),
~skb->csum);
} else if (pseudohdr)
*sum = ~csum_fold(csum_partial((char *)diff, sizeof(diff),
csum_unfold(*sum)));
}
static struct sk_buff *set_nw_addr(struct sk_buff *skb,
struct odp_flow_key *key,
const struct odp_action_nw_addr *a,
gfp_t gfp)
{
if (key->dl_type != htons(ETH_P_IP))
return skb;
skb = make_writable(skb, gfp);
if (skb) {
struct iphdr *nh = ip_hdr(skb);
u32 *f = a->type == ODPAT_SET_NW_SRC ? &nh->saddr : &nh->daddr;
u32 old = *f;
u32 new = a->nw_addr;
if (key->nw_proto == IPPROTO_TCP) {
struct tcphdr *th = tcp_hdr(skb);
update_csum(&th->check, skb, old, new, 1);
} else if (key->nw_proto == IPPROTO_UDP) {
struct udphdr *th = udp_hdr(skb);
update_csum(&th->check, skb, old, new, 1);
}
update_csum(&nh->check, skb, old, new, 0);
*f = new;
}
return skb;
}
static struct sk_buff *
set_tp_port(struct sk_buff *skb, struct odp_flow_key *key,
const struct odp_action_tp_port *a,
gfp_t gfp)
{
int check_ofs;
if (key->dl_type != htons(ETH_P_IP))
return skb;
if (key->nw_proto == IPPROTO_TCP)
check_ofs = offsetof(struct tcphdr, check);
else if (key->nw_proto == IPPROTO_UDP)
check_ofs = offsetof(struct udphdr, check);
else
return skb;
skb = make_writable(skb, gfp);
if (skb) {
struct udphdr *th = udp_hdr(skb);
u16 *f = a->type == ODPAT_SET_TP_SRC ? &th->source : &th->dest;
u16 old = *f;
u16 new = a->tp_port;
update_csum((u16*)((u8*)skb->data + check_ofs),
skb, old, new, 1);
*f = new;
}
return skb;
}
static inline unsigned packet_length(const struct sk_buff *skb)
{
unsigned length = skb->len - ETH_HLEN;
if (skb->protocol == htons(ETH_P_8021Q))
length -= VLAN_HLEN;
return length;
}
int dp_xmit_skb(struct sk_buff *skb)
{
struct datapath *dp = skb->dev->br_port->dp;
int len = skb->len;
if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) {
printk(KERN_WARNING "%s: dropped over-mtu packet: %d > %d\n",
dp_name(dp), packet_length(skb), skb->dev->mtu);
kfree_skb(skb);
return -E2BIG;
}
dev_queue_xmit(skb);
return len;
}
static void
do_output(struct datapath *dp, struct sk_buff *skb, int out_port)
{
struct net_bridge_port *p;
struct net_device *dev;
if (!skb)
goto error;
p = dp->ports[out_port];
if (!p)
goto error;
dev = skb->dev = p->dev;
if (is_dp_dev(dev))
dp_dev_recv(dev, skb);
else
dp_xmit_skb(skb);
return;
error:
kfree_skb(skb);
}
/* Never consumes 'skb'. Returns a port that 'skb' should be sent to, -1 if
* none. */
static int output_group(struct datapath *dp, __u16 group,
struct sk_buff *skb, gfp_t gfp)
{
struct dp_port_group *g = rcu_dereference(dp->groups[group]);
int prev_port = -1;
int i;
if (!g)
return -1;
for (i = 0; i < g->n_ports; i++) {
struct net_bridge_port *p = dp->ports[g->ports[i]];
if (!p || skb->dev == p->dev)
continue;
if (prev_port != -1) {
struct sk_buff *clone = skb_clone(skb, gfp);
if (!clone)
return -1;
do_output(dp, clone, prev_port);
}
prev_port = p->port_no;
}
return prev_port;
}
static int
output_control(struct datapath *dp, struct sk_buff *skb, u32 arg, gfp_t gfp)
{
skb = skb_clone(skb, gfp);
if (!skb)
return -ENOMEM;
return dp_output_control(dp, skb, _ODPL_ACTION_NR, arg);
}
/* Execute a list of actions against 'skb'. */
int execute_actions(struct datapath *dp, struct sk_buff *skb,
struct odp_flow_key *key,
const union odp_action *a, int n_actions,
gfp_t gfp)
{
/* Every output action needs a separate clone of 'skb', but the common
* case is just a single output action, so that doing a clone and
* then freeing the original skbuff is wasteful. So the following code
* is slightly obscure just to avoid that. */
int prev_port = -1;
int err = 0;
for (; n_actions > 0; a++, n_actions--) {
WARN_ON_ONCE(skb_shared(skb));
if (prev_port != -1) {
do_output(dp, skb_clone(skb, gfp), prev_port);
prev_port = -1;
}
switch (a->type) {
case ODPAT_OUTPUT:
prev_port = a->output.port;
break;
case ODPAT_OUTPUT_GROUP:
prev_port = output_group(dp, a->output_group.group,
skb, gfp);
break;
case ODPAT_CONTROLLER:
err = output_control(dp, skb, a->controller.arg, gfp);
if (err) {
kfree_skb(skb);
return err;
}
break;
case ODPAT_SET_VLAN_VID:
case ODPAT_SET_VLAN_PCP:
skb = modify_vlan_tci(dp, skb, key, a, n_actions, gfp);
if (IS_ERR(skb))
return PTR_ERR(skb);
break;
case ODPAT_STRIP_VLAN:
skb = strip_vlan(skb, key, gfp);
break;
case ODPAT_SET_DL_SRC:
case ODPAT_SET_DL_DST:
skb = set_dl_addr(skb, &a->dl_addr, gfp);
break;
case ODPAT_SET_NW_SRC:
case ODPAT_SET_NW_DST:
skb = set_nw_addr(skb, key, &a->nw_addr, gfp);
break;
case ODPAT_SET_TP_SRC:
case ODPAT_SET_TP_DST:
skb = set_tp_port(skb, key, &a->tp_port, gfp);
break;
}
if (!skb)
return -ENOMEM;
}
if (prev_port != -1)
do_output(dp, skb, prev_port);
else
kfree_skb(skb);
return err;
}

18
datapath/actions.h Normal file
View File

@ -0,0 +1,18 @@
#ifndef ACTIONS_H
#define ACTIONS_H 1
#include <linux/gfp.h>
struct datapath;
struct sk_buff;
struct odp_flow_key;
union odp_action;
struct sk_buff *make_writable(struct sk_buff *, gfp_t gfp);
int dp_xmit_skb(struct sk_buff *);
int execute_actions(struct datapath *dp, struct sk_buff *skb,
struct odp_flow_key *key,
const union odp_action *, int n_actions,
gfp_t gfp);
#endif /* actions.h */

185
datapath/brc_procfs.c Normal file
View File

@ -0,0 +1,185 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <net/genetlink.h>
#include "openvswitch/brcompat-netlink.h"
/* This code implements a Generic Netlink command BRC_GENL_C_SET_PROC that can
* be used to add, modify, and delete arbitrary files in selected
* subdirectories of /proc. It's a horrible kluge prompted by the need to
* simulate certain /proc/net/vlan and /proc/net/bonding files for software
* that wants to read them, and with any luck it will go away eventually.
*
* The implementation is a kluge too. In particular, we want to release the
* strings copied into the 'data' members of proc_dir_entry when the
* proc_dir_entry structures are freed, but there doesn't appear to be a way to
* hook that, so instead we have to rely on being the only entity modifying the
* directories in question.
*/
static int brc_seq_show(struct seq_file *seq, void *unused)
{
seq_puts(seq, seq->private);
return 0;
}
static int brc_seq_open(struct inode *inode, struct file *file)
{
return single_open(file, brc_seq_show, PDE(inode)->data);
}
static struct file_operations brc_fops = {
.owner = THIS_MODULE,
.open = brc_seq_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static struct proc_dir_entry *proc_vlan_dir;
static struct proc_dir_entry *proc_bonding_dir;
struct proc_dir_entry *brc_lookup_entry(struct proc_dir_entry *de, const char *name)
{
int namelen = strlen(name);
for (de = de->subdir; de; de = de->next) {
if (de->namelen != namelen)
continue;
if (!memcmp(name, de->name, de->namelen))
return de;
}
return NULL;
}
static struct proc_dir_entry *brc_open_dir(const char *dir_name,
struct proc_dir_entry *parent,
struct proc_dir_entry **dirp)
{
if (!*dirp) {
struct proc_dir_entry *dir;
if (brc_lookup_entry(parent, dir_name)) {
printk(KERN_WARNING "%s proc directory exists, can't "
"simulate--probably its real module is "
"loaded\n", dir_name);
return NULL;
}
dir = *dirp = proc_mkdir(dir_name, parent);
}
return *dirp;
}
/* Maximum length of the BRC_GENL_A_PROC_DIR and BRC_GENL_A_PROC_NAME strings.
* If we could depend on supporting NLA_NUL_STRING and the .len member in
* Generic Netlink policy, then we could just put this in brc_genl_policy (and
* simplify brc_genl_set_proc() below too), but upstream 2.6.18 does not have
* either. */
#define BRC_NAME_LEN_MAX 32
int brc_genl_set_proc(struct sk_buff *skb, struct genl_info *info)
{
struct proc_dir_entry *dir, *entry;
const char *dir_name, *name;
char *data;
if (!info->attrs[BRC_GENL_A_PROC_DIR] ||
VERIFY_NUL_STRING(info->attrs[BRC_GENL_A_PROC_DIR]) ||
!info->attrs[BRC_GENL_A_PROC_NAME] ||
VERIFY_NUL_STRING(info->attrs[BRC_GENL_A_PROC_NAME]) ||
(info->attrs[BRC_GENL_A_PROC_DATA] &&
VERIFY_NUL_STRING(info->attrs[BRC_GENL_A_PROC_DATA])))
return -EINVAL;
dir_name = nla_data(info->attrs[BRC_GENL_A_PROC_DIR]);
name = nla_data(info->attrs[BRC_GENL_A_PROC_NAME]);
if (strlen(dir_name) > BRC_NAME_LEN_MAX ||
strlen(name) > BRC_NAME_LEN_MAX)
return -EINVAL;
if (!strcmp(dir_name, "net/vlan"))
dir = brc_open_dir("vlan", proc_net, &proc_vlan_dir);
else if (!strcmp(dir_name, "net/bonding"))
dir = brc_open_dir("bonding", proc_net, &proc_bonding_dir);
else
return -EINVAL;
if (!dir) {
/* Probably failed because the module that really implements
* the function in question is loaded and already owns the
* directory in question.*/
return -EBUSY;
}
entry = brc_lookup_entry(dir, name);
if (!info->attrs[BRC_GENL_A_PROC_DATA]) {
if (!entry)
return -ENOENT;
data = entry->data;
remove_proc_entry(name, dir);
if (brc_lookup_entry(dir, name))
return -EBUSY; /* Shouldn't happen */
kfree(data);
} else {
data = kstrdup(nla_data(info->attrs[BRC_GENL_A_PROC_DATA]),
GFP_KERNEL);
if (!data)
return -ENOMEM;
if (entry) {
char *old_data = entry->data;
entry->data = data;
kfree(old_data);
return 0;
}
entry = create_proc_entry(name, S_IFREG|S_IRUSR|S_IWUSR, dir);
if (!entry) {
kfree(data);
return -ENOBUFS;
}
entry->proc_fops = &brc_fops;
entry->data = data;
}
return 0;
}
static void kill_proc_dir(const char *dir_name,
struct proc_dir_entry *parent,
struct proc_dir_entry *dir)
{
if (!dir)
return;
for (;;) {
struct proc_dir_entry *e;
char *data;
char name[BRC_NAME_LEN_MAX + 1];
e = dir->subdir;
if (!e)
break;
if (e->namelen >= sizeof name) {
/* Can't happen: we prevent adding names this long by
* limiting the BRC_GENL_A_PROC_NAME string to
* BRC_NAME_LEN_MAX bytes. */
WARN_ON(1);
break;
}
strcpy(name, e->name);
data = e->data;
e->data = NULL;
kfree(data);
remove_proc_entry(name, dir);
}
remove_proc_entry(dir_name, parent);
}
void brc_procfs_exit(void)
{
kill_proc_dir("vlan", proc_net, proc_vlan_dir);
kill_proc_dir("bonding", proc_net, proc_bonding_dir);
}

11
datapath/brc_procfs.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef BRC_PROCFS_H
#define BRC_PROCFS_H 1
struct sk_buff;
struct genl_info;
void brc_procfs_exit(void);
int brc_genl_set_proc(struct sk_buff *skb, struct genl_info *info);
#endif /* brc_procfs.h */

25
datapath/brc_sysfs.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef BRC_SYSFS_H
#define BRC_SYSFS_H 1
struct datapath;
struct net_bridge_port;
/* brc_sysfs_dp.c */
int brc_sysfs_add_dp(struct datapath *dp);
int brc_sysfs_del_dp(struct datapath *dp);
/* brc_sysfs_if.c */
int brc_sysfs_add_if(struct net_bridge_port *p);
int brc_sysfs_del_if(struct net_bridge_port *p);
#include <linux/version.h>
#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,18)
#define SUPPORT_SYSFS 1
#else
/* We only support sysfs on Linux 2.6.18 because that's the only place we
* really need it (on Xen, for brcompat) and it's a big pain to try to support
* multiple versions. */
#endif
#endif /* brc_sysfs.h */

532
datapath/brc_sysfs_dp.c Normal file
View File

@ -0,0 +1,532 @@
#include <linux/version.h>
/*
* Sysfs attributes of bridge for Open vSwitch
*
* This has been shamelessly copied from the kernel sources.
*/
#include <linux/capability.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
#include <linux/times.h>
#include <linux/version.h>
#include "brc_sysfs.h"
#include "datapath.h"
#include "dp_dev.h"
#ifdef SUPPORT_SYSFS
#define to_dev(obj) container_of(obj, struct device, kobj)
/* Hack to attempt to build on more platforms. */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21)
#define to_kobj(d) &(d)->class_dev.kobj
#define BRC_DEVICE_ATTR CLASS_DEVICE_ATTR
#else
#define to_kobj(d) &(d)->dev.kobj
#define BRC_DEVICE_ATTR DEVICE_ATTR
#endif
/*
* Common code for storing bridge parameters.
*/
static ssize_t store_bridge_parm(struct class_device *d,
const char *buf, size_t len,
void (*set)(struct datapath *, unsigned long))
{
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
char *endp;
unsigned long val;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
val = simple_strtoul(buf, &endp, 0);
if (endp == buf)
return -EINVAL;
#if 0
spin_lock_bh(&br->lock);
(*set)(br, val);
spin_unlock_bh(&br->lock);
#else
/* xxx We use a default value of 0 for all fields. If the caller is
* xxx attempting to set the value to our default, just silently
* xxx ignore the request.
*/
if (val != 0) {
printk("%s: xxx writing dp parms not supported yet!\n",
dp_name(dp));
}
#endif
return len;
}
static ssize_t show_forward_delay(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static void set_forward_delay(struct datapath *dp, unsigned long val)
{
#if 0
unsigned long delay = clock_t_to_jiffies(val);
br->forward_delay = delay;
if (br_is_root_bridge(br))
br->bridge_forward_delay = delay;
#else
printk("%s: xxx attempt to set_forward_delay()\n", dp_name(dp));
#endif
}
static ssize_t store_forward_delay(struct class_device *d,
const char *buf, size_t len)
{
return store_bridge_parm(d, buf, len, set_forward_delay);
}
static BRC_DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR,
show_forward_delay, store_forward_delay);
static ssize_t show_hello_time(struct class_device *d, char *buf)
{
#if 0
return sprintf(buf, "%lu\n",
jiffies_to_clock_t(to_bridge(d)->hello_time));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static void set_hello_time(struct datapath *dp, unsigned long val)
{
#if 0
unsigned long t = clock_t_to_jiffies(val);
br->hello_time = t;
if (br_is_root_bridge(br))
br->bridge_hello_time = t;
#else
printk("%s: xxx attempt to set_hello_time()\n", dp_name(dp));
#endif
}
static ssize_t store_hello_time(struct class_device *d,
const char *buf,
size_t len)
{
return store_bridge_parm(d, buf, len, set_hello_time);
}
static BRC_DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time,
store_hello_time);
static ssize_t show_max_age(struct class_device *d,
char *buf)
{
#if 0
return sprintf(buf, "%lu\n",
jiffies_to_clock_t(to_bridge(d)->max_age));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static void set_max_age(struct datapath *dp, unsigned long val)
{
#if 0
unsigned long t = clock_t_to_jiffies(val);
br->max_age = t;
if (br_is_root_bridge(br))
br->bridge_max_age = t;
#else
printk("%s: xxx attempt to set_max_age()\n", dp_name(dp));
#endif
}
static ssize_t store_max_age(struct class_device *d,
const char *buf, size_t len)
{
return store_bridge_parm(d, buf, len, set_max_age);
}
static BRC_DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age);
static ssize_t show_ageing_time(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->ageing_time));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static void set_ageing_time(struct datapath *dp, unsigned long val)
{
#if 0
br->ageing_time = clock_t_to_jiffies(val);
#else
printk("%s: xxx attempt to set_ageing_time()\n", dp_name(dp));
#endif
}
static ssize_t store_ageing_time(struct class_device *d,
const char *buf, size_t len)
{
return store_bridge_parm(d, buf, len, set_ageing_time);
}
static BRC_DEVICE_ATTR(ageing_time, S_IRUGO | S_IWUSR, show_ageing_time,
store_ageing_time);
static ssize_t show_stp_state(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%d\n", br->stp_enabled);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static ssize_t store_stp_state(struct class_device *d,
const char *buf,
size_t len)
{
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
#if 0
char *endp;
unsigned long val;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
val = simple_strtoul(buf, &endp, 0);
if (endp == buf)
return -EINVAL;
rtnl_lock();
br_stp_set_enabled(br, val);
rtnl_unlock();
#else
printk("%s: xxx attempt to set_stp_state()\n", dp_name(dp));
#endif
return len;
}
static BRC_DEVICE_ATTR(stp_state, S_IRUGO | S_IWUSR, show_stp_state,
store_stp_state);
static ssize_t show_priority(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%d\n",
(br->bridge_id.prio[0] << 8) | br->bridge_id.prio[1]);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static void set_priority(struct datapath *dp, unsigned long val)
{
#if 0
br_stp_set_bridge_priority(br, (u16) val);
#else
printk("%s: xxx attempt to set_priority()\n", dp_name(dp));
#endif
}
static ssize_t store_priority(struct class_device *d,
const char *buf, size_t len)
{
return store_bridge_parm(d, buf, len, set_priority);
}
static BRC_DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, show_priority, store_priority);
static ssize_t show_root_id(struct class_device *d,
char *buf)
{
#if 0
return br_show_bridge_id(buf, &to_bridge(d)->designated_root);
#else
return sprintf(buf, "0000.010203040506\n");
#endif
}
static BRC_DEVICE_ATTR(root_id, S_IRUGO, show_root_id, NULL);
static ssize_t show_bridge_id(struct class_device *d,
char *buf)
{
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
const unsigned char *addr = dp->ports[ODPP_LOCAL]->dev->dev_addr;
/* xxx Do we need a lock of some sort? */
return sprintf(buf, "%.2x%.2x.%.2x%.2x%.2x%.2x%.2x%.2x\n",
0, 0, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
}
static BRC_DEVICE_ATTR(bridge_id, S_IRUGO, show_bridge_id, NULL);
static ssize_t show_root_port(struct class_device *d,
char *buf)
{
#if 0
return sprintf(buf, "%d\n", to_bridge(d)->root_port);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(root_port, S_IRUGO, show_root_port, NULL);
static ssize_t show_root_path_cost(struct class_device *d,
char *buf)
{
#if 0
return sprintf(buf, "%d\n", to_bridge(d)->root_path_cost);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(root_path_cost, S_IRUGO, show_root_path_cost, NULL);
static ssize_t show_topology_change(struct class_device *d,
char *buf)
{
#if 0
return sprintf(buf, "%d\n", to_bridge(d)->topology_change);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(topology_change, S_IRUGO, show_topology_change, NULL);
static ssize_t show_topology_change_detected(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%d\n", br->topology_change_detected);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(topology_change_detected, S_IRUGO,
show_topology_change_detected, NULL);
static ssize_t show_hello_timer(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%ld\n", br_timer_value(&br->hello_timer));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(hello_timer, S_IRUGO, show_hello_timer, NULL);
static ssize_t show_tcn_timer(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%ld\n", br_timer_value(&br->tcn_timer));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(tcn_timer, S_IRUGO, show_tcn_timer, NULL);
static ssize_t show_topology_change_timer(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%ld\n", br_timer_value(&br->topology_change_timer));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(topology_change_timer, S_IRUGO, show_topology_change_timer,
NULL);
static ssize_t show_gc_timer(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%ld\n", br_timer_value(&br->gc_timer));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRC_DEVICE_ATTR(gc_timer, S_IRUGO, show_gc_timer, NULL);
static ssize_t show_group_addr(struct class_device *d,
char *buf)
{
#if 0
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
return sprintf(buf, "%x:%x:%x:%x:%x:%x\n",
br->group_addr[0], br->group_addr[1],
br->group_addr[2], br->group_addr[3],
br->group_addr[4], br->group_addr[5]);
#else
return sprintf(buf, "00:01:02:03:04:05\n");
#endif
}
static ssize_t store_group_addr(struct class_device *d,
const char *buf, size_t len)
{
struct datapath *dp = dp_dev_get_dp(to_net_dev(d));
#if 0
unsigned new_addr[6];
int i;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
if (sscanf(buf, "%x:%x:%x:%x:%x:%x",
&new_addr[0], &new_addr[1], &new_addr[2],
&new_addr[3], &new_addr[4], &new_addr[5]) != 6)
return -EINVAL;
/* Must be 01:80:c2:00:00:0X */
for (i = 0; i < 5; i++)
if (new_addr[i] != br_group_address[i])
return -EINVAL;
if (new_addr[5] & ~0xf)
return -EINVAL;
if (new_addr[5] == 1 /* 802.3x Pause address */
|| new_addr[5] == 2 /* 802.3ad Slow protocols */
|| new_addr[5] == 3) /* 802.1X PAE address */
return -EINVAL;
spin_lock_bh(&br->lock);
for (i = 0; i < 6; i++)
br->group_addr[i] = new_addr[i];
spin_unlock_bh(&br->lock);
#else
printk("%s: xxx attempt to store_group_addr()\n", dp_name(dp));
#endif
return len;
}
static BRC_DEVICE_ATTR(group_addr, S_IRUGO | S_IWUSR,
show_group_addr, store_group_addr);
static struct attribute *bridge_attrs[] = {
&class_device_attr_forward_delay.attr,
&class_device_attr_hello_time.attr,
&class_device_attr_max_age.attr,
&class_device_attr_ageing_time.attr,
&class_device_attr_stp_state.attr,
&class_device_attr_priority.attr,
&class_device_attr_bridge_id.attr,
&class_device_attr_root_id.attr,
&class_device_attr_root_path_cost.attr,
&class_device_attr_root_port.attr,
&class_device_attr_topology_change.attr,
&class_device_attr_topology_change_detected.attr,
&class_device_attr_hello_timer.attr,
&class_device_attr_tcn_timer.attr,
&class_device_attr_topology_change_timer.attr,
&class_device_attr_gc_timer.attr,
&class_device_attr_group_addr.attr,
NULL
};
static struct attribute_group bridge_group = {
.name = SYSFS_BRIDGE_ATTR,
.attrs = bridge_attrs,
};
/*
* Add entries in sysfs onto the existing network class device
* for the bridge.
* Adds a attribute group "bridge" containing tuning parameters.
* Sub directory to hold links to interfaces.
*
* Note: the ifobj exists only to be a subdirectory
* to hold links. The ifobj exists in the same data structure
* as its parent the bridge so reference counting works.
*/
int brc_sysfs_add_dp(struct datapath *dp)
{
struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
int err;
err = sysfs_create_group(kobj, &bridge_group);
if (err) {
pr_info("%s: can't create group %s/%s\n",
__func__, dp_name(dp), bridge_group.name);
goto out1;
}
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
kobject_set_name(&dp->ifobj, SYSFS_BRIDGE_PORT_SUBDIR);
dp->ifobj.ktype = NULL;
dp->ifobj.kset = NULL;
dp->ifobj.parent = kobj;
err = kobject_register(&dp->ifobj);
if (err) {
pr_info("%s: can't add kobject (directory) %s/%s\n",
__FUNCTION__, dp_name(dp), dp->ifobj.name);
goto out2;
}
#else
br->ifobj = kobject_create_and_add(SYSFS_BRIDGE_PORT_SUBDIR, kobj);
if (!br->ifobj) {
pr_info("%s: can't add kobject (directory) %s/%s\n",
__func__, dp_name(dp), SYSFS_BRIDGE_PORT_SUBDIR);
goto out2;
}
#endif
return 0;
out2:
sysfs_remove_group(kobj, &bridge_group);
out1:
return err;
}
int brc_sysfs_del_dp(struct datapath *dp)
{
struct kobject *kobj = to_kobj(dp->ports[ODPP_LOCAL]->dev);
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
kobject_unregister(&dp->ifobj);
#else
kobject_put(dp->ifobj);
#endif
sysfs_remove_group(kobj, &bridge_group);
return 0;
}
#else /* !SUPPORT_SYSFS */
int brc_sysfs_add_dp(struct datapath *dp) { return 0; }
int brc_sysfs_del_dp(struct datapath *dp) { return 0; }
int brc_sysfs_add_if(struct net_bridge_port *p) { return 0; }
int brc_sysfs_del_if(struct net_bridge_port *p)
{
dev_put(p->dev);
kfree(p);
return 0;
}
#endif /* !SUPPORT_SYSFS */

334
datapath/brc_sysfs_if.c Normal file
View File

@ -0,0 +1,334 @@
/*
* Sysfs attributes of bridge ports for Open vSwitch
*
* This has been shamelessly copied from the kernel sources.
*/
#include <linux/capability.h>
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
#include "brc_sysfs.h"
#include "datapath.h"
#ifdef SUPPORT_SYSFS
struct brport_attribute {
struct attribute attr;
ssize_t (*show)(struct net_bridge_port *, char *);
ssize_t (*store)(struct net_bridge_port *, unsigned long);
};
#define BRPORT_ATTR(_name,_mode,_show,_store) \
struct brport_attribute brport_attr_##_name = { \
.attr = {.name = __stringify(_name), \
.mode = _mode, \
.owner = THIS_MODULE, }, \
.show = _show, \
.store = _store, \
};
static ssize_t show_path_cost(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "%d\n", p->path_cost);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v)
{
#if 0
br_stp_set_path_cost(p, v);
#endif
return 0;
}
static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR,
show_path_cost, store_path_cost);
static ssize_t show_priority(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "%d\n", p->priority);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static ssize_t store_priority(struct net_bridge_port *p, unsigned long v)
{
#if 0
if (v >= (1<<(16-BR_PORT_BITS)))
return -ERANGE;
br_stp_set_port_priority(p, v);
#endif
return 0;
}
static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR,
show_priority, store_priority);
static ssize_t show_designated_root(struct net_bridge_port *p, char *buf)
{
#if 0
return br_show_bridge_id(buf, &p->designated_root);
#else
return sprintf(buf, "0000.010203040506\n");
#endif
}
static BRPORT_ATTR(designated_root, S_IRUGO, show_designated_root, NULL);
static ssize_t show_designated_bridge(struct net_bridge_port *p, char *buf)
{
#if 0
return br_show_bridge_id(buf, &p->designated_bridge);
#else
return sprintf(buf, "0000.060504030201\n");
#endif
}
static BRPORT_ATTR(designated_bridge, S_IRUGO, show_designated_bridge, NULL);
static ssize_t show_designated_port(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "%d\n", p->designated_port);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(designated_port, S_IRUGO, show_designated_port, NULL);
static ssize_t show_designated_cost(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "%d\n", p->designated_cost);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(designated_cost, S_IRUGO, show_designated_cost, NULL);
static ssize_t show_port_id(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "0x%x\n", p->port_id);
#else
return sprintf(buf, "0x%x\n", 0);
#endif
}
static BRPORT_ATTR(port_id, S_IRUGO, show_port_id, NULL);
static ssize_t show_port_no(struct net_bridge_port *p, char *buf)
{
return sprintf(buf, "0x%x\n", p->port_no);
}
static BRPORT_ATTR(port_no, S_IRUGO, show_port_no, NULL);
static ssize_t show_change_ack(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "%d\n", p->topology_change_ack);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(change_ack, S_IRUGO, show_change_ack, NULL);
static ssize_t show_config_pending(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "%d\n", p->config_pending);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(config_pending, S_IRUGO, show_config_pending, NULL);
static ssize_t show_port_state(struct net_bridge_port *p, char *buf)
{
#if 0
return sprintf(buf, "%d\n", p->state);
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(state, S_IRUGO, show_port_state, NULL);
static ssize_t show_message_age_timer(struct net_bridge_port *p,
char *buf)
{
#if 0
return sprintf(buf, "%ld\n", br_timer_value(&p->message_age_timer));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(message_age_timer, S_IRUGO, show_message_age_timer, NULL);
static ssize_t show_forward_delay_timer(struct net_bridge_port *p,
char *buf)
{
#if 0
return sprintf(buf, "%ld\n", br_timer_value(&p->forward_delay_timer));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(forward_delay_timer, S_IRUGO, show_forward_delay_timer, NULL);
static ssize_t show_hold_timer(struct net_bridge_port *p,
char *buf)
{
#if 0
return sprintf(buf, "%ld\n", br_timer_value(&p->hold_timer));
#else
return sprintf(buf, "%d\n", 0);
#endif
}
static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL);
static struct brport_attribute *brport_attrs[] = {
&brport_attr_path_cost,
&brport_attr_priority,
&brport_attr_port_id,
&brport_attr_port_no,
&brport_attr_designated_root,
&brport_attr_designated_bridge,
&brport_attr_designated_port,
&brport_attr_designated_cost,
&brport_attr_state,
&brport_attr_change_ack,
&brport_attr_config_pending,
&brport_attr_message_age_timer,
&brport_attr_forward_delay_timer,
&brport_attr_hold_timer,
NULL
};
#define to_brport_attr(_at) container_of(_at, struct brport_attribute, attr)
#define to_brport(obj) container_of(obj, struct net_bridge_port, kobj)
static ssize_t brport_show(struct kobject * kobj,
struct attribute * attr, char * buf)
{
struct brport_attribute * brport_attr = to_brport_attr(attr);
struct net_bridge_port * p = to_brport(kobj);
return brport_attr->show(p, buf);
}
static ssize_t brport_store(struct kobject * kobj,
struct attribute * attr,
const char * buf, size_t count)
{
struct net_bridge_port * p = to_brport(kobj);
#if 0
struct brport_attribute * brport_attr = to_brport_attr(attr);
char *endp;
unsigned long val;
#endif
ssize_t ret = -EINVAL;
if (!capable(CAP_NET_ADMIN))
return -EPERM;
#if 0
val = simple_strtoul(buf, &endp, 0);
if (endp != buf) {
rtnl_lock();
if (p->dev && p->br && brport_attr->store) {
spin_lock_bh(&p->br->lock);
ret = brport_attr->store(p, val);
spin_unlock_bh(&p->br->lock);
if (ret == 0)
ret = count;
}
rtnl_unlock();
}
#else
printk("%s: xxx writing port parms not supported yet!\n",
dp_name(p->dp));
#endif
return ret;
}
struct sysfs_ops brport_sysfs_ops = {
.show = brport_show,
.store = brport_store,
};
static void release_nbp(struct kobject *kobj)
{
struct net_bridge_port *p
= container_of(kobj, struct net_bridge_port, kobj);
kfree(p);
}
struct kobj_type brport_ktype = {
.sysfs_ops = &brport_sysfs_ops,
.release = release_nbp
};
/*
* Add sysfs entries to ethernet device added to a bridge.
* Creates a brport subdirectory with bridge attributes.
* Puts symlink in bridge's brport subdirectory
*/
int brc_sysfs_add_if(struct net_bridge_port *p)
{
struct datapath *dp = p->dp;
struct brport_attribute **a;
int err;
kobject_init(&p->kobj);
kobject_set_name(&p->kobj, SYSFS_BRIDGE_PORT_ATTR);
p->kobj.ktype = &brport_ktype;
p->kobj.kset = NULL;
p->kobj.parent = &(p->dev->class_dev.kobj);
err = kobject_add(&p->kobj);
if (err)
goto err_put;
err = sysfs_create_link(&p->kobj,
&dp->ports[ODPP_LOCAL]->dev->class_dev.kobj,
SYSFS_BRIDGE_PORT_LINK);
if (err)
goto err_del;
for (a = brport_attrs; *a; ++a) {
err = sysfs_create_file(&p->kobj, &((*a)->attr));
if (err)
goto err_del;
}
err = sysfs_create_link(&dp->ifobj, &p->kobj, p->dev->name);
if (err)
goto err_del;
kobject_uevent(&p->kobj, KOBJ_ADD);
return err;
err_del:
kobject_del(&p->kobj);
err_put:
kobject_put(&p->kobj);
return err;
}
int brc_sysfs_del_if(struct net_bridge_port *p)
{
struct net_device *dev = p->dev;
kobject_uevent(&p->kobj, KOBJ_REMOVE);
kobject_del(&p->kobj);
dev_put(dev);
kobject_put(&p->kobj);
return 0;
}
#endif /* SUPPORT_SYSFS */

519
datapath/brcompat.c Normal file
View File

@ -0,0 +1,519 @@
#include <linux/kernel.h>
#include <asm/uaccess.h>
#include <linux/completion.h>
#include <linux/delay.h>
#include <linux/etherdevice.h>
#include <linux/if_bridge.h>
#include <linux/rculist.h>
#include <linux/netdevice.h>
#include <linux/rtnetlink.h>
#include <net/genetlink.h>
#include "compat.h"
#include "openvswitch/brcompat-netlink.h"
#include "brc_procfs.h"
#include "brc_sysfs.h"
#include "datapath.h"
#include "dp_dev.h"
static struct genl_family brc_genl_family;
static struct genl_multicast_group brc_mc_group;
/* Time to wait for ovs-vswitchd to respond to a datapath action, in
* jiffies. */
#define BRC_TIMEOUT (HZ * 5)
/* Mutex to serialize ovs-brcompatd callbacks. (Some callbacks naturally hold
* br_ioctl_mutex, others hold rtnl_lock, but we can't take the former
* ourselves and we don't want to hold the latter over a potentially long
* period of time.) */
static DEFINE_MUTEX(brc_serial);
/* Userspace communication. */
static DEFINE_SPINLOCK(brc_lock); /* Ensure atomic access to these vars. */
static DECLARE_COMPLETION(brc_done); /* Userspace signaled operation done? */
static int brc_err; /* Error code from userspace. */
static u32 brc_seq; /* Sequence number for current op. */
static int brc_send_command(const char *bridge, const char *port, int op);
static int
get_dp_ifindices(int *indices, int num)
{
int i, index = 0;
rcu_read_lock();
for (i=0; i < ODP_MAX && index < num; i++) {
struct datapath *dp = get_dp(i);
if (!dp)
continue;
indices[index++] = dp->ports[ODPP_LOCAL]->dev->ifindex;
}
rcu_read_unlock();
return index;
}
static void
get_port_ifindices(struct datapath *dp, int *ifindices, int num)
{
struct net_bridge_port *p;
rcu_read_lock();
list_for_each_entry_rcu (p, &dp->port_list, node) {
if (p->port_no < num)
ifindices[p->port_no] = p->dev->ifindex;
}
rcu_read_unlock();
}
static int brc_add_del_bridge(char __user *uname, int add)
{
char name[IFNAMSIZ];
if (copy_from_user(name, uname, IFNAMSIZ))
return -EFAULT;
name[IFNAMSIZ - 1] = 0;
return brc_send_command(name, NULL,
add ? BRC_GENL_C_DP_ADD : BRC_GENL_C_DP_DEL);
}
static int brc_get_bridges(int __user *uindices, int n)
{
int *indices;
int ret;
if (n >= 2048)
return -ENOMEM;
indices = kcalloc(n, sizeof(int), GFP_KERNEL);
if (indices == NULL)
return -ENOMEM;
n = get_dp_ifindices(indices, n);
ret = copy_to_user(uindices, indices, n * sizeof(int)) ? -EFAULT : n;
kfree(indices);
return ret;
}
/* Legacy deviceless bridge ioctl's. Called with br_ioctl_mutex. */
static int
old_deviceless(void __user *uarg)
{
unsigned long args[3];
if (copy_from_user(args, uarg, sizeof(args)))
return -EFAULT;
switch (args[0]) {
case BRCTL_GET_BRIDGES:
return brc_get_bridges((int __user *)args[1], args[2]);
case BRCTL_ADD_BRIDGE:
return brc_add_del_bridge((void __user *)args[1], 1);
case BRCTL_DEL_BRIDGE:
return brc_add_del_bridge((void __user *)args[1], 0);
}
return -EOPNOTSUPP;
}
/* Called with the br_ioctl_mutex. */
static int
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
brc_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)
#else
brc_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
#endif
{
switch (cmd) {
case SIOCGIFBR:
case SIOCSIFBR:
return old_deviceless(uarg);
case SIOCBRADDBR:
return brc_add_del_bridge(uarg, 1);
case SIOCBRDELBR:
return brc_add_del_bridge(uarg, 0);
}
return -EOPNOTSUPP;
}
static int
brc_add_del_port(struct net_device *dev, int port_ifindex, int add)
{
struct net_device *port;
char dev_name[IFNAMSIZ], port_name[IFNAMSIZ];
int err;
port = __dev_get_by_index(&init_net, port_ifindex);
if (!port)
return -EINVAL;
/* Save name of dev and port because there's a race between the
* rtnl_unlock() and the brc_send_command(). */
strcpy(dev_name, dev->name);
strcpy(port_name, port->name);
rtnl_unlock();
err = brc_send_command(dev_name, port_name,
add ? BRC_GENL_C_PORT_ADD : BRC_GENL_C_PORT_DEL);
rtnl_lock();
return err;
}
static int
brc_get_bridge_info(struct net_device *dev, struct __bridge_info __user *ub)
{
struct __bridge_info b;
u64 id = 0;
int i;
memset(&b, 0, sizeof(struct __bridge_info));
for (i=0; i<ETH_ALEN; i++)
id |= (u64)dev->dev_addr[i] << (8*(ETH_ALEN-1 - i));
b.bridge_id = cpu_to_be64(id);
b.stp_enabled = 0;
if (copy_to_user(ub, &b, sizeof(struct __bridge_info)))
return -EFAULT;
return 0;
}
static int
brc_get_port_list(struct net_device *dev, int __user *uindices, int num)
{
struct dp_dev *dp_dev = netdev_priv(dev);
struct datapath *dp = dp_dev->dp;
int *indices;
if (num < 0)
return -EINVAL;
if (num == 0)
num = 256;
if (num > DP_MAX_PORTS)
num = DP_MAX_PORTS;
indices = kcalloc(num, sizeof(int), GFP_KERNEL);
if (indices == NULL)
return -ENOMEM;
get_port_ifindices(dp, indices, num);
if (copy_to_user(uindices, indices, num * sizeof(int)))
num = -EFAULT;
kfree(indices);
return num;
}
/* Legacy ioctl's through SIOCDEVPRIVATE. Called with rtnl_lock. */
static int
old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
unsigned long args[4];
if (copy_from_user(args, rq->ifr_data, sizeof(args)))
return -EFAULT;
switch (args[0]) {
case BRCTL_ADD_IF:
return brc_add_del_port(dev, args[1], 1);
case BRCTL_DEL_IF:
return brc_add_del_port(dev, args[1], 0);
case BRCTL_GET_BRIDGE_INFO:
return brc_get_bridge_info(dev, (struct __bridge_info __user *)args[1]);
case BRCTL_GET_PORT_LIST:
return brc_get_port_list(dev, (int __user *)args[1], args[2]);
}
return -EOPNOTSUPP;
}
/* Called with the rtnl_lock. */
static int
brc_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
int err;
switch (cmd) {
case SIOCDEVPRIVATE:
err = old_dev_ioctl(dev, rq, cmd);
break;
case SIOCBRADDIF:
return brc_add_del_port(dev, rq->ifr_ifindex, 1);
case SIOCBRDELIF:
return brc_add_del_port(dev, rq->ifr_ifindex, 0);
default:
err = -EOPNOTSUPP;
break;
}
return err;
}
static struct genl_family brc_genl_family = {
.id = GENL_ID_GENERATE,
.hdrsize = 0,
.name = BRC_GENL_FAMILY_NAME,
.version = 1,
.maxattr = BRC_GENL_A_MAX,
};
static int brc_genl_query(struct sk_buff *skb, struct genl_info *info)
{
int err = -EINVAL;
struct sk_buff *ans_skb;
void *data;
ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!ans_skb)
return -ENOMEM;
data = genlmsg_put_reply(ans_skb, info, &brc_genl_family,
0, BRC_GENL_C_QUERY_MC);
if (data == NULL) {
err = -ENOMEM;
goto err;
}
NLA_PUT_U32(ans_skb, BRC_GENL_A_MC_GROUP, brc_mc_group.id);
genlmsg_end(ans_skb, data);
return genlmsg_reply(ans_skb, info);
err:
nla_put_failure:
kfree_skb(ans_skb);
return err;
}
static struct genl_ops brc_genl_ops_query_dp = {
.cmd = BRC_GENL_C_QUERY_MC,
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
.policy = NULL,
.doit = brc_genl_query,
.dumpit = NULL
};
/* Attribute policy: what each attribute may contain. */
static struct nla_policy brc_genl_policy[BRC_GENL_A_MAX + 1] = {
[BRC_GENL_A_ERR_CODE] = { .type = NLA_U32 },
[BRC_GENL_A_PROC_DIR] = { .type = NLA_NUL_STRING },
[BRC_GENL_A_PROC_NAME] = { .type = NLA_NUL_STRING },
[BRC_GENL_A_PROC_DATA] = { .type = NLA_NUL_STRING },
};
static int
brc_genl_dp_result(struct sk_buff *skb, struct genl_info *info)
{
unsigned long int flags;
int err;
if (!info->attrs[BRC_GENL_A_ERR_CODE])
return -EINVAL;
spin_lock_irqsave(&brc_lock, flags);
if (brc_seq == info->snd_seq) {
brc_err = nla_get_u32(info->attrs[BRC_GENL_A_ERR_CODE]);
complete(&brc_done);
err = 0;
} else {
err = -ESTALE;
}
spin_unlock_irqrestore(&brc_lock, flags);
return err;
}
static struct genl_ops brc_genl_ops_dp_result = {
.cmd = BRC_GENL_C_DP_RESULT,
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
.policy = brc_genl_policy,
.doit = brc_genl_dp_result,
.dumpit = NULL
};
static struct genl_ops brc_genl_ops_set_proc = {
.cmd = BRC_GENL_C_SET_PROC,
.flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privelege. */
.policy = brc_genl_policy,
.doit = brc_genl_set_proc,
.dumpit = NULL
};
static int brc_send_command(const char *bridge, const char *port, int op)
{
unsigned long int flags;
struct sk_buff *skb;
void *data;
int error;
mutex_lock(&brc_serial);
/* Increment sequence number first, so that we ignore any replies
* to stale requests. */
spin_lock_irqsave(&brc_lock, flags);
brc_seq++;
INIT_COMPLETION(brc_done);
spin_unlock_irqrestore(&brc_lock, flags);
/* Compose message. */
skb = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
error = -ENOMEM;
if (skb == NULL)
goto exit_unlock;
data = genlmsg_put(skb, 0, brc_seq, &brc_genl_family, 0, op);
NLA_PUT_STRING(skb, BRC_GENL_A_DP_NAME, bridge);
if (port)
NLA_PUT_STRING(skb, BRC_GENL_A_PORT_NAME, port);
genlmsg_end(skb, data);
/* Send message. */
error = genlmsg_multicast(skb, 0, brc_mc_group.id, GFP_KERNEL);
if (error < 0)
goto exit_unlock;
/* Wait for reply. */
error = -ETIMEDOUT;
if (!wait_for_completion_timeout(&brc_done, BRC_TIMEOUT))
goto exit_unlock;
error = -brc_err;
goto exit_unlock;
nla_put_failure:
kfree_skb(skb);
exit_unlock:
mutex_unlock(&brc_serial);
return error;
}
int brc_add_dp(struct datapath *dp)
{
if (!try_module_get(THIS_MODULE))
return -ENODEV;
#ifdef SUPPORT_SYSFS
brc_sysfs_add_dp(dp);
#endif
return 0;
}
int brc_del_dp(struct datapath *dp)
{
#ifdef SUPPORT_SYSFS
brc_sysfs_del_dp(dp);
#endif
module_put(THIS_MODULE);
return 0;
}
static int
__init brc_init(void)
{
int i;
int err;
printk("Open vSwitch Bridge Compatibility, built "__DATE__" "__TIME__"\n");
rcu_read_lock();
for (i=0; i<ODP_MAX; i++) {
if (get_dp(i)) {
rcu_read_unlock();
printk(KERN_EMERG "brcompat: no datapaths may exist!\n");
return -EEXIST;
}
}
rcu_read_unlock();
/* Set the bridge ioctl handler */
brioctl_set(brc_ioctl_deviceless_stub);
/* Set the openvswitch_mod device ioctl handler */
dp_ioctl_hook = brc_dev_ioctl;
/* Register hooks for datapath adds and deletes */
dp_add_dp_hook = brc_add_dp;
dp_del_dp_hook = brc_del_dp;
/* Register hooks for interface adds and deletes */
#ifdef SUPPORT_SYSFS
dp_add_if_hook = brc_sysfs_add_if;
dp_del_if_hook = brc_sysfs_del_if;
#endif
/* Randomize the initial sequence number. This is not a security
* feature; it only helps avoid crossed wires between userspace and
* the kernel when the module is unloaded and reloaded. */
brc_seq = net_random();
/* Register generic netlink family to communicate changes to
* userspace. */
err = genl_register_family(&brc_genl_family);
if (err)
goto error;
err = genl_register_ops(&brc_genl_family, &brc_genl_ops_query_dp);
if (err != 0)
goto err_unregister;
err = genl_register_ops(&brc_genl_family, &brc_genl_ops_dp_result);
if (err != 0)
goto err_unregister;
err = genl_register_ops(&brc_genl_family, &brc_genl_ops_set_proc);
if (err != 0)
goto err_unregister;
strcpy(brc_mc_group.name, "brcompat");
err = genl_register_mc_group(&brc_genl_family, &brc_mc_group);
if (err < 0)
goto err_unregister;
return 0;
err_unregister:
genl_unregister_family(&brc_genl_family);
error:
printk(KERN_EMERG "brcompat: failed to install!");
return err;
}
static void
brc_cleanup(void)
{
/* Unregister hooks for datapath adds and deletes */
dp_add_dp_hook = NULL;
dp_del_dp_hook = NULL;
/* Unregister hooks for interface adds and deletes */
dp_add_if_hook = NULL;
dp_del_if_hook = NULL;
/* Unregister ioctl hooks */
dp_ioctl_hook = NULL;
brioctl_set(NULL);
genl_unregister_family(&brc_genl_family);
brc_procfs_exit();
}
module_init(brc_init);
module_exit(brc_cleanup);
MODULE_DESCRIPTION("Open vSwitch bridge compatibility");
MODULE_AUTHOR("Nicira Networks");
MODULE_LICENSE("GPL");

17
datapath/compat.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef COMPAT_H
#define COMPAT_H 1
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include "compat26.h"
#else
#include "compat24.h"
#endif
#endif /* compat.h */

1611
datapath/datapath.c Normal file

File diff suppressed because it is too large Load Diff

139
datapath/datapath.h Normal file
View File

@ -0,0 +1,139 @@
/* Interface exported by openvswitch_mod. */
#ifndef DATAPATH_H
#define DATAPATH_H 1
#include <asm/page.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/netlink.h>
#include <linux/netdevice.h>
#include <linux/workqueue.h>
#include <linux/skbuff.h>
#include "flow.h"
#include "brc_sysfs.h"
struct sk_buff;
/* Mask for the priority bits in a vlan header. If we ever merge upstream
* then this should go into include/linux/if_vlan.h. */
#define VLAN_PCP_MASK 0xe000
#define DP_MAX_PORTS 256
#define DP_MAX_GROUPS 16
#define DP_L2_BITS (PAGE_SHIFT - ilog2(sizeof(struct sw_flow*)))
#define DP_L2_SIZE (1 << DP_L2_BITS)
#define DP_L2_SHIFT 0
#define DP_L1_BITS (PAGE_SHIFT - ilog2(sizeof(struct sw_flow**)))
#define DP_L1_SIZE (1 << DP_L1_BITS)
#define DP_L1_SHIFT DP_L2_BITS
#define DP_MAX_BUCKETS (DP_L1_SIZE * DP_L2_SIZE)
struct dp_table {
unsigned int n_buckets;
struct sw_flow ***flows[2];
struct rcu_head rcu;
};
#define DP_N_QUEUES 2
#define DP_MAX_QUEUE_LEN 100
struct dp_stats_percpu {
u64 n_frags;
u64 n_hit;
u64 n_missed;
u64 n_lost;
};
struct dp_port_group {
struct rcu_head rcu;
int n_ports;
u16 ports[];
};
struct datapath {
struct mutex mutex;
int dp_idx;
#ifdef SUPPORT_SYSFS
struct kobject ifobj;
#endif
int drop_frags;
/* Queued data. */
struct sk_buff_head queues[DP_N_QUEUES];
wait_queue_head_t waitqueue;
/* Flow table. */
unsigned int n_flows;
struct dp_table *table;
/* Port groups. */
struct dp_port_group *groups[DP_MAX_GROUPS];
/* Switch ports. */
unsigned int n_ports;
struct net_bridge_port *ports[DP_MAX_PORTS];
struct list_head port_list; /* All ports, including local_port. */
/* Stats. */
struct dp_stats_percpu *stats_percpu;
};
struct net_bridge_port {
u16 port_no;
struct datapath *dp;
struct net_device *dev;
#ifdef SUPPORT_SYSFS
struct kobject kobj;
#endif
struct list_head node; /* Element in datapath.ports. */
};
extern struct notifier_block dp_device_notifier;
extern int (*dp_ioctl_hook)(struct net_device *dev, struct ifreq *rq, int cmd);
extern int (*dp_add_dp_hook)(struct datapath *dp);
extern int (*dp_del_dp_hook)(struct datapath *dp);
extern int (*dp_add_if_hook)(struct net_bridge_port *p);
extern int (*dp_del_if_hook)(struct net_bridge_port *p);
/* Flow table. */
struct dp_table *dp_table_create(unsigned int n_buckets);
void dp_table_destroy(struct dp_table *, int free_flows);
struct sw_flow *dp_table_lookup(struct dp_table *, const struct odp_flow_key *);
struct sw_flow **dp_table_lookup_for_insert(struct dp_table *, const struct odp_flow_key *);
int dp_table_delete(struct dp_table *, struct sw_flow *);
int dp_table_expand(struct datapath *);
int dp_table_flush(struct datapath *);
int dp_table_foreach(struct dp_table *table,
int (*callback)(struct sw_flow *flow, void *aux),
void *aux);
void dp_process_received_packet(struct sk_buff *, struct net_bridge_port *);
int dp_del_port(struct net_bridge_port *, struct list_head *);
int dp_output_port(struct datapath *, struct sk_buff *, int out_port,
int ignore_no_fwd);
int dp_output_control(struct datapath *, struct sk_buff *, int, u32 arg);
void dp_set_origin(struct datapath *, u16, struct sk_buff *);
struct datapath *get_dp(int dp_idx);
static inline const char *dp_name(const struct datapath *dp)
{
return dp->ports[ODPP_LOCAL]->dev->name;
}
#ifdef CONFIG_XEN
int skb_checksum_setup(struct sk_buff *skb);
#else
static inline int skb_checksum_setup(struct sk_buff *skb)
{
return 0;
}
#endif
#endif /* datapath.h */

210
datapath/dp_dev.c Normal file
View File

@ -0,0 +1,210 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/rcupdate.h>
#include <linux/skbuff.h>
#include <linux/workqueue.h>
#include "datapath.h"
#include "dp_dev.h"
struct datapath *dp_dev_get_dp(struct net_device *netdev)
{
return dp_dev_priv(netdev)->dp;
}
EXPORT_SYMBOL(dp_dev_get_dp);
static struct net_device_stats *dp_dev_get_stats(struct net_device *netdev)
{
struct dp_dev *dp_dev = dp_dev_priv(netdev);
return &dp_dev->stats;
}
int dp_dev_recv(struct net_device *netdev, struct sk_buff *skb)
{
struct dp_dev *dp_dev = dp_dev_priv(netdev);
int len;
len = skb->len;
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, netdev);
if (in_interrupt())
netif_rx(skb);
else
netif_rx_ni(skb);
netdev->last_rx = jiffies;
dp_dev->stats.rx_packets++;
dp_dev->stats.rx_bytes += len;
return len;
}
static int dp_dev_mac_addr(struct net_device *dev, void *p)
{
struct sockaddr *addr = p;
if (!is_valid_ether_addr(addr->sa_data))
return -EADDRNOTAVAIL;
memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
return 0;
}
static int dp_dev_xmit(struct sk_buff *skb, struct net_device *netdev)
{
struct dp_dev *dp_dev = dp_dev_priv(netdev);
/* By orphaning 'skb' we will screw up socket accounting slightly, but
* the effect is limited to the device queue length. If we don't
* do this, then the sk_buff will be destructed eventually, but it is
* harder to predict when. */
skb_orphan(skb);
/* We are going to modify 'skb', by sticking it on &dp_dev->xmit_queue,
* so we need to have our own clone. (At any rate, fwd_port_input()
* will need its own clone, so there's no benefit to queuing any other
* way.) */
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
return 0;
dp_dev->stats.tx_packets++;
dp_dev->stats.tx_bytes += skb->len;
if (skb_queue_len(&dp_dev->xmit_queue) >= netdev->tx_queue_len) {
/* Queue overflow. Stop transmitter. */
netif_stop_queue(netdev);
/* We won't see all dropped packets individually, so overrun
* error is appropriate. */
dp_dev->stats.tx_fifo_errors++;
}
skb_queue_tail(&dp_dev->xmit_queue, skb);
netdev->trans_start = jiffies;
schedule_work(&dp_dev->xmit_work);
return 0;
}
static void dp_dev_do_xmit(struct work_struct *work)
{
struct dp_dev *dp_dev = container_of(work, struct dp_dev, xmit_work);
struct datapath *dp = dp_dev->dp;
struct sk_buff *skb;
while ((skb = skb_dequeue(&dp_dev->xmit_queue)) != NULL) {
skb_reset_mac_header(skb);
rcu_read_lock_bh();
dp_process_received_packet(skb, dp->ports[dp_dev->port_no]);
rcu_read_unlock_bh();
}
netif_wake_queue(dp_dev->dev);
}
static int dp_dev_open(struct net_device *netdev)
{
netif_start_queue(netdev);
return 0;
}
static int dp_dev_stop(struct net_device *netdev)
{
netif_stop_queue(netdev);
return 0;
}
static void dp_getinfo(struct net_device *netdev, struct ethtool_drvinfo *info)
{
struct dp_dev *dp_dev = dp_dev_priv(netdev);
strcpy(info->driver, "openvswitch");
sprintf(info->bus_info, "%d", dp_dev->dp->dp_idx);
}
static struct ethtool_ops dp_ethtool_ops = {
.get_drvinfo = dp_getinfo,
.get_link = ethtool_op_get_link,
.get_sg = ethtool_op_get_sg,
.get_tx_csum = ethtool_op_get_tx_csum,
.get_tso = ethtool_op_get_tso,
};
static void
do_setup(struct net_device *netdev)
{
ether_setup(netdev);
netdev->do_ioctl = dp_ioctl_hook;
netdev->get_stats = dp_dev_get_stats;
netdev->hard_start_xmit = dp_dev_xmit;
netdev->open = dp_dev_open;
SET_ETHTOOL_OPS(netdev, &dp_ethtool_ops);
netdev->stop = dp_dev_stop;
netdev->tx_queue_len = 100;
netdev->set_mac_address = dp_dev_mac_addr;
netdev->flags = IFF_BROADCAST | IFF_MULTICAST;
random_ether_addr(netdev->dev_addr);
/* Set the OUI to the Nicira one. */
netdev->dev_addr[0] = 0x00;
netdev->dev_addr[1] = 0x23;
netdev->dev_addr[2] = 0x20;
/* Set the top bits to indicate random Nicira address. */
netdev->dev_addr[3] |= 0xc0;
}
/* Create a datapath device associated with 'dp'. If 'dp_name' is null,
* the device name will be of the form 'of<dp_idx>'. Returns the new device or
* an error code.
*
* Called with RTNL lock and dp_mutex. */
struct net_device *dp_dev_create(struct datapath *dp, const char *dp_name, int port_no)
{
struct dp_dev *dp_dev;
struct net_device *netdev;
char dev_name[IFNAMSIZ];
int err;
if (dp_name) {
if (strlen(dp_name) >= IFNAMSIZ)
return ERR_PTR(-EINVAL);
strncpy(dev_name, dp_name, sizeof(dev_name));
} else
snprintf(dev_name, sizeof dev_name, "of%d", dp->dp_idx);
netdev = alloc_netdev(sizeof(struct dp_dev), dev_name, do_setup);
if (!netdev)
return ERR_PTR(-ENOMEM);
err = register_netdevice(netdev);
if (err) {
free_netdev(netdev);
return ERR_PTR(err);
}
dp_dev = dp_dev_priv(netdev);
dp_dev->dp = dp;
dp_dev->port_no = port_no;
dp_dev->dev = netdev;
skb_queue_head_init(&dp_dev->xmit_queue);
INIT_WORK(&dp_dev->xmit_work, dp_dev_do_xmit);
return netdev;
}
/* Called with RTNL lock and dp_mutex.*/
void dp_dev_destroy(struct net_device *netdev)
{
struct dp_dev *dp_dev = dp_dev_priv(netdev);
netif_tx_disable(netdev);
synchronize_net();
skb_queue_purge(&dp_dev->xmit_queue);
unregister_netdevice(netdev);
}
int is_dp_dev(struct net_device *netdev)
{
return netdev->open == dp_dev_open;
}
EXPORT_SYMBOL(is_dp_dev);

27
datapath/dp_dev.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef DP_DEV_H
#define DP_DEV_H 1
struct dp_dev {
struct datapath *dp;
int port_no;
struct net_device *dev;
struct net_device_stats stats;
struct sk_buff_head xmit_queue;
struct work_struct xmit_work;
struct list_head list;
};
static inline struct dp_dev *dp_dev_priv(struct net_device *netdev)
{
return netdev_priv(netdev);
}
struct net_device *dp_dev_create(struct datapath *, const char *, int port_no);
void dp_dev_destroy(struct net_device *);
int dp_dev_recv(struct net_device *, struct sk_buff *);
int is_dp_dev(struct net_device *);
struct datapath *dp_dev_get_dp(struct net_device *);
#endif /* dp_dev.h */

29
datapath/dp_notify.c Normal file
View File

@ -0,0 +1,29 @@
/*
* Distributed under the terms of the GNU GPL version 2.
* Copyright (c) 2007, 2008, 2009 Nicira Networks.
*/
/* Handle changes to managed devices */
#include <linux/netdevice.h>
#include "datapath.h"
static int dp_device_event(struct notifier_block *unused, unsigned long event,
void *ptr)
{
struct net_device *dev = ptr;
struct net_bridge_port *p = dev->br_port;
if (event == NETDEV_UNREGISTER && p) {
struct datapath *dp = p->dp;
mutex_lock(&dp->mutex);
dp_del_port(p, NULL);
mutex_unlock(&dp->mutex);
}
return NOTIFY_DONE;
}
struct notifier_block dp_device_notifier = {
.notifier_call = dp_device_event
};

301
datapath/flow.c Normal file
View File

@ -0,0 +1,301 @@
/*
* Distributed under the terms of the GNU GPL version 2.
* Copyright (c) 2007, 2008, 2009 Nicira Networks.
*/
#include "flow.h"
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
#include <net/llc_pdu.h>
#include <linux/kernel.h>
#include <linux/jiffies.h>
#include <linux/llc.h>
#include <linux/module.h>
#include <linux/in.h>
#include <linux/rcupdate.h>
#include <linux/if_ether.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#include <linux/icmp.h>
#include <net/ip.h>
#include "compat.h"
struct kmem_cache *flow_cache;
static inline int iphdr_ok(struct sk_buff *skb)
{
int nh_ofs = skb_network_offset(skb);
if (skb->len >= nh_ofs + sizeof(struct iphdr)) {
int ip_len = ip_hdrlen(skb);
return (ip_len >= sizeof(struct iphdr)
&& pskb_may_pull(skb, nh_ofs + ip_len));
}
return 0;
}
static inline int tcphdr_ok(struct sk_buff *skb)
{
int th_ofs = skb_transport_offset(skb);
if (pskb_may_pull(skb, th_ofs + sizeof(struct tcphdr))) {
int tcp_len = tcp_hdrlen(skb);
return (tcp_len >= sizeof(struct tcphdr)
&& skb->len >= th_ofs + tcp_len);
}
return 0;
}
static inline int udphdr_ok(struct sk_buff *skb)
{
int th_ofs = skb_transport_offset(skb);
return pskb_may_pull(skb, th_ofs + sizeof(struct udphdr));
}
static inline int icmphdr_ok(struct sk_buff *skb)
{
int th_ofs = skb_transport_offset(skb);
return pskb_may_pull(skb, th_ofs + sizeof(struct icmphdr));
}
#define TCP_FLAGS_OFFSET 13
#define TCP_FLAG_MASK 0x3f
static inline struct ovs_tcphdr *ovs_tcp_hdr(const struct sk_buff *skb)
{
return (struct ovs_tcphdr *)skb_transport_header(skb);
}
void flow_used(struct sw_flow *flow, struct sk_buff *skb)
{
unsigned long flags;
u8 tcp_flags = 0;
if (flow->key.dl_type == htons(ETH_P_IP) && iphdr_ok(skb)) {
struct iphdr *nh = ip_hdr(skb);
flow->ip_tos = nh->tos;
if (flow->key.nw_proto == IPPROTO_TCP && tcphdr_ok(skb)) {
u8 *tcp = (u8 *)tcp_hdr(skb);
tcp_flags = *(tcp + TCP_FLAGS_OFFSET) & TCP_FLAG_MASK;
}
}
spin_lock_irqsave(&flow->lock, flags);
getnstimeofday(&flow->used);
flow->packet_count++;
flow->byte_count += skb->len;
flow->tcp_flags |= tcp_flags;
spin_unlock_irqrestore(&flow->lock, flags);
}
struct sw_flow_actions *flow_actions_alloc(size_t n_actions)
{
struct sw_flow_actions *sfa;
if (n_actions > (PAGE_SIZE - sizeof *sfa) / sizeof(union odp_action))
return ERR_PTR(-EINVAL);
sfa = kmalloc(sizeof *sfa + n_actions * sizeof(union odp_action),
GFP_KERNEL);
if (!sfa)
return ERR_PTR(-ENOMEM);
sfa->n_actions = n_actions;
return sfa;
}
/* Frees 'flow' immediately. */
void flow_free(struct sw_flow *flow)
{
if (unlikely(!flow))
return;
kfree(flow->sf_acts);
kmem_cache_free(flow_cache, flow);
}
/* RCU callback used by flow_deferred_free. */
static void rcu_free_flow_callback(struct rcu_head *rcu)
{
struct sw_flow *flow = container_of(rcu, struct sw_flow, rcu);
flow_free(flow);
}
/* Schedules 'flow' to be freed after the next RCU grace period.
* The caller must hold rcu_read_lock for this to be sensible. */
void flow_deferred_free(struct sw_flow *flow)
{
call_rcu(&flow->rcu, rcu_free_flow_callback);
}
/* RCU callback used by flow_deferred_free_acts. */
static void rcu_free_acts_callback(struct rcu_head *rcu)
{
struct sw_flow_actions *sf_acts = container_of(rcu,
struct sw_flow_actions, rcu);
kfree(sf_acts);
}
/* Schedules 'sf_acts' to be freed after the next RCU grace period.
* The caller must hold rcu_read_lock for this to be sensible. */
void flow_deferred_free_acts(struct sw_flow_actions *sf_acts)
{
call_rcu(&sf_acts->rcu, rcu_free_acts_callback);
}
#define SNAP_OUI_LEN 3
struct eth_snap_hdr
{
struct ethhdr eth;
u8 dsap; /* Always 0xAA */
u8 ssap; /* Always 0xAA */
u8 ctrl;
u8 oui[SNAP_OUI_LEN];
u16 ethertype;
} __attribute__ ((packed));
static int is_snap(const struct eth_snap_hdr *esh)
{
return (esh->dsap == LLC_SAP_SNAP
&& esh->ssap == LLC_SAP_SNAP
&& !memcmp(esh->oui, "\0\0\0", 3));
}
/* Parses the Ethernet frame in 'skb', which was received on 'in_port',
* and initializes 'key' to match. Returns 1 if 'skb' contains an IP
* fragment, 0 otherwise. */
int flow_extract(struct sk_buff *skb, u16 in_port, struct odp_flow_key *key)
{
struct ethhdr *eth;
struct eth_snap_hdr *esh;
int retval = 0;
int nh_ofs;
memset(key, 0, sizeof *key);
key->dl_vlan = htons(ODP_VLAN_NONE);
key->in_port = in_port;
if (skb->len < sizeof *eth)
return 0;
if (!pskb_may_pull(skb, skb->len >= 64 ? 64 : skb->len)) {
return 0;
}
skb_reset_mac_header(skb);
eth = eth_hdr(skb);
esh = (struct eth_snap_hdr *) eth;
nh_ofs = sizeof *eth;
if (likely(ntohs(eth->h_proto) >= ODP_DL_TYPE_ETH2_CUTOFF))
key->dl_type = eth->h_proto;
else if (skb->len >= sizeof *esh && is_snap(esh)) {
key->dl_type = esh->ethertype;
nh_ofs = sizeof *esh;
} else {
key->dl_type = htons(ODP_DL_TYPE_NOT_ETH_TYPE);
if (skb->len >= nh_ofs + sizeof(struct llc_pdu_un)) {
nh_ofs += sizeof(struct llc_pdu_un);
}
}
/* Check for a VLAN tag */
if (key->dl_type == htons(ETH_P_8021Q) &&
skb->len >= nh_ofs + sizeof(struct vlan_hdr)) {
struct vlan_hdr *vh = (struct vlan_hdr*)(skb->data + nh_ofs);
key->dl_type = vh->h_vlan_encapsulated_proto;
key->dl_vlan = vh->h_vlan_TCI & htons(VLAN_VID_MASK);
nh_ofs += sizeof(struct vlan_hdr);
}
memcpy(key->dl_src, eth->h_source, ETH_ALEN);
memcpy(key->dl_dst, eth->h_dest, ETH_ALEN);
skb_set_network_header(skb, nh_ofs);
/* Network layer. */
if (key->dl_type == htons(ETH_P_IP) && iphdr_ok(skb)) {
struct iphdr *nh = ip_hdr(skb);
int th_ofs = nh_ofs + nh->ihl * 4;
key->nw_src = nh->saddr;
key->nw_dst = nh->daddr;
key->nw_proto = nh->protocol;
skb_set_transport_header(skb, th_ofs);
/* Transport layer. */
if (!(nh->frag_off & htons(IP_MF | IP_OFFSET))) {
if (key->nw_proto == IPPROTO_TCP) {
if (tcphdr_ok(skb)) {
struct tcphdr *tcp = tcp_hdr(skb);
key->tp_src = tcp->source;
key->tp_dst = tcp->dest;
} else {
/* Avoid tricking other code into
* thinking that this packet has an L4
* header. */
key->nw_proto = 0;
}
} else if (key->nw_proto == IPPROTO_UDP) {
if (udphdr_ok(skb)) {
struct udphdr *udp = udp_hdr(skb);
key->tp_src = udp->source;
key->tp_dst = udp->dest;
} else {
/* Avoid tricking other code into
* thinking that this packet has an L4
* header. */
key->nw_proto = 0;
}
} else if (key->nw_proto == IPPROTO_ICMP) {
if (icmphdr_ok(skb)) {
struct icmphdr *icmp = icmp_hdr(skb);
/* The ICMP type and code fields use the 16-bit
* transport port fields, so we need to store them
* in 16-bit network byte order. */
key->tp_src = htons(icmp->type);
key->tp_dst = htons(icmp->code);
} else {
/* Avoid tricking other code into
* thinking that this packet has an L4
* header. */
key->nw_proto = 0;
}
}
} else {
retval = 1;
}
} else {
skb_reset_transport_header(skb);
}
return retval;
}
/* Initializes the flow module.
* Returns zero if successful or a negative error code. */
int flow_init(void)
{
flow_cache = kmem_cache_create("sw_flow", sizeof(struct sw_flow), 0,
0, NULL);
if (flow_cache == NULL)
return -ENOMEM;
return 0;
}
/* Uninitializes the flow module. */
void flow_exit(void)
{
kmem_cache_destroy(flow_cache);
}
void print_flow(const struct odp_flow_key *key)
{
#define MAC_FMT "%02x:%02x:%02x:%02x:%02x:%02x"
#define MAC_ARG(x) ((u8*)(x))[0],((u8*)(x))[1],((u8*)(x))[2],((u8*)(x))[3],((u8*)(x))[4],((u8*)(x))[5]
printk("port%04x:vlan%d mac"MAC_FMT"->"MAC_FMT" "
"type%04x proto%d ip%x->%x port%d->%d\n",
key->in_port, ntohs(key->dl_vlan),
MAC_ARG(key->dl_src), MAC_ARG(key->dl_dst),
ntohs(key->dl_type), key->nw_proto,
key->nw_src, key->nw_dst,
ntohs(key->tp_src), ntohs(key->tp_dst));
}

49
datapath/flow.h Normal file
View File

@ -0,0 +1,49 @@
#ifndef FLOW_H
#define FLOW_H 1
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include <linux/rcupdate.h>
#include <linux/gfp.h>
#include "openvswitch/datapath-protocol.h"
struct sk_buff;
struct sw_flow_actions {
struct rcu_head rcu;
unsigned int n_actions;
union odp_action actions[];
};
struct sw_flow {
struct rcu_head rcu;
struct odp_flow_key key;
struct sw_flow_actions *sf_acts;
struct timespec used; /* Last used time. */
u8 ip_tos; /* IP TOS value. */
spinlock_t lock; /* Lock for values below. */
u64 packet_count; /* Number of packets matched. */
u64 byte_count; /* Number of bytes matched. */
u8 tcp_flags; /* Union of seen TCP flags. */
};
extern struct kmem_cache *flow_cache;
struct sw_flow_actions *flow_actions_alloc(size_t n_actions);
void flow_free(struct sw_flow *);
void flow_deferred_free(struct sw_flow *);
void flow_deferred_free_acts(struct sw_flow_actions *);
int flow_extract(struct sk_buff *, u16 in_port, struct odp_flow_key *);
void flow_used(struct sw_flow *, struct sk_buff *);
void print_flow(const struct odp_flow_key *);
int flow_init(void);
void flow_exit(void);
#endif /* flow.h */

20
datapath/linux-2.6/.gitignore vendored Normal file
View File

@ -0,0 +1,20 @@
/Kbuild
/Makefile
/Makefile.main
/actions.c
/brcompat.c
/brc_sysfs_dp.c
/brc_sysfs_if.c
/datapath.c
/dp_dev.c
/dp_notify.c
/flow.c
/genetlink-brcompat.c
/genetlink-openvswitch.c
/kcompat.h
/linux-2.6
/modules.order
/random32.c
/table.c
/tmp
/veth.c

View File

@ -0,0 +1,34 @@
# -*- makefile -*-
export builddir = @abs_builddir@
export srcdir = @abs_srcdir@
export top_srcdir = @abs_top_srcdir@
export VERSION = @VERSION@
export BUILDNR = @BUILDNR@
include $(srcdir)/../Modules.mk
include $(srcdir)/Modules.mk
EXTRA_CFLAGS := -DVERSION=\"$(VERSION)\"
EXTRA_CFLAGS += -I$(srcdir)/..
EXTRA_CFLAGS += -I$(builddir)/..
EXTRA_CFLAGS += -I$(top_srcdir)/include
ifeq '$(BUILDNR)' '0'
EXTRA_CFLAGS += -DBUILDNR=\"\"
else
EXTRA_CFLAGS += -DBUILDNR=\"+build$(BUILDNR)\"
endif
EXTRA_CFLAGS += -g
EXTRA_CFLAGS += -include $(builddir)/kcompat.h
# These include directories have to go before -I$(KSRC)/include.
# NOSTDINC_FLAGS just happens to be a variable that goes in the
# right place, even though it's conceptually incorrect.
NOSTDINC_FLAGS += -I$(srcdir)/compat-2.6 -I$(srcdir)/compat-2.6/include
obj-m := $(patsubst %,%_mod.o,$(build_modules))
define module_template
$(1)_mod-y = $$(notdir $$(patsubst %.c,%.o,$($(1)_sources)))
endef
$(foreach module,$(build_modules),$(eval $(call module_template,$(module))))

View File

@ -0,0 +1,9 @@
ifeq ($(KERNELRELEASE),)
# We're being called directly by running make in this directory.
include Makefile.main
else
# We're being included by the Linux kernel build system
include Kbuild
endif

View File

@ -0,0 +1,82 @@
# -*- makefile -*-
export builddir = @abs_builddir@
export srcdir = @abs_srcdir@
export top_srcdir = @abs_top_srcdir@
export KSRC = @KSRC26@
export VERSION = @VERSION@
export BUILD_VETH = @BUILD_VETH@
include $(srcdir)/../Modules.mk
include $(srcdir)/Modules.mk
default: $(build_links)
$(foreach s,$(sort $(foreach m,$(build_modules),$($(m)_sources))), \
$(eval $(notdir $(s)): ; ln -s $(srcdir)/../$(s) $@))
distclean: clean
rm -f kcompat.h
distdir: clean
install:
all: default
check: all
clean:
rm -f *.o *.ko *_mod.* Module.symvers *.cmd kcompat.h.new
for d in $(build_links); do if test -h $$d; then rm $$d; fi; done
ifneq ($(KSRC),)
ifeq (/lib/modules/$(shell uname -r)/source, $(KSRC))
KOBJ := /lib/modules/$(shell uname -r)/build
else
KOBJ := $(KSRC)
endif
ifneq ($(shell grep -c 'PATCHLEVEL = 6' $(KSRC)/Makefile),1)
$(error Linux kernel source in $(KSRC) not 2.6)
endif
VERSION_FILE := $(KOBJ)/include/linux/version.h
ifeq (,$(wildcard $(VERSION_FILE)))
$(error Linux kernel source not configured - missing version.h)
endif
CONFIG_FILE := $(KSRC)/include/linux/autoconf.h
ifeq (,$(wildcard $(CONFIG_FILE)))
$(error Linux kernel source not configured - missing autoconf.h)
endif
default:
$(MAKE) -C $(KSRC) M=$(builddir) modules
endif
# Much of the kernel build system in this file is derived from Intel's
# e1000 distribution, with the following license:
################################################################################
#
# Intel PRO/1000 Linux driver
# Copyright(c) 1999 - 2007, 2009 Intel Corporation.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms and conditions of the GNU General Public License,
# version 2, as published by the Free Software Foundation.
#
# This program is distributed in the hope 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.,
# 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
#
# The full GNU General Public License is included in this distribution in
# the file called "COPYING".
#
# Contact Information:
# Linux NICS <linux.nics@intel.com>
# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
#
################################################################################

View File

@ -0,0 +1,50 @@
openvswitch_sources += \
linux-2.6/compat-2.6/genetlink-openvswitch.c \
linux-2.6/compat-2.6/random32.c
openvswitch_headers += \
linux-2.6/compat-2.6/compat26.h \
linux-2.6/compat-2.6/include/asm-generic/bug.h \
linux-2.6/compat-2.6/include/linux/dmi.h \
linux-2.6/compat-2.6/include/linux/err.h \
linux-2.6/compat-2.6/include/linux/icmp.h \
linux-2.6/compat-2.6/include/linux/if_arp.h \
linux-2.6/compat-2.6/include/linux/ip.h \
linux-2.6/compat-2.6/include/linux/ipv6.h \
linux-2.6/compat-2.6/include/linux/jiffies.h \
linux-2.6/compat-2.6/include/linux/kernel.h \
linux-2.6/compat-2.6/include/linux/log2.h \
linux-2.6/compat-2.6/include/linux/lockdep.h \
linux-2.6/compat-2.6/include/linux/mutex.h \
linux-2.6/compat-2.6/include/linux/netdevice.h \
linux-2.6/compat-2.6/include/linux/netfilter_bridge.h \
linux-2.6/compat-2.6/include/linux/netfilter_ipv4.h \
linux-2.6/compat-2.6/include/linux/netlink.h \
linux-2.6/compat-2.6/include/linux/percpu.h \
linux-2.6/compat-2.6/include/linux/random.h \
linux-2.6/compat-2.6/include/linux/rculist.h \
linux-2.6/compat-2.6/include/linux/rtnetlink.h \
linux-2.6/compat-2.6/include/linux/skbuff.h \
linux-2.6/compat-2.6/include/linux/tcp.h \
linux-2.6/compat-2.6/include/linux/timer.h \
linux-2.6/compat-2.6/include/linux/types.h \
linux-2.6/compat-2.6/include/linux/udp.h \
linux-2.6/compat-2.6/include/linux/workqueue.h \
linux-2.6/compat-2.6/include/net/checksum.h \
linux-2.6/compat-2.6/include/net/genetlink.h \
linux-2.6/compat-2.6/include/net/netlink.h
both_modules += brcompat
brcompat_sources = \
linux-2.6/compat-2.6/genetlink-brcompat.c \
brcompat.c \
brc_procfs.c \
brc_sysfs_dp.c \
brc_sysfs_if.c
brcompat_headers = \
brc_procfs.h \
brc_sysfs.h
dist_modules += veth
build_modules += $(if $(BUILD_VETH),veth)
veth_sources = linux-2.6/compat-2.6/veth.c
veth_headers =

View File

@ -0,0 +1,37 @@
#ifndef __COMPAT26_H
#define __COMPAT26_H 1
#include <linux/version.h>
#if defined(CONFIG_PREEMPT) && LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,21)
#error "CONFIG_PREEMPT is broken with 2.6.x before 2.6.21--see commit 4498121ca3, \"[NET]: Handle disabled preemption in gfp_any()\""
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,23)
/*----------------------------------------------------------------------------
* In 2.6.24, a namespace argument became required for dev_get_by_name. */
#define dev_get_by_name(net, name) \
dev_get_by_name((name))
#define dev_get_by_index(net, ifindex) \
dev_get_by_index((ifindex))
#define __dev_get_by_name(net, name) \
__dev_get_by_name((name))
#define __dev_get_by_index(net, ifindex) \
__dev_get_by_index((ifindex))
#endif /* linux kernel <= 2.6.23 */
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)
/*----------------------------------------------------------------------------
* In 2.6.23, the last argument was dropped from kmem_cache_create. */
#define kmem_cache_create(n, s, a, f, c) \
kmem_cache_create((n), (s), (a), (f), (c), NULL)
#endif /* linux kernel <= 2.6.22 */
#endif /* compat26.h */

View File

@ -0,0 +1,20 @@
#include "net/genetlink.h"
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
/* We fix grp->id to 32 so that it doesn't collide with any of the multicast
* groups selected by openvswitch_mod, which uses groups 16 through 31.
* Collision isn't fatal--multicast listeners should check that the family is
* the one that they want and discard others--but it wastes time and memory to
* receive unwanted messages. */
int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp)
{
grp->id = 32;
grp->family = family;
return 0;
}
#endif /* kernel < 2.6.23 */

View File

@ -0,0 +1,22 @@
#include "net/genetlink.h"
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
/* We use multicast groups 16 through 31 to avoid colliding with the multicast
* group selected by brcompat_mod, which uses groups 32. Collision isn't
* fatal--multicast listeners should check that the family is the one that they
* want and discard others--but it wastes time and memory to receive unwanted
* messages. */
int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp)
{
/* This code is called single-threaded. */
static unsigned int next_id = 0;
grp->id = next_id++ % 16 + 16;
grp->family = family;
return 0;
}
#endif /* kernel < 2.6.23 */

View File

@ -0,0 +1,19 @@
#ifndef __ASM_GENERIC_BUG_WRAPPER_H
#define __ASM_GENERIC_BUG_WRAPPER_H
#include_next <asm-generic/bug.h>
#ifndef WARN_ON_ONCE
#define WARN_ON_ONCE(condition) ({ \
static int __warned; \
int __ret_warn_once = !!(condition); \
\
if (unlikely(__ret_warn_once) && !__warned) { \
WARN_ON(1); \
__warned = 1; \
} \
unlikely(__ret_warn_once); \
})
#endif
#endif

View File

@ -0,0 +1,11 @@
#ifndef __LINUX_CPUMASK_WRAPPER_H
#define __LINUX_CPUMASK_WRAPPER_H
#include_next <linux/cpumask.h>
/* for_each_cpu was renamed for_each_possible_cpu in 2.6.18. */
#ifndef for_each_possible_cpu
#define for_each_possible_cpu for_each_cpu
#endif
#endif /* linux/cpumask.h wrapper */

View File

@ -0,0 +1,114 @@
#ifndef __LINUX_DMI_WRAPPER_H
#define __LINUX_DMI_WRAPPER_H 1
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
#include_next <linux/dmi.h>
#else /* linux version >= 2.6.23 */
#ifndef __DMI_H__
#define __DMI_H__
#include <linux/list.h>
enum dmi_field {
DMI_NONE,
DMI_BIOS_VENDOR,
DMI_BIOS_VERSION,
DMI_BIOS_DATE,
DMI_SYS_VENDOR,
DMI_PRODUCT_NAME,
DMI_PRODUCT_VERSION,
DMI_PRODUCT_SERIAL,
DMI_PRODUCT_UUID,
DMI_BOARD_VENDOR,
DMI_BOARD_NAME,
DMI_BOARD_VERSION,
DMI_BOARD_SERIAL,
DMI_BOARD_ASSET_TAG,
DMI_CHASSIS_VENDOR,
DMI_CHASSIS_TYPE,
DMI_CHASSIS_VERSION,
DMI_CHASSIS_SERIAL,
DMI_CHASSIS_ASSET_TAG,
DMI_STRING_MAX,
};
enum dmi_device_type {
DMI_DEV_TYPE_ANY = 0,
DMI_DEV_TYPE_OTHER,
DMI_DEV_TYPE_UNKNOWN,
DMI_DEV_TYPE_VIDEO,
DMI_DEV_TYPE_SCSI,
DMI_DEV_TYPE_ETHERNET,
DMI_DEV_TYPE_TOKENRING,
DMI_DEV_TYPE_SOUND,
DMI_DEV_TYPE_IPMI = -1,
DMI_DEV_TYPE_OEM_STRING = -2
};
struct dmi_header {
u8 type;
u8 length;
u16 handle;
};
/*
* DMI callbacks for problem boards
*/
struct dmi_strmatch {
u8 slot;
char *substr;
};
struct dmi_system_id {
int (*callback)(struct dmi_system_id *);
const char *ident;
struct dmi_strmatch matches[4];
void *driver_data;
};
#define DMI_MATCH(a, b) { a, b }
struct dmi_device {
struct list_head list;
int type;
const char *name;
void *device_data; /* Type specific data */
};
/* No CONFIG_DMI before 2.6.16 */
#if defined(CONFIG_DMI) || defined(CONFIG_X86_32)
extern int dmi_check_system(struct dmi_system_id *list);
extern char * dmi_get_system_info(int field);
extern struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16)
extern void dmi_scan_machine(void);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,17)
extern int dmi_get_year(int field);
#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
extern int dmi_name_in_vendors(char *str);
#endif
#else
static inline int dmi_check_system(struct dmi_system_id *list) { return 0; }
static inline char * dmi_get_system_info(int field) { return NULL; }
static inline struct dmi_device * dmi_find_device(int type, const char *name,
struct dmi_device *from) { return NULL; }
static inline int dmi_get_year(int year) { return 0; }
static inline int dmi_name_in_vendors(char *s) { return 0; }
#endif
#endif /* __DMI_H__ */
#endif /* linux kernel < 2.6.22 */
#endif

View File

@ -0,0 +1,21 @@
#ifndef __LINUX_ERR_WRAPPER_H
#define __LINUX_ERR_WRAPPER_H 1
#include_next <linux/err.h>
#ifndef HAVE_ERR_CAST
/**
* ERR_CAST - Explicitly cast an error-valued pointer to another pointer type
* @ptr: The pointer to cast.
*
* Explicitly cast an error-valued pointer to another pointer type in such a
* way as to make it clear that's what's going on.
*/
static inline void *ERR_CAST(const void *ptr)
{
/* cast away the const */
return (void *) ptr;
}
#endif /* HAVE_ERR_CAST */
#endif

View File

@ -0,0 +1,13 @@
#ifndef __LINUX_ICMP_WRAPPER_H
#define __LINUX_ICMP_WRAPPER_H 1
#include_next <linux/icmp.h>
#ifndef HAVE_SKBUFF_HEADER_HELPERS
static inline struct icmphdr *icmp_hdr(const struct sk_buff *skb)
{
return (struct icmphdr *)skb_transport_header(skb);
}
#endif
#endif

View File

@ -0,0 +1,15 @@
#ifndef __LINUX_IF_ARP_WRAPPER_H
#define __LINUX_IF_ARP_WRAPPER_H 1
#include_next <linux/if_arp.h>
#ifndef HAVE_SKBUFF_HEADER_HELPERS
#include <linux/skbuff.h>
static inline struct arphdr *arp_hdr(const struct sk_buff *skb)
{
return (struct arphdr *)skb_network_header(skb);
}
#endif /* !HAVE_SKBUFF_HEADER_HELPERS */
#endif

View File

@ -0,0 +1,18 @@
#ifndef __LINUX_IP_WRAPPER_H
#define __LINUX_IP_WRAPPER_H 1
#include_next <linux/ip.h>
#ifndef HAVE_SKBUFF_HEADER_HELPERS
static inline struct iphdr *ip_hdr(const struct sk_buff *skb)
{
return (struct iphdr *)skb_network_header(skb);
}
static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
{
return ip_hdr(skb)->ihl * 4;
}
#endif /* !HAVE_SKBUFF_HEADER_HELPERS */
#endif

View File

@ -0,0 +1,13 @@
#ifndef __LINUX_IPV6_WRAPPER_H
#define __LINUX_IPV6_WRAPPER_H 1
#include_next <linux/ipv6.h>
#ifndef HAVE_SKBUFF_HEADER_HELPERS
static inline struct ipv6hdr *ipv6_hdr(const struct sk_buff *skb)
{
return (struct ipv6hdr *)skb_network_header(skb);
}
#endif
#endif

View File

@ -0,0 +1,26 @@
#ifndef __LINUX_JIFFIES_WRAPPER_H
#define __LINUX_JIFFIES_WRAPPER_H 1
#include_next <linux/jiffies.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
/* Same as above, but does so with platform independent 64bit types.
* These must be used when utilizing jiffies_64 (i.e. return value of
* get_jiffies_64() */
#define time_after64(a,b) \
(typecheck(__u64, a) && \
typecheck(__u64, b) && \
((__s64)(b) - (__s64)(a) < 0))
#define time_before64(a,b) time_after64(b,a)
#define time_after_eq64(a,b) \
(typecheck(__u64, a) && \
typecheck(__u64, b) && \
((__s64)(a) - (__s64)(b) >= 0))
#define time_before_eq64(a,b) time_after_eq64(b,a)
#endif /* linux kernel < 2.6.19 */
#endif

View File

@ -0,0 +1,9 @@
#ifndef __KERNEL_H_WRAPPER
#define __KERNEL_H_WRAPPER 1
#include_next <linux/kernel.h>
#ifndef HAVE_LOG2_H
#include <linux/log2.h>
#endif
#endif /* linux/kernel.h */

View File

@ -0,0 +1,450 @@
/*
* Runtime locking correctness validator
*
* Copyright (C) 2006,2007 Red Hat, Inc., Ingo Molnar <mingo@redhat.com>
* Copyright (C) 2007 Red Hat, Inc., Peter Zijlstra <pzijlstr@redhat.com>
*
* see Documentation/lockdep-design.txt for more details.
*/
#ifndef __LINUX_LOCKDEP_WRAPPER_H
#define __LINUX_LOCKDEP_WRAPPER_H
#include_next <linux/lockdep.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
struct task_struct;
struct lockdep_map;
#ifdef CONFIG_LOCKDEP
#include <linux/linkage.h>
#include <linux/list.h>
#include <linux/debug_locks.h>
#include <linux/stacktrace.h>
/*
* Lock-class usage-state bits:
*/
enum lock_usage_bit
{
LOCK_USED = 0,
LOCK_USED_IN_HARDIRQ,
LOCK_USED_IN_SOFTIRQ,
LOCK_ENABLED_SOFTIRQS,
LOCK_ENABLED_HARDIRQS,
LOCK_USED_IN_HARDIRQ_READ,
LOCK_USED_IN_SOFTIRQ_READ,
LOCK_ENABLED_SOFTIRQS_READ,
LOCK_ENABLED_HARDIRQS_READ,
LOCK_USAGE_STATES
};
/*
* Usage-state bitmasks:
*/
#define LOCKF_USED (1 << LOCK_USED)
#define LOCKF_USED_IN_HARDIRQ (1 << LOCK_USED_IN_HARDIRQ)
#define LOCKF_USED_IN_SOFTIRQ (1 << LOCK_USED_IN_SOFTIRQ)
#define LOCKF_ENABLED_HARDIRQS (1 << LOCK_ENABLED_HARDIRQS)
#define LOCKF_ENABLED_SOFTIRQS (1 << LOCK_ENABLED_SOFTIRQS)
#define LOCKF_ENABLED_IRQS (LOCKF_ENABLED_HARDIRQS | LOCKF_ENABLED_SOFTIRQS)
#define LOCKF_USED_IN_IRQ (LOCKF_USED_IN_HARDIRQ | LOCKF_USED_IN_SOFTIRQ)
#define LOCKF_USED_IN_HARDIRQ_READ (1 << LOCK_USED_IN_HARDIRQ_READ)
#define LOCKF_USED_IN_SOFTIRQ_READ (1 << LOCK_USED_IN_SOFTIRQ_READ)
#define LOCKF_ENABLED_HARDIRQS_READ (1 << LOCK_ENABLED_HARDIRQS_READ)
#define LOCKF_ENABLED_SOFTIRQS_READ (1 << LOCK_ENABLED_SOFTIRQS_READ)
#define LOCKF_ENABLED_IRQS_READ \
(LOCKF_ENABLED_HARDIRQS_READ | LOCKF_ENABLED_SOFTIRQS_READ)
#define LOCKF_USED_IN_IRQ_READ \
(LOCKF_USED_IN_HARDIRQ_READ | LOCKF_USED_IN_SOFTIRQ_READ)
#define MAX_LOCKDEP_SUBCLASSES 8UL
/*
* Lock-classes are keyed via unique addresses, by embedding the
* lockclass-key into the kernel (or module) .data section. (For
* static locks we use the lock address itself as the key.)
*/
struct lockdep_subclass_key {
char __one_byte;
} __attribute__ ((__packed__));
struct lock_class_key {
struct lockdep_subclass_key subkeys[MAX_LOCKDEP_SUBCLASSES];
};
/*
* The lock-class itself:
*/
struct lock_class {
/*
* class-hash:
*/
struct list_head hash_entry;
/*
* global list of all lock-classes:
*/
struct list_head lock_entry;
struct lockdep_subclass_key *key;
unsigned int subclass;
/*
* IRQ/softirq usage tracking bits:
*/
unsigned long usage_mask;
struct stack_trace usage_traces[LOCK_USAGE_STATES];
/*
* These fields represent a directed graph of lock dependencies,
* to every node we attach a list of "forward" and a list of
* "backward" graph nodes.
*/
struct list_head locks_after, locks_before;
/*
* Generation counter, when doing certain classes of graph walking,
* to ensure that we check one node only once:
*/
unsigned int version;
/*
* Statistics counter:
*/
unsigned long ops;
const char *name;
int name_version;
#ifdef CONFIG_LOCK_STAT
unsigned long contention_point[4];
#endif
};
#ifdef CONFIG_LOCK_STAT
struct lock_time {
s64 min;
s64 max;
s64 total;
unsigned long nr;
};
enum bounce_type {
bounce_acquired_write,
bounce_acquired_read,
bounce_contended_write,
bounce_contended_read,
nr_bounce_types,
bounce_acquired = bounce_acquired_write,
bounce_contended = bounce_contended_write,
};
struct lock_class_stats {
unsigned long contention_point[4];
struct lock_time read_waittime;
struct lock_time write_waittime;
struct lock_time read_holdtime;
struct lock_time write_holdtime;
unsigned long bounces[nr_bounce_types];
};
struct lock_class_stats lock_stats(struct lock_class *class);
void clear_lock_stats(struct lock_class *class);
#endif
/*
* Map the lock object (the lock instance) to the lock-class object.
* This is embedded into specific lock instances:
*/
struct lockdep_map {
struct lock_class_key *key;
struct lock_class *class_cache;
const char *name;
#ifdef CONFIG_LOCK_STAT
int cpu;
#endif
};
/*
* Every lock has a list of other locks that were taken after it.
* We only grow the list, never remove from it:
*/
struct lock_list {
struct list_head entry;
struct lock_class *class;
struct stack_trace trace;
int distance;
};
/*
* We record lock dependency chains, so that we can cache them:
*/
struct lock_chain {
struct list_head entry;
u64 chain_key;
};
struct held_lock {
/*
* One-way hash of the dependency chain up to this point. We
* hash the hashes step by step as the dependency chain grows.
*
* We use it for dependency-caching and we skip detection
* passes and dependency-updates if there is a cache-hit, so
* it is absolutely critical for 100% coverage of the validator
* to have a unique key value for every unique dependency path
* that can occur in the system, to make a unique hash value
* as likely as possible - hence the 64-bit width.
*
* The task struct holds the current hash value (initialized
* with zero), here we store the previous hash value:
*/
u64 prev_chain_key;
struct lock_class *class;
unsigned long acquire_ip;
struct lockdep_map *instance;
#ifdef CONFIG_LOCK_STAT
u64 waittime_stamp;
u64 holdtime_stamp;
#endif
/*
* The lock-stack is unified in that the lock chains of interrupt
* contexts nest ontop of process context chains, but we 'separate'
* the hashes by starting with 0 if we cross into an interrupt
* context, and we also keep do not add cross-context lock
* dependencies - the lock usage graph walking covers that area
* anyway, and we'd just unnecessarily increase the number of
* dependencies otherwise. [Note: hardirq and softirq contexts
* are separated from each other too.]
*
* The following field is used to detect when we cross into an
* interrupt context:
*/
int irq_context;
int trylock;
int read;
int check;
int hardirqs_off;
};
/*
* Initialization, self-test and debugging-output methods:
*/
extern void lockdep_init(void);
extern void lockdep_info(void);
extern void lockdep_reset(void);
extern void lockdep_reset_lock(struct lockdep_map *lock);
extern void lockdep_free_key_range(void *start, unsigned long size);
extern void lockdep_off(void);
extern void lockdep_on(void);
/*
* These methods are used by specific locking variants (spinlocks,
* rwlocks, mutexes and rwsems) to pass init/acquire/release events
* to lockdep:
*/
extern void lockdep_init_map(struct lockdep_map *lock, const char *name,
struct lock_class_key *key, int subclass);
/*
* Reinitialize a lock key - for cases where there is special locking or
* special initialization of locks so that the validator gets the scope
* of dependencies wrong: they are either too broad (they need a class-split)
* or they are too narrow (they suffer from a false class-split):
*/
#define lockdep_set_class(lock, key) \
lockdep_init_map(&(lock)->dep_map, #key, key, 0)
#define lockdep_set_class_and_name(lock, key, name) \
lockdep_init_map(&(lock)->dep_map, name, key, 0)
#define lockdep_set_class_and_subclass(lock, key, sub) \
lockdep_init_map(&(lock)->dep_map, #key, key, sub)
#define lockdep_set_subclass(lock, sub) \
lockdep_init_map(&(lock)->dep_map, #lock, \
(lock)->dep_map.key, sub)
/*
* Acquire a lock.
*
* Values for "read":
*
* 0: exclusive (write) acquire
* 1: read-acquire (no recursion allowed)
* 2: read-acquire with same-instance recursion allowed
*
* Values for check:
*
* 0: disabled
* 1: simple checks (freeing, held-at-exit-time, etc.)
* 2: full validation
*/
extern void lock_acquire(struct lockdep_map *lock, unsigned int subclass,
int trylock, int read, int check, unsigned long ip);
extern void lock_release(struct lockdep_map *lock, int nested,
unsigned long ip);
# define INIT_LOCKDEP .lockdep_recursion = 0,
#define lockdep_depth(tsk) (debug_locks ? (tsk)->lockdep_depth : 0)
#else /* !LOCKDEP */
static inline void lockdep_off(void)
{
}
static inline void lockdep_on(void)
{
}
# define lock_acquire(l, s, t, r, c, i) do { } while (0)
# define lock_release(l, n, i) do { } while (0)
# define lockdep_init() do { } while (0)
# define lockdep_info() do { } while (0)
# define lockdep_init_map(lock, name, key, sub) do { (void)(key); } while (0)
# define lockdep_set_class(lock, key) do { (void)(key); } while (0)
# define lockdep_set_class_and_name(lock, key, name) \
do { (void)(key); } while (0)
#define lockdep_set_class_and_subclass(lock, key, sub) \
do { (void)(key); } while (0)
#define lockdep_set_subclass(lock, sub) do { } while (0)
# define INIT_LOCKDEP
# define lockdep_reset() do { debug_locks = 1; } while (0)
# define lockdep_free_key_range(start, size) do { } while (0)
/*
* The class key takes no space if lockdep is disabled:
*/
struct lock_class_key { };
#define lockdep_depth(tsk) (0)
#endif /* !LOCKDEP */
#ifdef CONFIG_LOCK_STAT
extern void lock_contended(struct lockdep_map *lock, unsigned long ip);
extern void lock_acquired(struct lockdep_map *lock);
#define LOCK_CONTENDED(_lock, try, lock) \
do { \
if (!try(_lock)) { \
lock_contended(&(_lock)->dep_map, _RET_IP_); \
lock(_lock); \
} \
lock_acquired(&(_lock)->dep_map); \
} while (0)
#else /* CONFIG_LOCK_STAT */
#define lock_contended(lockdep_map, ip) do {} while (0)
#define lock_acquired(lockdep_map) do {} while (0)
#define LOCK_CONTENDED(_lock, try, lock) \
lock(_lock)
#endif /* CONFIG_LOCK_STAT */
#if defined(CONFIG_TRACE_IRQFLAGS) && defined(CONFIG_GENERIC_HARDIRQS)
extern void early_init_irq_lock_class(void);
#else
static inline void early_init_irq_lock_class(void)
{
}
#endif
#ifdef CONFIG_TRACE_IRQFLAGS
extern void early_boot_irqs_off(void);
extern void early_boot_irqs_on(void);
extern void print_irqtrace_events(struct task_struct *curr);
#else
static inline void early_boot_irqs_off(void)
{
}
static inline void early_boot_irqs_on(void)
{
}
static inline void print_irqtrace_events(struct task_struct *curr)
{
}
#endif
/*
* For trivial one-depth nesting of a lock-class, the following
* global define can be used. (Subsystems with multiple levels
* of nesting should define their own lock-nesting subclasses.)
*/
#define SINGLE_DEPTH_NESTING 1
/*
* Map the dependency ops to NOP or to real lockdep ops, depending
* on the per lock-class debug mode:
*/
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# ifdef CONFIG_PROVE_LOCKING
# define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i)
# else
# define spin_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i)
# endif
# define spin_release(l, n, i) lock_release(l, n, i)
#else
# define spin_acquire(l, s, t, i) do { } while (0)
# define spin_release(l, n, i) do { } while (0)
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# ifdef CONFIG_PROVE_LOCKING
# define rwlock_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i)
# define rwlock_acquire_read(l, s, t, i) lock_acquire(l, s, t, 2, 2, i)
# else
# define rwlock_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i)
# define rwlock_acquire_read(l, s, t, i) lock_acquire(l, s, t, 2, 1, i)
# endif
# define rwlock_release(l, n, i) lock_release(l, n, i)
#else
# define rwlock_acquire(l, s, t, i) do { } while (0)
# define rwlock_acquire_read(l, s, t, i) do { } while (0)
# define rwlock_release(l, n, i) do { } while (0)
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# ifdef CONFIG_PROVE_LOCKING
# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i)
# else
# define mutex_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i)
# endif
# define mutex_release(l, n, i) lock_release(l, n, i)
#else
# define mutex_acquire(l, s, t, i) do { } while (0)
# define mutex_release(l, n, i) do { } while (0)
#endif
#ifdef CONFIG_DEBUG_LOCK_ALLOC
# ifdef CONFIG_PROVE_LOCKING
# define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 2, i)
# define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 2, i)
# else
# define rwsem_acquire(l, s, t, i) lock_acquire(l, s, t, 0, 1, i)
# define rwsem_acquire_read(l, s, t, i) lock_acquire(l, s, t, 1, 1, i)
# endif
# define rwsem_release(l, n, i) lock_release(l, n, i)
#else
# define rwsem_acquire(l, s, t, i) do { } while (0)
# define rwsem_acquire_read(l, s, t, i) do { } while (0)
# define rwsem_release(l, n, i) do { } while (0)
#endif
#endif /* linux kernel < 2.6.18 */
#endif /* __LINUX_LOCKDEP_WRAPPER_H */

View File

@ -0,0 +1,17 @@
#ifndef __LINUX_LOG2_WRAPPER
#define __LINUX_LOG2_WRAPPER
#ifdef HAVE_LOG2_H
#include_next <linux/log2.h>
#else
/* This is very stripped down because log2.h has far too many dependencies. */
extern __attribute__((const, noreturn))
int ____ilog2_NaN(void);
#define ilog2(n) ((n) == 4 ? 2 : \
(n) == 8 ? 3 : \
____ilog2_NaN())
#endif
#endif

View File

@ -0,0 +1,59 @@
#ifndef __LINUX_MUTEX_WRAPPER_H
#define __LINUX_MUTEX_WRAPPER_H
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
#include <asm/semaphore.h>
struct mutex {
struct semaphore sema;
};
#define mutex_init(mutex) init_MUTEX(&(mutex)->sema)
#define mutex_destroy(mutex) do { } while (0)
#define __MUTEX_INITIALIZER(name) \
__SEMAPHORE_INITIALIZER(name,1)
#define DEFINE_MUTEX(mutexname) \
struct mutex mutexname = { __MUTEX_INITIALIZER(mutexname.sema) }
/*
* See kernel/mutex.c for detailed documentation of these APIs.
* Also see Documentation/mutex-design.txt.
*/
static inline void mutex_lock(struct mutex *lock)
{
down(&lock->sema);
}
static inline int mutex_lock_interruptible(struct mutex *lock)
{
return down_interruptible(&lock->sema);
}
#define mutex_lock_nested(lock, subclass) mutex_lock(lock)
#define mutex_lock_interruptible_nested(lock, subclass) mutex_lock_interruptible(lock)
/*
* NOTE: mutex_trylock() follows the spin_trylock() convention,
* not the down_trylock() convention!
*/
static inline int mutex_trylock(struct mutex *lock)
{
return !down_trylock(&lock->sema);
}
static inline void mutex_unlock(struct mutex *lock)
{
up(&lock->sema);
}
#else
#include_next <linux/mutex.h>
#endif /* linux version < 2.6.16 */
#endif

View File

@ -0,0 +1,35 @@
#ifndef __LINUX_NETDEVICE_WRAPPER_H
#define __LINUX_NETDEVICE_WRAPPER_H 1
#include_next <linux/netdevice.h>
struct net;
#ifndef to_net_dev
#define to_net_dev(class) container_of(class, struct net_device, class_dev)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
static inline
struct net *dev_net(const struct net_device *dev)
{
return NULL;
}
#endif /* linux kernel < 2.6.26 */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
#define proc_net init_net.proc_net
#endif
#ifndef for_each_netdev
/* Linux before 2.6.22 didn't have for_each_netdev at all. */
#define for_each_netdev(net, d) for (d = dev_base; d; d = d->next)
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
/* Linux 2.6.24 added a network namespace pointer to the macro. */
#undef for_each_netdev
#define for_each_netdev(net,d) list_for_each_entry(d, &dev_base_head, dev_list)
#endif
#endif

View File

@ -0,0 +1,24 @@
#ifndef __LINUX_NETFILTER_BRIDGE_WRAPPER_H
#define __LINUX_NETFILTER_BRIDGE_WRAPPER_H
#include_next <linux/netfilter_bridge.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
#include <linux/if_vlan.h>
#include <linux/if_pppox.h>
static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
{
switch (skb->protocol) {
case __constant_htons(ETH_P_8021Q):
return VLAN_HLEN;
default:
return 0;
}
}
#endif /* linux version < 2.6.22 */
#endif

View File

@ -0,0 +1,19 @@
#ifndef __LINUX_NETFILTER_IPV4_WRAPPER_H
#define __LINUX_NETFILTER_IPV4_WRAPPER_H 1
#include_next <linux/netfilter_ipv4.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
#ifdef __KERNEL__
#define NF_INET_PRE_ROUTING NF_IP_PRE_ROUTING
#define NF_INET_POST_ROUTING NF_IP_POST_ROUTING
#define NF_INET_FORWARD NF_IP_FORWARD
#endif /* __KERNEL__ */
#endif /* linux kernel < 2.6.25 */
#endif

View File

@ -0,0 +1,24 @@
#ifndef __LINUX_NETLINK_WRAPPER_H
#define __LINUX_NETLINK_WRAPPER_H 1
#include <linux/skbuff.h>
#include_next <linux/netlink.h>
#include <net/netlink.h>
#include <linux/version.h>
#ifndef NLMSG_DEFAULT_SIZE
#define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN)
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
#define nlmsg_new(s, f) nlmsg_new_proper((s), (f))
static inline struct sk_buff *nlmsg_new_proper(int size, gfp_t flags)
{
return alloc_skb(size, flags);
}
#endif /* linux kernel < 2.6.19 */
#endif

View File

@ -0,0 +1,10 @@
#ifndef __LINUX_PERCPU_H_WRAPPER
#define __LINUX_PERCPU_H_WRAPPER 1
#include_next <linux/percpu.h>
#ifndef percpu_ptr
#define percpu_ptr per_cpu_ptr
#endif
#endif /* linux/percpu.h wrapper */

View File

@ -0,0 +1,17 @@
#ifndef __LINUX_RANDOM_WRAPPER_H
#define __LINUX_RANDOM_WRAPPER_H 1
#include_next <linux/random.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
#ifdef __KERNEL__
u32 random32(void);
void srandom32(u32 seed);
#endif /* __KERNEL__ */
#endif /* linux kernel < 2.6.19 */
#endif

View File

@ -0,0 +1,12 @@
#ifndef __LINUX_RCULIST_WRAPPER_H
#define __LINUX_RCULIST_WRAPPER_H
#include <linux/version.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
#include_next <linux/rculist.h>
#else
/* Prior to 2.6.26, the contents of rculist.h were part of list.h. */
#include <linux/list.h>
#endif
#endif

View File

@ -0,0 +1,29 @@
#ifndef __RTNETLINK_WRAPPER_H
#define __RTNETLINK_WRAPPER_H 1
#include_next <linux/rtnetlink.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
static inline int rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid,
u32 group, struct nlmsghdr *nlh, gfp_t flags)
{
BUG_ON(nlh); /* not implemented */
if (group) {
/* errors reported via destination sk->sk_err */
nlmsg_multicast(rtnl, skb, 0, group);
}
return 0;
}
static inline void rtnl_set_sk_err(struct net *net, u32 group, int error)
{
netlink_set_err(rtnl, 0, group, error);
}
#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
#define rtnl_notify(skb, net, pid, group, nlh, flags) \
((void) (net), rtnl_notify(skb, pid, group, nlh, flags))
#define rtnl_set_sk_err(net, group, error) \
((void) (net), rtnl_set_sk_err(group, error))
#endif /* linux kernel < 2.6.25 */
#endif /* linux/rtnetlink.h wrapper */

View File

@ -0,0 +1,170 @@
#ifndef __LINUX_SKBUFF_WRAPPER_H
#define __LINUX_SKBUFF_WRAPPER_H 1
#include_next <linux/skbuff.h>
#include <linux/version.h>
#ifndef HAVE_SKB_COPY_FROM_LINEAR_DATA_OFFSET
static inline void skb_copy_from_linear_data_offset(const struct sk_buff *skb,
const int offset, void *to,
const unsigned int len)
{
memcpy(to, skb->data + offset, len);
}
static inline void skb_copy_to_linear_data_offset(struct sk_buff *skb,
const int offset,
const void *from,
const unsigned int len)
{
memcpy(skb->data + offset, from, len);
}
#endif /* !HAVE_SKB_COPY_FROM_LINEAR_DATA_OFFSET */
/*
* The networking layer reserves some headroom in skb data (via
* dev_alloc_skb). This is used to avoid having to reallocate skb data when
* the header has to grow. In the default case, if the header has to grow
* 16 bytes or less we avoid the reallocation.
*
* Unfortunately this headroom changes the DMA alignment of the resulting
* network packet. As for NET_IP_ALIGN, this unaligned DMA is expensive
* on some architectures. An architecture can override this value,
* perhaps setting it to a cacheline in size (since that will maintain
* cacheline alignment of the DMA). It must be a power of 2.
*
* Various parts of the networking layer expect at least 16 bytes of
* headroom, you should not reduce this.
*/
#ifndef NET_SKB_PAD
#define NET_SKB_PAD 16
#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
static inline int __skb_cow(struct sk_buff *skb, unsigned int headroom,
int cloned)
{
int delta = 0;
if (headroom < NET_SKB_PAD)
headroom = NET_SKB_PAD;
if (headroom > skb_headroom(skb))
delta = headroom - skb_headroom(skb);
if (delta || cloned)
return pskb_expand_head(skb, ALIGN(delta, NET_SKB_PAD), 0,
GFP_ATOMIC);
return 0;
}
static inline int skb_cow_head(struct sk_buff *skb, unsigned int headroom)
{
return __skb_cow(skb, headroom, skb_header_cloned(skb));
}
#endif /* linux < 2.6.23 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17)
/* Emulate Linux 2.6.17 and later behavior, in which kfree_skb silently ignores
* null pointer arguments. */
#define kfree_skb(skb) kfree_skb_maybe_null(skb)
static inline void kfree_skb_maybe_null(struct sk_buff *skb)
{
if (likely(skb != NULL))
(kfree_skb)(skb);
}
#endif
#ifndef CHECKSUM_PARTIAL
/* Note that CHECKSUM_PARTIAL is not implemented, but this allows us to at
* least test against it: see update_csum() in forward.c. */
#define CHECKSUM_PARTIAL 3
#endif
#ifndef CHECKSUM_COMPLETE
#define CHECKSUM_COMPLETE CHECKSUM_HW
#endif
#ifdef HAVE_MAC_RAW
#define mac_header mac.raw
#define network_header nh.raw
#endif
#ifndef HAVE_SKBUFF_HEADER_HELPERS
static inline unsigned char *skb_transport_header(const struct sk_buff *skb)
{
return skb->h.raw;
}
static inline void skb_reset_transport_header(struct sk_buff *skb)
{
skb->h.raw = skb->data;
}
static inline void skb_set_transport_header(struct sk_buff *skb,
const int offset)
{
skb->h.raw = skb->data + offset;
}
static inline unsigned char *skb_network_header(const struct sk_buff *skb)
{
return skb->nh.raw;
}
static inline void skb_set_network_header(struct sk_buff *skb, const int offset)
{
skb->nh.raw = skb->data + offset;
}
static inline unsigned char *skb_mac_header(const struct sk_buff *skb)
{
return skb->mac.raw;
}
static inline void skb_reset_mac_header(struct sk_buff *skb)
{
skb->mac_header = skb->data;
}
static inline void skb_set_mac_header(struct sk_buff *skb, const int offset)
{
skb->mac.raw = skb->data + offset;
}
static inline int skb_transport_offset(const struct sk_buff *skb)
{
return skb_transport_header(skb) - skb->data;
}
static inline int skb_network_offset(const struct sk_buff *skb)
{
return skb_network_header(skb) - skb->data;
}
static inline void skb_copy_to_linear_data(struct sk_buff *skb,
const void *from,
const unsigned int len)
{
memcpy(skb->data, from, len);
}
#endif /* !HAVE_SKBUFF_HEADER_HELPERS */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
#warning "TSO/UFO not supported on kernels earlier than 2.6.18"
static inline int skb_is_gso(const struct sk_buff *skb)
{
return 0;
}
static inline struct sk_buff *skb_gso_segment(struct sk_buff *skb,
int features)
{
return NULL;
}
#endif /* before 2.6.18 */
#endif

View File

@ -0,0 +1,18 @@
#ifndef __LINUX_TCP_WRAPPER_H
#define __LINUX_TCP_WRAPPER_H 1
#include_next <linux/tcp.h>
#ifndef HAVE_SKBUFF_HEADER_HELPERS
static inline struct tcphdr *tcp_hdr(const struct sk_buff *skb)
{
return (struct tcphdr *)skb_transport_header(skb);
}
static inline unsigned int tcp_hdrlen(const struct sk_buff *skb)
{
return tcp_hdr(skb)->doff * 4;
}
#endif /* !HAVE_SKBUFF_HEADER_HELPERS */
#endif

View File

@ -0,0 +1,96 @@
#ifndef __LINUX_TIMER_WRAPPER_H
#define __LINUX_TIMER_WRAPPER_H 1
#include_next <linux/timer.h>
#include <linux/version.h>
#ifndef RHEL_RELEASE_VERSION
#define RHEL_RELEASE_VERSION(X,Y) ( 0 )
#endif
#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) && \
(!defined(RHEL_RELEASE_CODE) || \
(RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(5,1))))
extern unsigned long volatile jiffies;
/**
* __round_jiffies - function to round jiffies to a full second
* @j: the time in (absolute) jiffies that should be rounded
* @cpu: the processor number on which the timeout will happen
*
* __round_jiffies() rounds an absolute time in the future (in jiffies)
* up or down to (approximately) full seconds. This is useful for timers
* for which the exact time they fire does not matter too much, as long as
* they fire approximately every X seconds.
*
* By rounding these timers to whole seconds, all such timers will fire
* at the same time, rather than at various times spread out. The goal
* of this is to have the CPU wake up less, which saves power.
*
* The exact rounding is skewed for each processor to avoid all
* processors firing at the exact same time, which could lead
* to lock contention or spurious cache line bouncing.
*
* The return value is the rounded version of the @j parameter.
*/
static inline unsigned long __round_jiffies(unsigned long j, int cpu)
{
int rem;
unsigned long original = j;
/*
* We don't want all cpus firing their timers at once hitting the
* same lock or cachelines, so we skew each extra cpu with an extra
* 3 jiffies. This 3 jiffies came originally from the mm/ code which
* already did this.
* The skew is done by adding 3*cpunr, then round, then subtract this
* extra offset again.
*/
j += cpu * 3;
rem = j % HZ;
/*
* If the target jiffie is just after a whole second (which can happen
* due to delays of the timer irq, long irq off times etc etc) then
* we should round down to the whole second, not up. Use 1/4th second
* as cutoff for this rounding as an extreme upper bound for this.
*/
if (rem < HZ/4) /* round down */
j = j - rem;
else /* round up */
j = j - rem + HZ;
/* now that we have rounded, subtract the extra skew again */
j -= cpu * 3;
if (j <= jiffies) /* rounding ate our timeout entirely; */
return original;
return j;
}
/**
* round_jiffies - function to round jiffies to a full second
* @j: the time in (absolute) jiffies that should be rounded
*
* round_jiffies() rounds an absolute time in the future (in jiffies)
* up or down to (approximately) full seconds. This is useful for timers
* for which the exact time they fire does not matter too much, as long as
* they fire approximately every X seconds.
*
* By rounding these timers to whole seconds, all such timers will fire
* at the same time, rather than at various times spread out. The goal
* of this is to have the CPU wake up less, which saves power.
*
* The return value is the rounded version of the @j parameter.
*/
static inline unsigned long round_jiffies(unsigned long j)
{
return __round_jiffies(j, 0); // FIXME
}
#endif /* linux kernel < 2.6.20 */
#endif

View File

@ -0,0 +1,14 @@
#ifndef __LINUX_TYPES_WRAPPER_H
#define __LINUX_TYPES_WRAPPER_H 1
#include_next <linux/types.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
typedef __u16 __bitwise __sum16;
typedef __u32 __bitwise __wsum;
#endif /* linux kernel < 2.6.20 */
#endif

View File

@ -0,0 +1,13 @@
#ifndef __LINUX_UDP_WRAPPER_H
#define __LINUX_UDP_WRAPPER_H 1
#include_next <linux/udp.h>
#ifndef HAVE_SKBUFF_HEADER_HELPERS
static inline struct udphdr *udp_hdr(const struct sk_buff *skb)
{
return (struct udphdr *)skb_transport_header(skb);
}
#endif /* HAVE_SKBUFF_HEADER_HELPERS */
#endif

View File

@ -0,0 +1,42 @@
#ifndef __LINUX_WORKQUEUE_WRAPPER_H
#define __LINUX_WORKQUEUE_WRAPPER_H 1
#include_next <linux/workqueue.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#ifdef __KERNEL__
/*
* initialize a work-struct's func and data pointers:
*/
#undef PREPARE_WORK
#define PREPARE_WORK(_work, _func) \
do { \
(_work)->func = (void(*)(void*)) _func; \
(_work)->data = _work; \
} while (0)
/*
* initialize all of a work-struct:
*/
#undef INIT_WORK
#define INIT_WORK(_work, _func) \
do { \
INIT_LIST_HEAD(&(_work)->entry); \
(_work)->pending = 0; \
PREPARE_WORK((_work), (_func)); \
init_timer(&(_work)->timer); \
} while (0)
#endif /* __KERNEL__ */
#endif /* linux kernel < 2.6.20 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
/* There is no equivalent to cancel_work_sync() so just flush all
* pending work. */
#define cancel_work_sync(_work) flush_scheduled_work()
#endif
#endif

View File

@ -0,0 +1,16 @@
#ifndef __NET_CHECKSUM_WRAPPER_H
#define __NET_CHECKSUM_WRAPPER_H 1
#include_next <net/checksum.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
static inline __wsum csum_unfold(__sum16 n)
{
return (__force __wsum)n;
}
#endif /* linux kernel < 2.6.20 */
#endif /* checksum.h */

View File

@ -0,0 +1,123 @@
#ifndef __NET_GENERIC_NETLINK_WRAPPER_H
#define __NET_GENERIC_NETLINK_WRAPPER_H 1
#include <linux/netlink.h>
#include_next <net/genetlink.h>
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
#include <linux/genetlink.h>
/*----------------------------------------------------------------------------
* In 2.6.23, registering of multicast groups was added. Our compatability
* layer just supports registering a single group, since that's all we
* need.
*/
/**
* struct genl_multicast_group - generic netlink multicast group
* @name: name of the multicast group, names are per-family
* @id: multicast group ID, assigned by the core, to use with
* genlmsg_multicast().
* @list: list entry for linking
* @family: pointer to family, need not be set before registering
*/
struct genl_multicast_group
{
struct genl_family *family; /* private */
struct list_head list; /* private */
char name[GENL_NAMSIZ];
u32 id;
};
int genl_register_mc_group(struct genl_family *family,
struct genl_multicast_group *grp);
#endif /* linux kernel < 2.6.23 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
/**
* genlmsg_msg_size - length of genetlink message not including padding
* @payload: length of message payload
*/
static inline int genlmsg_msg_size(int payload)
{
return GENL_HDRLEN + payload;
}
/**
* genlmsg_total_size - length of genetlink message including padding
* @payload: length of message payload
*/
static inline int genlmsg_total_size(int payload)
{
return NLMSG_ALIGN(genlmsg_msg_size(payload));
}
#define genlmsg_multicast(s, p, g, f) \
genlmsg_multicast_flags((s), (p), (g), (f))
static inline int genlmsg_multicast_flags(struct sk_buff *skb, u32 pid,
unsigned int group, gfp_t flags)
{
int err;
NETLINK_CB(skb).dst_group = group;
err = netlink_broadcast(genl_sock, skb, pid, group, flags);
if (err > 0)
err = 0;
return err;
}
#endif /* linux kernel < 2.6.19 */
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
#define genlmsg_put(skb, p, seq, fam, flg, c) \
genlmsg_put((skb), (p), (seq), (fam)->id, (fam)->hdrsize, \
(flg), (c), (fam)->version)
/**
* genlmsg_put_reply - Add generic netlink header to a reply message
* @skb: socket buffer holding the message
* @info: receiver info
* @family: generic netlink family
* @flags: netlink message flags
* @cmd: generic netlink command
*
* Returns pointer to user specific header
*/
static inline void *genlmsg_put_reply(struct sk_buff *skb,
struct genl_info *info, struct genl_family *family,
int flags, u8 cmd)
{
return genlmsg_put(skb, info->snd_pid, info->snd_seq, family,
flags, cmd);
}
/**
* genlmsg_reply - reply to a request
* @skb: netlink message to be sent back
* @info: receiver information
*/
static inline int genlmsg_reply(struct sk_buff *skb, struct genl_info *info)
{
return genlmsg_unicast(skb, info->snd_pid);
}
/**
* genlmsg_new - Allocate a new generic netlink message
* @payload: size of the message payload
* @flags: the type of memory to allocate.
*/
static inline struct sk_buff *genlmsg_new(size_t payload, gfp_t flags)
{
return nlmsg_new(genlmsg_total_size(payload), flags);
}
#endif /* linux kernel < 2.6.20 */
#endif /* genetlink.h */

View File

@ -0,0 +1,22 @@
#ifndef __NET_NETLINK_WRAPPER_H
#define __NET_NETLINK_WRAPPER_H 1
#include_next <net/netlink.h>
#ifndef HAVE_NLA_NUL_STRING
#define NLA_NUL_STRING NLA_STRING
static inline int VERIFY_NUL_STRING(struct nlattr *attr)
{
return (!attr || (nla_len(attr)
&& memchr(nla_data(attr), '\0', nla_len(attr)))
? 0 : EINVAL);
}
#else
static inline int VERIFY_NUL_STRING(struct nlattr *attr)
{
return 0;
}
#endif /* !HAVE_NLA_NUL_STRING */
#endif /* net/netlink.h */

View File

@ -0,0 +1,144 @@
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19)
/*
This is a maximally equidistributed combined Tausworthe generator
based on code from GNU Scientific Library 1.5 (30 Jun 2004)
x_n = (s1_n ^ s2_n ^ s3_n)
s1_{n+1} = (((s1_n & 4294967294) <<12) ^ (((s1_n <<13) ^ s1_n) >>19))
s2_{n+1} = (((s2_n & 4294967288) << 4) ^ (((s2_n << 2) ^ s2_n) >>25))
s3_{n+1} = (((s3_n & 4294967280) <<17) ^ (((s3_n << 3) ^ s3_n) >>11))
The period of this generator is about 2^88.
From: P. L'Ecuyer, "Maximally Equidistributed Combined Tausworthe
Generators", Mathematics of Computation, 65, 213 (1996), 203--213.
This is available on the net from L'Ecuyer's home page,
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme.ps
ftp://ftp.iro.umontreal.ca/pub/simulation/lecuyer/papers/tausme.ps
There is an erratum in the paper "Tables of Maximally
Equidistributed Combined LFSR Generators", Mathematics of
Computation, 68, 225 (1999), 261--269:
http://www.iro.umontreal.ca/~lecuyer/myftp/papers/tausme2.ps
... the k_j most significant bits of z_j must be non-
zero, for each j. (Note: this restriction also applies to the
computer code given in [4], but was mistakenly not mentioned in
that paper.)
This affects the seeding procedure by imposing the requirement
s1 > 1, s2 > 7, s3 > 15.
*/
#include <linux/types.h>
#include <linux/module.h>
#include <linux/jiffies.h>
#include <linux/random.h>
#include <linux/smp.h>
#include "compat26.h"
struct rnd_state {
u32 s1, s2, s3;
};
static struct rnd_state net_rand_state[NR_CPUS];
static u32 __random32(struct rnd_state *state)
{
#define TAUSWORTHE(s,a,b,c,d) ((s&c)<<d) ^ (((s <<a) ^ s)>>b)
state->s1 = TAUSWORTHE(state->s1, 13, 19, 4294967294UL, 12);
state->s2 = TAUSWORTHE(state->s2, 2, 25, 4294967288UL, 4);
state->s3 = TAUSWORTHE(state->s3, 3, 11, 4294967280UL, 17);
return (state->s1 ^ state->s2 ^ state->s3);
}
static void __set_random32(struct rnd_state *state, unsigned long s)
{
if (s == 0)
s = 1; /* default seed is 1 */
#define LCG(n) (69069 * n)
state->s1 = LCG(s);
state->s2 = LCG(state->s1);
state->s3 = LCG(state->s2);
/* "warm it up" */
__random32(state);
__random32(state);
__random32(state);
__random32(state);
__random32(state);
__random32(state);
}
/**
* random32 - pseudo random number generator
*
* A 32 bit pseudo-random number is generated using a fast
* algorithm suitable for simulation. This algorithm is NOT
* considered safe for cryptographic use.
*/
u32 random32(void)
{
return __random32(&net_rand_state[smp_processor_id()]);
}
/**
* srandom32 - add entropy to pseudo random number generator
* @seed: seed value
*
* Add some additional seeding to the random32() pool.
* Note: this pool is per cpu so it only affects current CPU.
*/
void srandom32(u32 entropy)
{
struct rnd_state *state = &net_rand_state[smp_processor_id()];
__set_random32(state, state->s1 ^ entropy);
}
static int __init random32_reseed(void);
/*
* Generate some initially weak seeding values to allow
* to start the random32() engine.
*/
int __init random32_init(void)
{
int i;
for (i = 0; i < NR_CPUS; i++) {
struct rnd_state *state = &net_rand_state[i];
__set_random32(state, i + jiffies);
}
random32_reseed();
return 0;
}
/*
* Generate better values after random number generator
* is fully initalized.
*/
static int __init random32_reseed(void)
{
int i;
unsigned long seed;
for (i = 0; i < NR_CPUS; i++) {
struct rnd_state *state = &net_rand_state[i];
get_random_bytes(&seed, sizeof(seed));
__set_random32(state, seed);
}
return 0;
}
#endif /* kernel < 2.6.19 */

View File

@ -0,0 +1,537 @@
/* veth driver port to Linux 2.6.18 */
/*
* drivers/net/veth.c
*
* Copyright (C) 2007, 2009 OpenVZ http://openvz.org, SWsoft Inc
*
* Author: Pavel Emelianov <xemul@openvz.org>
* Ethtool interface from: Eric W. Biederman <ebiederm@xmission.com>
*
*/
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/ethtool.h>
#include <linux/etherdevice.h>
#include <net/dst.h>
#include <net/xfrm.h>
#define DRV_NAME "veth"
#define DRV_VERSION "1.0"
struct veth_net_stats {
unsigned long rx_packets;
unsigned long tx_packets;
unsigned long rx_bytes;
unsigned long tx_bytes;
unsigned long tx_dropped;
};
struct veth_priv {
struct net_device *peer;
struct net_device *dev;
struct list_head list;
struct veth_net_stats *stats;
unsigned ip_summed;
struct net_device_stats dev_stats;
};
static LIST_HEAD(veth_list);
/*
* ethtool interface
*/
static struct {
const char string[ETH_GSTRING_LEN];
} ethtool_stats_keys[] = {
{ "peer_ifindex" },
};
static int veth_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
{
cmd->supported = 0;
cmd->advertising = 0;
cmd->speed = SPEED_10000;
cmd->duplex = DUPLEX_FULL;
cmd->port = PORT_TP;
cmd->phy_address = 0;
cmd->transceiver = XCVR_INTERNAL;
cmd->autoneg = AUTONEG_DISABLE;
cmd->maxtxpkt = 0;
cmd->maxrxpkt = 0;
return 0;
}
static void veth_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
{
strcpy(info->driver, DRV_NAME);
strcpy(info->version, DRV_VERSION);
strcpy(info->fw_version, "N/A");
}
static void veth_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
{
switch(stringset) {
case ETH_SS_STATS:
memcpy(buf, &ethtool_stats_keys, sizeof(ethtool_stats_keys));
break;
}
}
static void veth_get_ethtool_stats(struct net_device *dev,
struct ethtool_stats *stats, u64 *data)
{
struct veth_priv *priv;
priv = netdev_priv(dev);
data[0] = priv->peer->ifindex;
}
static u32 veth_get_rx_csum(struct net_device *dev)
{
struct veth_priv *priv;
priv = netdev_priv(dev);
return priv->ip_summed == CHECKSUM_UNNECESSARY;
}
static int veth_set_rx_csum(struct net_device *dev, u32 data)
{
struct veth_priv *priv;
priv = netdev_priv(dev);
priv->ip_summed = data ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
return 0;
}
static u32 veth_get_tx_csum(struct net_device *dev)
{
return (dev->features & NETIF_F_NO_CSUM) != 0;
}
static int veth_set_tx_csum(struct net_device *dev, u32 data)
{
if (data)
dev->features |= NETIF_F_NO_CSUM;
else
dev->features &= ~NETIF_F_NO_CSUM;
return 0;
}
static struct ethtool_ops veth_ethtool_ops = {
.get_settings = veth_get_settings,
.get_drvinfo = veth_get_drvinfo,
.get_link = ethtool_op_get_link,
.get_rx_csum = veth_get_rx_csum,
.set_rx_csum = veth_set_rx_csum,
.get_tx_csum = veth_get_tx_csum,
.set_tx_csum = veth_set_tx_csum,
.get_sg = ethtool_op_get_sg,
.set_sg = ethtool_op_set_sg,
.get_strings = veth_get_strings,
.get_ethtool_stats = veth_get_ethtool_stats,
};
/*
* xmit
*/
static int veth_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct net_device *rcv = NULL;
struct veth_priv *priv, *rcv_priv;
struct veth_net_stats *stats;
int length, cpu;
skb_orphan(skb);
priv = netdev_priv(dev);
rcv = priv->peer;
rcv_priv = netdev_priv(rcv);
cpu = smp_processor_id();
stats = per_cpu_ptr(priv->stats, cpu);
if (!(rcv->flags & IFF_UP))
goto outf;
skb->dev = rcv;
skb->pkt_type = PACKET_HOST;
skb->protocol = eth_type_trans(skb, rcv);
if (dev->features & NETIF_F_NO_CSUM)
skb->ip_summed = rcv_priv->ip_summed;
dst_release(skb->dst);
skb->dst = NULL;
secpath_reset(skb);
nf_reset(skb);
length = skb->len;
stats->tx_bytes += length;
stats->tx_packets++;
stats = per_cpu_ptr(rcv_priv->stats, cpu);
stats->rx_bytes += length;
stats->rx_packets++;
netif_rx(skb);
return 0;
outf:
kfree_skb(skb);
stats->tx_dropped++;
return 0;
}
/*
* general routines
*/
static struct net_device_stats *veth_get_stats(struct net_device *dev)
{
struct veth_priv *priv;
struct net_device_stats *dev_stats;
int cpu;
struct veth_net_stats *stats;
priv = netdev_priv(dev);
dev_stats = &priv->dev_stats;
dev_stats->rx_packets = 0;
dev_stats->tx_packets = 0;
dev_stats->rx_bytes = 0;
dev_stats->tx_bytes = 0;
dev_stats->tx_dropped = 0;
for_each_online_cpu(cpu) {
stats = per_cpu_ptr(priv->stats, cpu);
dev_stats->rx_packets += stats->rx_packets;
dev_stats->tx_packets += stats->tx_packets;
dev_stats->rx_bytes += stats->rx_bytes;
dev_stats->tx_bytes += stats->tx_bytes;
dev_stats->tx_dropped += stats->tx_dropped;
}
return dev_stats;
}
static int veth_open(struct net_device *dev)
{
struct veth_priv *priv;
priv = netdev_priv(dev);
if (priv->peer == NULL)
return -ENOTCONN;
if (priv->peer->flags & IFF_UP) {
netif_carrier_on(dev);
netif_carrier_on(priv->peer);
}
return 0;
}
static int veth_dev_init(struct net_device *dev)
{
struct veth_net_stats *stats;
struct veth_priv *priv;
stats = alloc_percpu(struct veth_net_stats);
if (stats == NULL)
return -ENOMEM;
priv = netdev_priv(dev);
priv->stats = stats;
return 0;
}
static void veth_dev_free(struct net_device *dev)
{
struct veth_priv *priv;
priv = netdev_priv(dev);
free_percpu(priv->stats);
free_netdev(dev);
}
static void veth_setup(struct net_device *dev)
{
ether_setup(dev);
dev->hard_start_xmit = veth_xmit;
dev->get_stats = veth_get_stats;
dev->open = veth_open;
dev->ethtool_ops = &veth_ethtool_ops;
dev->features |= NETIF_F_LLTX;
dev->init = veth_dev_init;
dev->destructor = veth_dev_free;
}
static void veth_change_state(struct net_device *dev)
{
struct net_device *peer;
struct veth_priv *priv;
priv = netdev_priv(dev);
peer = priv->peer;
if (netif_carrier_ok(peer)) {
if (!netif_carrier_ok(dev))
netif_carrier_on(dev);
} else {
if (netif_carrier_ok(dev))
netif_carrier_off(dev);
}
}
static int veth_device_event(struct notifier_block *unused,
unsigned long event, void *ptr)
{
struct net_device *dev = ptr;
if (dev->open != veth_open)
goto out;
switch (event) {
case NETDEV_CHANGE:
veth_change_state(dev);
break;
}
out:
return NOTIFY_DONE;
}
static struct notifier_block veth_notifier_block __read_mostly = {
.notifier_call = veth_device_event,
};
/*
* netlink interface
*/
static int veth_newlink(const char *devname, const char *peername)
{
int err;
const char *names[2];
struct net_device *devs[2];
int i;
names[0] = devname;
names[1] = peername;
devs[0] = devs[1] = NULL;
for (i = 0; i < 2; i++) {
struct net_device *dev;
err = -ENOMEM;
devs[i] = alloc_netdev(sizeof(struct veth_priv),
names[i], veth_setup);
if (!devs[i]) {
goto err;
}
dev = devs[i];
if (strchr(dev->name, '%')) {
err = dev_alloc_name(dev, dev->name);
if (err < 0)
goto err;
}
random_ether_addr(dev->dev_addr);
err = register_netdevice(dev);
if (err < 0)
goto err;
netif_carrier_off(dev);
}
/*
* tie the devices together
*/
for (i = 0; i < 2; i++) {
struct veth_priv *priv = netdev_priv(devs[i]);
priv->dev = devs[i];
priv->peer = devs[!i];
if (!i)
list_add(&priv->list, &veth_list);
else
INIT_LIST_HEAD(&priv->list);
}
return 0;
err:
for (i = 0; i < 2; i++) {
if (devs[i]) {
if (devs[i]->reg_state != NETREG_UNINITIALIZED)
unregister_netdevice(devs[i]);
else
free_netdev(devs[i]);
}
}
return err;
}
static void veth_dellink(struct net_device *dev)
{
struct veth_priv *priv;
struct net_device *peer;
priv = netdev_priv(dev);
peer = priv->peer;
if (!list_empty(&priv->list))
list_del(&priv->list);
priv = netdev_priv(peer);
if (!list_empty(&priv->list))
list_del(&priv->list);
unregister_netdevice(dev);
unregister_netdevice(peer);
}
/*
* sysfs
*/
/*
* "show" function for the veth_pairs attribute.
* The class parameter is ignored.
*/
static ssize_t veth_show_veth_pairs(struct class *cls, char *buffer)
{
int res = 0;
struct veth_priv *priv;
list_for_each_entry(priv, &veth_list, list) {
if (res > (PAGE_SIZE - (IFNAMSIZ * 2 + 1))) {
/* not enough space for another interface name */
if ((PAGE_SIZE - res) > 10)
res = PAGE_SIZE - 10;
res += sprintf(buffer + res, "++more++");
break;
}
res += sprintf(buffer + res, "%s,%s ",
priv->dev->name, priv->peer->name);
}
res += sprintf(buffer + res, "\n");
res++;
return res;
}
/*
* "store" function for the veth_pairs attribute. This is what
* creates and deletes veth pairs.
*
* The class parameter is ignored.
*
*/
static ssize_t veth_store_veth_pairs(struct class *cls, const char *buffer,
size_t count)
{
int c = *buffer++;
int retval;
printk("1\n");
if (c == '+') {
char devname[IFNAMSIZ + 1] = "";
char peername[IFNAMSIZ + 1] = "";
char *comma = strchr(buffer, ',');
printk("2\n");
if (!comma)
goto err_no_cmd;
strncat(devname, buffer,
min_t(int, sizeof devname, comma - buffer));
strncat(peername, comma + 1,
min_t(int, sizeof peername, strcspn(comma + 1, "\n")));
printk("3 '%s' '%s'\n", devname, peername);
if (!dev_valid_name(devname) || !dev_valid_name(peername))
goto err_no_cmd;
printk("4\n");
rtnl_lock();
retval = veth_newlink(devname, peername);
rtnl_unlock();
return retval ? retval : count;
} else if (c == '-') {
struct net_device *dev;
rtnl_lock();
dev = dev_get_by_name(buffer);
if (!dev)
retval = -ENODEV;
else if (dev->init != veth_dev_init)
retval = -EINVAL;
else {
veth_dellink(dev);
retval = count;
}
rtnl_unlock();
return retval;
}
err_no_cmd:
printk(KERN_ERR DRV_NAME ": no command found in veth_pairs. Use +ifname,peername or -ifname.\n");
return -EPERM;
}
/* class attribute for veth_pairs file. This ends up in /sys/class/net */
static CLASS_ATTR(veth_pairs, S_IWUSR | S_IRUGO,
veth_show_veth_pairs, veth_store_veth_pairs);
static struct class *netdev_class;
/*
* Initialize sysfs. This sets up the veth_pairs file in
* /sys/class/net.
*/
int veth_create_sysfs(void)
{
struct net_device *dev = dev_get_by_name("lo");
if (!dev)
return -ESRCH;
netdev_class = dev->class_dev.class;
if (!netdev_class)
return -ENODEV;
return class_create_file(netdev_class, &class_attr_veth_pairs);
}
/*
* Remove /sys/class/net/veth_pairs.
*/
void veth_destroy_sysfs(void)
{
class_remove_file(netdev_class, &class_attr_veth_pairs);
}
/*
* init/fini
*/
static __init int veth_init(void)
{
int retval = veth_create_sysfs();
if (retval)
return retval;
register_netdevice_notifier(&veth_notifier_block);
return 0;
}
static __exit void veth_exit(void)
{
unregister_netdevice_notifier(&veth_notifier_block);
}
module_init(veth_init);
module_exit(veth_exit);
MODULE_DESCRIPTION("Virtual Ethernet Tunnel");
MODULE_LICENSE("GPL v2");

File diff suppressed because it is too large Load Diff

240
datapath/table.c Normal file
View File

@ -0,0 +1,240 @@
#include "flow.h"
#include "datapath.h"
#include <linux/gfp.h>
#include <linux/jhash.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/highmem.h>
#include <asm/pgtable.h>
static void free_table(struct sw_flow ***flows, unsigned int n_buckets,
int free_flows)
{
unsigned int i;
for (i = 0; i < n_buckets >> DP_L1_BITS; i++) {
struct sw_flow **l2 = flows[i];
if (free_flows) {
unsigned int j;
for (j = 0; j < DP_L1_SIZE; j++) {
if (l2[j])
flow_free(l2[j]);
}
}
free_page((unsigned long)l2);
}
kfree(flows);
}
static struct sw_flow ***alloc_table(unsigned int n_buckets)
{
struct sw_flow ***flows;
unsigned int i;
flows = kmalloc((n_buckets >> DP_L1_BITS) * sizeof(struct sw_flow**),
GFP_KERNEL);
if (!flows)
return NULL;
for (i = 0; i < n_buckets >> DP_L1_BITS; i++) {
flows[i] = (struct sw_flow **)get_zeroed_page(GFP_KERNEL);
if (!flows[i]) {
free_table(flows, i << DP_L1_BITS, 0);
return NULL;
}
}
return flows;
}
struct dp_table *dp_table_create(unsigned int n_buckets)
{
struct dp_table *table;
table = kzalloc(sizeof *table, GFP_KERNEL);
if (!table)
goto err;
table->n_buckets = n_buckets;
table->flows[0] = alloc_table(n_buckets);
if (!table[0].flows)
goto err_free_tables;
table->flows[1] = alloc_table(n_buckets);
if (!table->flows[1])
goto err_free_flows0;
return table;
err_free_flows0:
free_table(table->flows[0], table->n_buckets, 0);
err_free_tables:
kfree(table);
err:
return NULL;
}
void dp_table_destroy(struct dp_table *table, int free_flows)
{
int i;
for (i = 0; i < 2; i++)
free_table(table->flows[i], table->n_buckets, free_flows);
kfree(table);
}
static struct sw_flow **find_bucket(struct dp_table *table,
struct sw_flow ***flows, u32 hash)
{
unsigned int l1 = (hash & (table->n_buckets - 1)) >> DP_L1_SHIFT;
unsigned int l2 = hash & ((1 << DP_L2_BITS) - 1);
return &flows[l1][l2];
}
static struct sw_flow *lookup_table(struct dp_table *table,
struct sw_flow ***flows, u32 hash,
const struct odp_flow_key *key)
{
struct sw_flow **bucket = find_bucket(table, flows, hash);
struct sw_flow *flow = rcu_dereference(*bucket);
if (flow && !memcmp(&flow->key, key, sizeof(struct odp_flow_key)))
return flow;
return NULL;
}
static u32 flow_hash0(const struct odp_flow_key *key)
{
return jhash2((u32*)key, sizeof *key / sizeof(u32), 0xaaaaaaaa);
}
static u32 flow_hash1(const struct odp_flow_key *key)
{
return jhash2((u32*)key, sizeof *key / sizeof(u32), 0x55555555);
}
static void find_buckets(struct dp_table *table,
const struct odp_flow_key *key,
struct sw_flow **buckets[2])
{
buckets[0] = find_bucket(table, table->flows[0], flow_hash0(key));
buckets[1] = find_bucket(table, table->flows[1], flow_hash1(key));
}
struct sw_flow *dp_table_lookup(struct dp_table *table,
const struct odp_flow_key *key)
{
struct sw_flow *flow;
flow = lookup_table(table, table->flows[0], flow_hash0(key), key);
if (!flow)
flow = lookup_table(table, table->flows[1],
flow_hash1(key), key);
return flow;
}
int dp_table_foreach(struct dp_table *table,
int (*callback)(struct sw_flow *flow, void *aux),
void *aux)
{
unsigned int i, j, k;
for (i = 0; i < 2; i++) {
for (j = 0; j < table->n_buckets >> DP_L1_BITS; j++) {
struct sw_flow **l2 = table->flows[i][j];
for (k = 0; k < DP_L1_SIZE; k++) {
struct sw_flow *flow = rcu_dereference(l2[k]);
if (flow) {
int error = callback(flow, aux);
if (error)
return error;
}
}
}
}
return 0;
}
static int insert_flow(struct sw_flow *flow, void *new_table_)
{
struct dp_table *new_table = new_table_;
struct sw_flow **buckets[2];
int i;
find_buckets(new_table, &flow->key, buckets);
for (i = 0; i < 2; i++) {
if (!*buckets[i]) {
rcu_assign_pointer(*buckets[i], flow);
return 0;
}
}
WARN_ON_ONCE(1);
return 0;
}
static void dp_free_table_rcu(struct rcu_head *rcu)
{
struct dp_table *table = container_of(rcu, struct dp_table, rcu);
dp_table_destroy(table, 0);
}
int dp_table_expand(struct datapath *dp)
{
struct dp_table *old_table = rcu_dereference(dp->table);
struct dp_table *new_table = dp_table_create(old_table->n_buckets * 2);
if (!new_table)
return -ENOMEM;
dp_table_foreach(old_table, insert_flow, new_table);
rcu_assign_pointer(dp->table, new_table);
call_rcu(&old_table->rcu, dp_free_table_rcu);
return 0;
}
static void dp_free_table_and_flows_rcu(struct rcu_head *rcu)
{
struct dp_table *table = container_of(rcu, struct dp_table, rcu);
dp_table_destroy(table, 1);
}
int dp_table_flush(struct datapath *dp)
{
struct dp_table *old_table = rcu_dereference(dp->table);
struct dp_table *new_table = dp_table_create(DP_L1_SIZE);
if (!new_table)
return -ENOMEM;
rcu_assign_pointer(dp->table, new_table);
call_rcu(&old_table->rcu, dp_free_table_and_flows_rcu);
return 0;
}
struct sw_flow **
dp_table_lookup_for_insert(struct dp_table *table,
const struct odp_flow_key *target)
{
struct sw_flow **buckets[2];
struct sw_flow **empty_bucket = NULL;
int i;
find_buckets(table, target, buckets);
for (i = 0; i < 2; i++) {
struct sw_flow *f = rcu_dereference(*buckets[i]);
if (f) {
if (!memcmp(&f->key, target, sizeof(struct odp_flow_key)))
return buckets[i];
} else if (!empty_bucket)
empty_bucket = buckets[i];
}
return empty_bucket;
}
int dp_table_delete(struct dp_table *table, struct sw_flow *target)
{
struct sw_flow **buckets[2];
int i;
find_buckets(table, &target->key, buckets);
for (i = 0; i < 2; i++) {
struct sw_flow *flow = rcu_dereference(*buckets[i]);
if (flow == target) {
rcu_assign_pointer(*buckets[i], NULL);
return 0;
}
}
return -ENOENT;
}

19
debian/.gitignore vendored Normal file
View File

@ -0,0 +1,19 @@
*.debhelper
*.debhelper.log
*.substvars
/control
/corekeeper
/files
/nicira-switch
/openvswitch
/openvswitch-common
/openvswitch-common.copyright
/openvswitch-controller
/openvswitch-datapath-source
/openvswitch-dbg
/openvswitch-monitor
/openvswitch-pki
/openvswitch-pki-server
/openvswitch-switch
/openvswitch-switch-config
/openvswitch-switch.copyright

50
debian/automake.mk vendored Normal file
View File

@ -0,0 +1,50 @@
EXTRA_DIST += \
debian/changelog \
debian/commands/reconfigure \
debian/commands/update \
debian/compat \
debian/control \
debian/control.modules.in \
debian/copyright \
debian/corekeeper.cron.daily \
debian/corekeeper.init \
debian/dirs \
debian/ovs-switch-setup \
debian/ovs-switch-setup.8 \
debian/openvswitch-common.dirs \
debian/openvswitch-common.install \
debian/openvswitch-common.manpages \
debian/openvswitch-controller.README.Debian \
debian/openvswitch-controller.default \
debian/openvswitch-controller.dirs \
debian/openvswitch-controller.init \
debian/openvswitch-controller.install \
debian/openvswitch-controller.manpages \
debian/openvswitch-controller.postinst \
debian/openvswitch-datapath-module-_KVERS_.postinst.modules.in \
debian/openvswitch-datapath-source.README.Debian \
debian/openvswitch-datapath-source.copyright \
debian/openvswitch-datapath-source.dirs \
debian/openvswitch-datapath-source.install \
debian/openvswitch-pki-server.apache2 \
debian/openvswitch-pki-server.dirs \
debian/openvswitch-pki-server.install \
debian/openvswitch-pki-server.postinst \
debian/openvswitch-pki.postinst \
debian/openvswitch-switch-config.dirs \
debian/openvswitch-switch-config.install \
debian/openvswitch-switch-config.manpages \
debian/openvswitch-switch-config.overrides \
debian/openvswitch-switch-config.templates \
debian/openvswitch-switch.README.Debian \
debian/openvswitch-switch.dirs \
debian/openvswitch-switch.init \
debian/openvswitch-switch.install \
debian/openvswitch-switch.logrotate \
debian/openvswitch-switch.manpages \
debian/openvswitch-switch.postinst \
debian/openvswitch-switch.postrm \
debian/openvswitch-switch.template \
debian/po/POTFILES.in \
debian/po/templates.pot \
debian/rules

5
debian/changelog vendored Normal file
View File

@ -0,0 +1,5 @@
openvswitch (0.90.0) unstable; urgency=low
* Development version.
-- Open vSwitch developers <ovs-dev@openvswitch.org> Mon, 19 Nov 2007 14:57:52 -0800

128
debian/commands/reconfigure vendored Executable file
View File

@ -0,0 +1,128 @@
#! /usr/bin/perl
use POSIX;
use strict;
use warnings;
my $default = '/etc/default/openvswitch-switch';
my (%config) = load_config($default);
if (@ARGV) {
foreach my $arg (@ARGV) {
my ($key, $value) = $arg =~ /^([^=]+)=(.*)/
or die "bad argument '$arg'\n";
if ($value ne '') {
$config{$key} = $value;
} else {
delete $config{$key};
}
}
save_config($default, %config);
}
print "$_=$config{$_}\n" foreach sort(keys(%config));
sub load_config {
my ($file) = @_;
# Get the list of the variables that the shell sets automatically.
my (%auto_vars) = read_vars("set -a && env");
# Get the variables from $default.
my (%config) = read_vars("set -a && . '$default' && env");
# Subtract.
delete @config{keys %auto_vars};
return %config;
}
sub read_vars {
my ($cmd) = @_;
local @ENV;
if (!open(VARS, '-|', $cmd)) {
print STDERR "$cmd: failed to execute: $!\n";
return ();
}
my (%config);
while (<VARS>) {
my ($var, $value) = /^([^=]+)=(.*)$/ or next;
$config{$var} = $value;
}
close(VARS);
return %config;
}
sub shell_escape {
local $_ = $_[0];
if ($_ eq '') {
return '""';
} elsif (m&^[-a-zA-Z0-9:./%^_+,]*$&) {
return $_;
} else {
s/'/'\\''/;
return "'$_'";
}
}
sub shell_assign {
my ($var, $value) = @_;
return $var . '=' . shell_escape($value);
}
sub save_config {
my ($file, %config) = @_;
my (@lines);
if (open(FILE, '<', $file)) {
@lines = <FILE>;
chomp @lines;
close(FILE);
}
# Replace all existing variable assignments.
for (my ($i) = 0; $i <= $#lines; $i++) {
local $_ = $lines[$i];
my ($var, $value) = /^\s*([^=#]+)=(.*)$/ or next;
if (exists($config{$var})) {
$lines[$i] = shell_assign($var, $config{$var});
delete $config{$var};
} else {
$lines[$i] = "#$lines[$i]";
}
}
# Find a place to put any remaining variable assignments.
VAR:
for my $var (keys(%config)) {
my $assign = shell_assign($var, $config{$var});
# Replace the last commented-out variable assignment to $var, if any.
for (my ($i) = $#lines; $i >= 0; $i--) {
local $_ = $lines[$i];
if (/^\s*#\s*$var=/) {
$lines[$i] = $assign;
next VAR;
}
}
# Find a place to add the var: after the final commented line
# just after a line that contains "$var:".
for (my ($i) = 0; $i <= $#lines; $i++) {
if ($lines[$i] =~ /^\s*#\s*$var:/) {
for (my ($j) = $i + 1; $j <= $#lines; $j++) {
if ($lines[$j] !~ /^\s*#/) {
splice(@lines, $j, 0, $assign);
next VAR;
}
}
}
}
# Just append it.
push(@lines, $assign);
}
open(NEWFILE, '>', "$file.tmp") or die "$file.tmp: create: $!\n";
print NEWFILE join('', map("$_\n", @lines));
close(NEWFILE);
rename("$file.tmp", $file) or die "$file.tmp: rename to $file: $!\n";
}

4
debian/commands/update vendored Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
set -e
apt-get update -qy
apt-get upgrade -qy

1
debian/compat vendored Normal file
View File

@ -0,0 +1 @@
5

143
debian/control vendored Normal file
View File

@ -0,0 +1,143 @@
Source: openvswitch
Section: net
Priority: extra
Maintainer: Open vSwitch developers <ovs-dev@openvswitch.org>
Build-Depends: debhelper (>= 5), autoconf (>= 2.60), automake1.10, libssl-dev, pkg-config (>= 0.21), po-debconf, bzip2, openssl, libncurses5-dev, libpcre3-dev
Standards-Version: 3.7.3
Package: openvswitch-datapath-source
Architecture: all
Depends: module-assistant, bzip2, debhelper (>= 5.0.37)
Suggests: openvswitch-switch
Description: Source code for Open vSwitch datapath Linux module
This package provides the Open vSwitch datapath module source code
that is needed by openvswitch-switch. The kernel module can be built
from it using module-assistant or make-kpkg. README.Debian in this
package provides further instructions.
.
Open vSwitch is a software-based Ethernet switch targeted at virtual
servers.
Package: openvswitch-common
Architecture: any
Depends: ${shlibs:Depends}, openssl
Description: Open vSwitch common components
openvswitch-common provides components required by both openvswitch-switch
and openvswitch-controller.
.
Open vSwitch is a software-based Ethernet switch targeted at virtual
servers.
Package: openvswitch-switch
Architecture: any
Suggests: openvswitch-datapath-module
Depends: ${shlibs:Depends}, ${misc:Depends}, openvswitch-common, dhcp3-client, module-init-tools, dmidecode, procps, debianutils
Description: Open vSwitch switch implementations
openvswitch-switch provides the userspace components and utilities for
the Open vSwitch kernel-based switch.
.
Open vSwitch is a software-based Ethernet switch targeted at virtual
servers.
Package: openvswitch-switch-config
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}, openvswitch-switch, libwww-perl, libdigest-sha1-perl
Description: Open vSwitch switch implementations
openvswitch-switch-config provides a utility for interactively configuring
the Open vSwitch switch provided in the openvswitch-switch package.
.
Open vSwitch is a software-based Ethernet switch targeted at virtual
servers.
Package: openvswitch-switchui
Architecture: any
Recommends: openvswitch-switch
Depends: ${shlibs:Depends}, ${misc:Depends}, console-tools
Description: Monitoring utility for OpenFlow switches
The ovs-switchui utility included in this package provides a
"front-panel display" to allow administrators to view the status of
an OpenFlow switch at a glance.
.
The ezio-term utility, also included, provides a VT100-compatible
terminal interface for EZIO3 (aka MTB-134) 16x2 LCD displays found on
server appliances made by Portwell. It allows ovs-switchui to work
with such displays.
Package: openvswitch-pki
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, openvswitch-common
Description: Open vSwitch public key infrastructure
openvswitch-pki provides PKI (public key infrastructure) support for
Open vSwitch switches and controllers, reducing the risk of
man-in-the-middle attacks on the Open vSwitch network infrastructure.
.
Open vSwitch is a software-based Ethernet switch targeted at virtual
servers.
Package: openvswitch-pki-server
Architecture: all
Depends: ${shlibs:Depends}, ${misc:Depends}, ${perl:Depends}, openvswitch-pki, apache2
Description: Open vSwitch public key infrastructure (HTTP server support)
openvswitch-pki-server provides HTTP access to the Open vSwitch PKI (public
key infrastructure) maintained on the local machine by the
openvswitch-pki package. This HTTP access is needed for secure and
convenient OpenFlow switch setup using the ovs-switch-setup program
in the openvswitch-switch package.
.
Open vSwitch is a software-based Ethernet switch targeted at virtual
servers.
Package: openvswitch-controller
Architecture: any
Depends: ${shlibs:Depends}, openvswitch-common, openvswitch-pki
Description: Open vSwitch controller implementation
The Open vSwitch controller enables OpenFlow switches that connect to it
to act as MAC-learning Ethernet switches.
.
Open vSwitch is a software-based Ethernet switch targeted at virtual
servers.
Package: corekeeper
Architecture: all
Depends: tmpreaper
Description: Core file centralizer and reaper
The corekeeper package configures the system to dump all core files to
/var/log/core. It also deletes core files older than 7 days.
Package: openvswitch-dbg
Architecture: any
Depends: ${shlibs:Depends}
Description: Debug symbols for Open vSwitch packages
This package contains the debug symbols for all the other openvswitch-*
packages. Install it to debug one of them or to examine a core dump
produced by one of them.
Package: openvswitch-monitor
Architecture: any
Recommends: openvswitch-switch
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Monitor utility for Open vSwitch switches
The ovs-monitor utility included in this package monitors the secure
channel and datapath. If either become unresponsive, the switch is
rebooted.
Package: openvswitch-wdt
Architecture: any
Recommends: openvswitch-switch
Depends: ${shlibs:Depends}, ${misc:Depends}
Description: Watchdog utility for Open vSwitch switches
The ovs-wdt program included in this package manages the hardware
watchdog timer in switches based on the Portwell NAR-5520 hardware.
Package: nicira-switch
Architecture: all
Depends:
openvswitch-common (= ${source:Version}),
openvswitch-switch (= ${source:Version}),
openvswitch-switchui (= ${source:Version}),
openvswitch-datapath-module (= ${source:Version}),
corekeeper, openvswitch-monitor, openvswitch-wdt
Description: Metapackage for installing a Nicira Open vSwitch switch
Installing this package will install everything needed for a Nicira
Portwell-based Open vSwitch switch, including monitoring and the switch UI.

20
debian/control.modules.in vendored Normal file
View File

@ -0,0 +1,20 @@
Source: openvswitch
Section: net
Priority: extra
Maintainer: Open vSwitch developers <ovs-dev@openvswitch.org>
Build-Depends: debhelper (>= 5.0.37)
Standards-Version: 3.7.3
Package: openvswitch-datapath-module-_KVERS_
Architecture: any
Recommends: kernel-image-_KVERS_, openvswitch-switch
Provides: openvswitch-datapath-module
Description: Open vSwitch Linux datapath kernel module
This package contains the Open vSwitch loadable datapath kernel modules for
the kernel-image-_KVERS_ package.
.
If you compiled a custom kernel, you will most likely need to compile
a custom version of this module as well. The
openvswitch-datapath-source package has been provided for this
purpose. Refer to README.Debian provided in that package for further
instructions.

21
debian/copyright vendored Normal file
View File

@ -0,0 +1,21 @@
Upstream Authors:
Nicira Networks
Copyright:
Copyright (C) 2008 Nicira Networks.
License:
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

5
debian/corekeeper.cron.daily vendored Executable file
View File

@ -0,0 +1,5 @@
#! /bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
tmpreaper 7d --mtime --all /var/log/core

63
debian/corekeeper.init vendored Executable file
View File

@ -0,0 +1,63 @@
#!/bin/sh
#
# Example init.d script with LSB support.
#
# Please read this init.d carefully and modify the sections to
# adjust it to the program you want to run.
#
# Copyright (c) 2007 Javier Fernandez-Sanguino <jfs@debian.org>
#
# This is free software; you may redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2,
# or (at your option) any later version.
#
# This 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 with
# the Debian operating system, in /usr/share/common-licenses/GPL; if
# not, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA 02111-1307 USA
#
### BEGIN INIT INFO
# Provides: corekeeper
# Required-Start:
# Required-Stop:
# Should-Start: $syslog
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Configure core file dump location
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
. /lib/lsb/init-functions
set -e
case "$1" in
start)
log_daemon_msg "Initializing core dump location..."
if echo "/var/log/core/core.%e.%t" > /proc/sys/kernel/core_pattern
then
log_progress_msg "success"
log_end_msg 0
exit 0
else
log_end_msg 1
exit 1
fi
;;
stop|restart|force-reload|status|reload)
exit 0
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
exit 1
;;
esac

2
debian/dirs vendored Normal file
View File

@ -0,0 +1,2 @@
usr/bin
usr/sbin

1
debian/openvswitch-common.dirs vendored Normal file
View File

@ -0,0 +1 @@
var/log/openvswitch

3
debian/openvswitch-common.install vendored Normal file
View File

@ -0,0 +1,3 @@
_debian/utilities/ovs-appctl usr/sbin
_debian/utilities/ovs-parse-leaks usr/bin
_debian/utilities/ovs-pki usr/sbin

2
debian/openvswitch-common.manpages vendored Normal file
View File

@ -0,0 +1,2 @@
_debian/utilities/ovs-appctl.8
_debian/utilities/ovs-pki.8

View File

@ -0,0 +1,12 @@
README.Debian for openvswitch-controller
-------------------------------------
* To (re)configure the controller, edit /etc/default/openvswitch-controller
and run "/etc/init.d/openvswitch-controller restart".
* To enable OpenFlow switches to automatically discover the location
of the controller, you must install and configure a DHCP server.
The secchan(8) manpage (found in the openvswitch-switch package) gives
a working example configuration file for the ISC DHCP server.
-- Ben Pfaff <blp@nicira.com>, Mon, 11 May 2009 13:26:38 -0700

29
debian/openvswitch-controller.default vendored Normal file
View File

@ -0,0 +1,29 @@
# This is a POSIX shell fragment -*- sh -*-
# LISTEN: What OpenFlow connection methods should the controller listen on?
#
# This is a space-delimited list of connection methods:
#
# * "pssl:[PORT]": Listen for SSL connections on the specified PORT
# (default: 6633). The private key, certificate, and CA certificate
# must be specified below.
#
# * "pctp:[PORT]": Listen for TCP connections on the specified PORT
# (default: 6633). Not recommended for security reasons.
#
LISTEN="pssl:"
# PRIVKEY: Name of file containing controller's private key.
# Required if SSL enabled.
PRIVKEY=/etc/openvswitch-controller/privkey.pem
# CERT: Name of file containing certificate for private key.
# Required if SSL enabled.
CERT=/etc/openvswitch-controller/cert.pem
# CACERT: Name of file containing switch CA certificate.
# Required if SSL enabled.
CACERT=/etc/openvswitch-controller/cacert.pem
# Additional options to pass to controller, e.g. "--hub"
DAEMON_OPTS=""

1
debian/openvswitch-controller.dirs vendored Normal file
View File

@ -0,0 +1 @@
etc/openvswitch-controller

269
debian/openvswitch-controller.init vendored Executable file
View File

@ -0,0 +1,269 @@
#!/bin/sh
#
# Copyright (c) 2007, 2009 Javier Fernandez-Sanguino <jfs@debian.org>
#
# This is free software; you may redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2,
# or (at your option) any later version.
#
# This 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 with
# the Debian operating system, in /usr/share/common-licenses/GPL; if
# not, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA 02111-1307 USA
#
### BEGIN INIT INFO
# Provides: openvswitch-controller
# Required-Start: $network $local_fs
# Required-Stop:
# Should-Start: $named
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Open vSwitch controller
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/controller # Introduce the server's location here
NAME=ovs-controller # Introduce the short server's name here
DESC=ovs-controller # Introduce a short description here
LOGDIR=/var/log/openvswitch # Log directory to use
PIDFILE=/var/run/$NAME.pid
test -x $DAEMON || exit 0
. /lib/lsb/init-functions
# Default options, these can be overriden by the information
# at /etc/default/$NAME
DAEMON_OPTS="" # Additional options given to the server
DODTIME=10 # Time to wait for the server to die, in seconds
# If this value is set too low you might not
# let some servers to die gracefully and
# 'restart' will not work
LOGFILE=$LOGDIR/$NAME.log # Server logfile
#DAEMONUSER= # User to run the daemons as. If this value
# is set start-stop-daemon will chuid the server
# Include defaults if available
default=/etc/default/openvswitch-controller
if [ -f $default ] ; then
. $default
fi
# Check that the user exists (if we set a user)
# Does the user exist?
if [ -n "$DAEMONUSER" ] ; then
if getent passwd | grep -q "^$DAEMONUSER:"; then
# Obtain the uid and gid
DAEMONUID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $3}'`
DAEMONGID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $4}'`
else
log_failure_msg "The user $DAEMONUSER, required to run $NAME does not exist."
exit 1
fi
fi
set -e
running_pid() {
# Check if a given process pid's cmdline matches a given name
pid=$1
name=$2
[ -z "$pid" ] && return 1
[ ! -d /proc/$pid ] && return 1
cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1`
# Is this the expected server
[ "$cmd" != "$name" ] && return 1
return 0
}
running() {
# Check if the process is running looking at /proc
# (works for all users)
# No pidfile, probably no daemon present
[ ! -f "$PIDFILE" ] && return 1
pid=`cat $PIDFILE`
running_pid $pid $DAEMON || return 1
return 0
}
start_server() {
if [ -z "$LISTEN" ]; then
echo "$default: No connection methods configured, controller disabled" >&2
exit 0
fi
SSL_OPTS=
case $LISTEN in
*ssl*)
: ${PRIVKEY:=/etc/openvswitch-controller/privkey.pem}
: ${CERT:=/etc/openvswitch-controller/cert.pem}
: ${CACERT:=/etc/openvswitch-controller/cacert.pem}
if test ! -e "$PRIVKEY" || test ! -e "$CERT" ||
test ! -e "$CACERT"; then
if test ! -e "$PRIVKEY"; then
echo "$PRIVKEY: private key missing" >&2
fi
if test ! -e "$CERT"; then
echo "$CERT: certificate for private key missing" >&2
fi
if test ! -e "$CACERT"; then
echo "$CACERT: CA certificate missing" >&2
fi
exit 1
fi
SSL_OPTS="--private-key=$PRIVKEY --certificate=$CERT --ca-cert=$CACERT"
;;
esac
# Start the process using the wrapper
if [ -z "$DAEMONUSER" ] ; then
start-stop-daemon --start --pidfile $PIDFILE \
--exec $DAEMON -- --detach --pidfile=$PIDFILE \
$LISTEN $DAEMON_OPTS $SSL_OPTS
errcode=$?
else
# if we are using a daemonuser then change the user id
start-stop-daemon --start --quiet --pidfile $PIDFILE \
--chuid $DAEMONUSER --exec $DAEMON -- \
--detach --pidfile=$PIDFILE $LISTEN $DAEMON_OPTS \
$SSL_OPTS
errcode=$?
fi
return $errcode
}
stop_server() {
# Stop the process using the wrapper
if [ -z "$DAEMONUSER" ] ; then
start-stop-daemon --stop --quiet --pidfile $PIDFILE \
--exec $DAEMON
errcode=$?
else
# if we are using a daemonuser then look for process that match
start-stop-daemon --stop --quiet --pidfile $PIDFILE \
--user $DAEMONUSER --exec $DAEMON
errcode=$?
fi
return $errcode
}
reload_server() {
[ ! -f "$PIDFILE" ] && return 1
pid=`cat $PIDFILE` # This is the daemon's pid
# Send a SIGHUP
kill -1 $pid
return $?
}
force_stop() {
# Force the process to die killing it manually
[ ! -e "$PIDFILE" ] && return
if running ; then
kill -15 $pid
# Is it really dead?
sleep "$DIETIME"s
if running ; then
kill -9 $pid
sleep "$DIETIME"s
if running ; then
echo "Cannot kill $NAME (pid=$pid)!"
exit 1
fi
fi
fi
rm -f $PIDFILE
}
case "$1" in
start)
log_daemon_msg "Starting $DESC " "$NAME"
# Check if it's running first
if running ; then
log_progress_msg "apparently already running"
log_end_msg 0
exit 0
fi
if start_server && running ; then
# It's ok, the server started and is running
log_end_msg 0
else
# Either we could not start it or it is not running
# after we did
# NOTE: Some servers might die some time after they start,
# this code does not try to detect this and might give
# a false positive (use 'status' for that)
log_end_msg 1
fi
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
if running ; then
# Only stop the server if we see it running
stop_server
log_end_msg $?
else
# If it's not running don't do anything
log_progress_msg "apparently not running"
log_end_msg 0
exit 0
fi
;;
force-stop)
# First try to stop gracefully the program
$0 stop
if running; then
# If it's still running try to kill it more forcefully
log_daemon_msg "Stopping (force) $DESC" "$NAME"
force_stop
log_end_msg $?
fi
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
stop_server
# Wait some sensible amount, some server need this
[ -n "$DIETIME" ] && sleep $DIETIME
start_server
running
log_end_msg $?
;;
status)
log_daemon_msg "Checking status of $DESC" "$NAME"
if running ; then
log_progress_msg "running"
log_end_msg 0
else
log_progress_msg "apparently not running"
log_end_msg 1
exit 1
fi
;;
# Use this if the daemon cannot reload
reload)
log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon"
log_warning_msg "cannot re-read the config file (use restart)."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|force-stop|restart|force-reload|status}" >&2
exit 1
;;
esac
exit 0

1
debian/openvswitch-controller.install vendored Normal file
View File

@ -0,0 +1 @@
_debian/utilities/ovs-controller usr/sbin

View File

@ -0,0 +1 @@
_debian/utilities/ovs-controller.8

52
debian/openvswitch-controller.postinst vendored Executable file
View File

@ -0,0 +1,52 @@
#!/bin/sh
# postinst script for openvswitch-controller
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure)
cd /etc/openvswitch-controller
if ! test -e cacert.pem; then
ln -s /usr/share/openvswitch/pki/switchca/cacert.pem cacert.pem
fi
if ! test -e privkey.pem || ! test -e cert.pem; then
oldumask=$(umask)
umask 077
ovs-pki req+sign tmp controller >/dev/null
mv tmp-privkey.pem privkey.pem
mv tmp-cert.pem cert.pem
mv tmp-req.pem req.pem
chmod go+r cert.pem req.pem
umask $oldumask
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
#DEBHELPER#
exit 0

View File

@ -0,0 +1,25 @@
#!/bin/sh
# postinst script for #PACKAGE#
#
# see: dh_installdeb(1)
set -e
depmod -a
#DEBHELPER#
# If the switch is running, restart it. This ensures that we are using the
# latest kernel module, because the init script will unload and reload the
# module.
#
# (Ideally we'd only want to do this if this package corresponds to the
# running kernel, but I don't know a reliable way to check.)
INIT=/etc/init.d/openvswitch-switch
if test -x $INIT && $INIT status; then
$INIT restart || true
fi
exit 0

View File

@ -0,0 +1,31 @@
Open vSwitch for Debian
----------------------
* How do I build this module the Debian way?
- Building with module-assistant:
$ module-assistant auto-install openvswitch
or
$ m-a a-i openvswitch
If kernel source or headers are in a non-standard directory, add
the option -k /path/to/kernel/source with the correct path.
- Building with make-kpkg
$ cd /usr/src/
$ tar jxvf openvswitch.tar.bz2
$ cd /usr/src/kernel-source-2.6.9
$ make-kpkg --added-modules=openvswitch modules
- Building without make-kpkg
$ cd /usr/src/
$ tar jxvf openvswitch.tar.bz2
$ cd modules/openvswitch
$ fakeroot debian/rules kdist_image
If you run this as root, fakeroot is not needed.
-- Ben Pfaff <blp@nicira.com>, Mon, 11 May 2009 13:27:50 -0700

View File

@ -0,0 +1,15 @@
Upstream Authors:
Nicira Networks
Copyright:
Copyright (C) 2008 Nicira Networks
License:
Files in the datapath/ and its sub-directories are covered under the GNU
General Public License Version 2.
On Debian systems, the complete text of the GNU General
Public License can be found in `/usr/share/common-licenses/GPL'.

View File

@ -0,0 +1 @@
usr/src/modules/openvswitch-datapath/debian

View File

@ -0,0 +1,6 @@
debian/changelog usr/src/modules/openvswitch-datapath/debian
debian/control usr/src/modules/openvswitch-datapath/debian
debian/compat usr/src/modules/openvswitch-datapath/debian
debian/*.modules.in usr/src/modules/openvswitch-datapath/debian
debian/rules usr/src/modules/openvswitch-datapath/debian
_debian/openvswitch.tar.gz usr/src/modules/openvswitch-datapath

27
debian/openvswitch-monitor.default vendored Normal file
View File

@ -0,0 +1,27 @@
# This is a POSIX shell fragment -*- sh -*-
# To configure the Open vSwitch monitor package, modify the following.
# Afterward, the monitor will be configured automatically at boot time.
# It can be started immediately with
# /etc/init.d/openvswitch-monitor start
# Defaults for initscript
# sourced by /etc/init.d/openvswitch-monitor
# installed at /etc/default/openvswitch-monitor by the maintainer scripts
# THRESHOLD: The number of failed attempts the monitor should make until
# it reboots the system. A value of zero disables the monitor.
THRESHOLD=3
# INTERVAL: The number of seconds to wait between probing secchan and
# the datapath.
INTERVAL=1
# LOG_FILE: File to log messages related to monitoring.
LOG_FILE="/var/log/openvswitch/monitor"
# SWITCH_VCONN: The vconn used to connect to the switch (secchan).
# The secchan must be configured to listen to this vconn. The default
# here set is also listened to by default by the openvswitch-switch
# package, so ordinarily there is no need to modify this.
SWITCH_VCONN="/var/run/secchan.mgmt"

1
debian/openvswitch-monitor.dirs vendored Normal file
View File

@ -0,0 +1 @@
usr/sbin

174
debian/openvswitch-monitor.init vendored Executable file
View File

@ -0,0 +1,174 @@
#!/bin/sh
#
# Example init.d script with LSB support.
#
# Please read this init.d carefully and modify the sections to
# adjust it to the program you want to run.
#
# Copyright (c) 2007, 2009 Javier Fernandez-Sanguino <jfs@debian.org>
#
# This is free software; you may redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2,
# or (at your option) any later version.
#
# This 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 with
# the Debian operating system, in /usr/share/common-licenses/GPL; if
# not, write to the Free Software Foundation, Inc., 59 Temple Place,
# Suite 330, Boston, MA 02111-1307 USA
#
### BEGIN INIT INFO
# Provides: openvswitch-monitor
# Required-Start: $network $local_fs
# Required-Stop:
# Should-Start: $named $syslog openvswitch-switch
# Should-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Open vSwitch switch monitor
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
DAEMON=/usr/sbin/ovs-monitor
NAME=openvswitch-monitor
DESC="Open vSwitch switch monitor"
PIDFILE=/var/run/$NAME.pid
test -x $DAEMON || exit 0
. /lib/lsb/init-functions
# Default options, these can be overriden by the information
# at /etc/default/$NAME
DAEMON_OPTS="" # Additional options given to the daemon
DODTIME=10 # Time to wait for the daemon to die, in seconds
# If this value is set too low you might not
# let some daemons to die gracefully and
# 'restart' will not work
# Include defaults if available
if [ -f /etc/default/$NAME ] ; then
. /etc/default/$NAME
fi
set -e
running_pid() {
# Check if a given process pid's cmdline matches a given name
pid=$1
name=$2
[ -z "$pid" ] && return 1
[ ! -d /proc/$pid ] && return 1
return 0
}
running() {
# Check if the process is running looking at /proc
# (works for all users)
# No pidfile, probably no daemon present
[ ! -f "$PIDFILE" ] && return 1
pid=`cat $PIDFILE`
running_pid $pid $DAEMON || return 1
return 0
}
start_daemon() {
# Start the process using the wrapper
if test $THRESHOLD != 0; then
start-stop-daemon --start --quiet -m --background --pidfile $PIDFILE \
--exec $DAEMON -- -c $THRESHOLD -i $INTERVAL -l $LOG_FILE \
-s $SWITCH_VCONN $DAEMON_OPTS
fi
# Wait up to 3 seconds for the daemon to start.
for i in 1 2 3; do
if running; then
break
fi
sleep 1
done
}
stop_daemon() {
start-stop-daemon -o --stop --pidfile $PIDFILE
rm $PIDFILE
}
case "$1" in
start)
log_daemon_msg "Starting $DESC " "$NAME"
# Check if it's running first
if running ; then
log_progress_msg "apparently already running"
log_end_msg 0
exit 0
fi
if start_daemon && running ; then
# It's ok, the daemon started and is running
log_end_msg 0
else
# Either we could not start it or it is not running
# after we did
# NOTE: Some daemons might die some time after they start,
# this code does not try to detect this and might give
# a false positive (use 'status' for that)
log_end_msg 1
fi
;;
stop)
log_daemon_msg "Stopping $DESC" "$NAME"
if running ; then
# Only stop the daemon if we see it running
stop_daemon
log_end_msg $?
else
# If it's not running don't do anything
log_progress_msg "apparently not running"
log_end_msg 0
exit 0
fi
;;
restart|force-reload)
log_daemon_msg "Restarting $DESC" "$NAME"
if running ; then
stop_daemon
# Wait some sensible amount, some daemons need this
[ -n "$DIETIME" ] && sleep $DIETIME
fi
start_daemon
running
log_end_msg $?
;;
status)
log_daemon_msg "Checking status of $DESC" "$NAME"
if running ; then
log_progress_msg "running"
log_end_msg 0
else
log_progress_msg "apparently not running"
log_end_msg 1
exit 1
fi
;;
# Use this if the daemon cannot reload
reload)
log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon"
log_warning_msg "cannot re-read the config file (use restart)."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload|status}" >&2
exit 1
;;
esac
exit 0

Some files were not shown because too many files have changed in this diff Show More