refactor scripts and update NSH patch
Change-Id: Ifc76e9bf2f83f904e765e6e8216ed98910642bae Signed-off-by: Guo Ruijing <ruijing.guo@intel.com>
This commit is contained in:
parent
b15c57083b
commit
2bad5a25e9
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
INSTALL_HOME=/tmp/ovs-nshdpdk
|
||||
rm -rf $INSTALL_HOME; mkdir -p $INSTALL_HOME
|
||||
cd $INSTALL_HOME
|
||||
|
||||
host=$1
|
||||
nsh=$2
|
||||
dpdk=$3
|
||||
|
||||
wget -r -nd -np http://$host:8080/plugins/fuel-plugin-ovs-0.9/ovs_package/ubuntu
|
||||
|
||||
if [ $nsh = 'true' ]
|
||||
then
|
||||
dpkg -i openvswitch-datapath-dkms_2.5.90-1_all.deb
|
||||
dpkg -i openvswitch-common_2.5.90-1_amd64.deb
|
||||
dpkg -i openvswitch-switch_2.5.90-1_amd64.deb
|
||||
if [ $dpdk = 'true' ]
|
||||
then
|
||||
dpkg -i openvswitch-switch-dpdk_2.5.90-1_amd64.deb
|
||||
fi
|
||||
fi
|
|
@ -1,21 +1,11 @@
|
|||
$fuel_settings = parseyaml(file('/etc/astute.yaml'))
|
||||
$master_ip = $::fuel_settings['master_ip']
|
||||
$support_nsh = $::fuel_settings['fuel-plugin-ovs']['support_nsh']
|
||||
$support_dpdk = $::fuel_settings['fuel-plugin-ovs']['support_dpdk']
|
||||
if $operatingsystem == 'Ubuntu' {
|
||||
if $fuel_settings['fuel-plugin-ovs']['support_nsh'] and
|
||||
$fuel_settings['fuel-plugin-ovs']['support_dpdk'] {
|
||||
exec { 'install ovs/nsh-dpdk':
|
||||
command => '/usr/bin/curl http://10.20.0.2:8080/plugins/fuel-plugin-ovs-0.9/repositories/ubuntu/install.sh | /bin/bash -s nshdpdk'
|
||||
}
|
||||
exec { 'install ovs_nsh_dpdk':
|
||||
command => "curl http://${master_ip}:8080/plugins/fuel-plugin-ovs-0.9/deployment_scripts/install.sh | bash -s ${master_ip} ${support_nsh} ${support_dpdk}",
|
||||
path => "/usr/bin:/usr/sbin:/bin:/sbin";
|
||||
}
|
||||
elsif $fuel_settings['fuel-plugin-ovs']['support_dpdk'] {
|
||||
exec { 'install ovs/dpdk':
|
||||
command => '/usr/bin/curl http://10.20.0.2:8080/plugins/fuel-plugin-ovs-0.9/repositories/ubuntu/install.sh | /bin/bash -s dpdk'
|
||||
}
|
||||
}
|
||||
elsif $fuel_settings['fuel-plugin-ovs']['support_nsh'] {
|
||||
exec { 'install ovs/nsh':
|
||||
command => '/usr/bin/curl http://10.20.0.2:8080/plugins/fuel-plugin-ovs-0.9/repositories/ubuntu/install.sh | /bin/bash -s nsh'
|
||||
}
|
||||
}
|
||||
|
||||
} elsif $operatingsystem == 'CentOS' {
|
||||
}
|
||||
|
|
|
@ -1 +1,20 @@
|
|||
[]
|
||||
- id: ovs_nsh_dpdk
|
||||
type: group
|
||||
role: ['compute']
|
||||
requires: [deploy_start]
|
||||
required_for: [deploy_end]
|
||||
tasks: [hiera, setup_repositories, fuel_pkgs, globals, tools, logging, ovs_install_compute]
|
||||
parameters:
|
||||
strategy:
|
||||
type: parallel
|
||||
|
||||
- id: ovs_install_compute
|
||||
type: puppet
|
||||
version: 2.0.0
|
||||
groups: [ovs_nsh_dpdk]
|
||||
required_for: [pre_deployment_end]
|
||||
requires: [pre_deployment_start]
|
||||
parameters:
|
||||
puppet_manifest: puppet/manifests/ovs-install-compute.pp
|
||||
puppet_modules: puppet/modules:/etc/puppet/modules
|
||||
timeout: 720
|
||||
|
|
|
@ -3,12 +3,8 @@
|
|||
FROM ubuntu:14.04.3
|
||||
|
||||
RUN apt-get update -y
|
||||
|
||||
RUN rm -rf /lib/modules
|
||||
RUN apt-get install -y linux-headers-3.13.0-76-generic
|
||||
RUN ln -s /lib/modules/3.13.0-76-generic /lib/modules/`uname -r`
|
||||
RUN apt-get install -y linux-headers-3.13.0-86-generic
|
||||
RUN ln -s /lib/modules/3.13.0-86-generic /lib/modules/`uname -r`
|
||||
|
||||
RUN apt-get build-dep openvswitch -y
|
||||
RUN apt-get -y install devscripts dpkg-dev git wget
|
||||
|
||||
ADD ./ /ovs_build
|
||||
ADD ./ /ovs_build
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
#!/bin/bash
|
||||
|
||||
OVS_COMMIT=cd4764fdd8ce0aa0063525dad0e67f20b3bcf6e9
|
||||
URL_OVS=https://github.com/openvswitch/ovs.git
|
||||
OVS_VER=${OVS_VER:-2.5.1}
|
||||
BUILD_HOME=$HOME/dpdk
|
||||
BUILD_DEST=${BUILD_DEST:-/deb}
|
||||
|
||||
BUILD_HOME=`pwd`
|
||||
sudo apt-get update -y
|
||||
sudo apt-get build-dep openvswitch -y
|
||||
sudo apt-get -y install devscripts dpkg-dev git wget
|
||||
|
||||
rm -rf ${BUILD_HOME}; mkdir -p ${BUILD_HOME}
|
||||
|
||||
cd ${BUILD_HOME}
|
||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0-0ubuntu8.dsc
|
||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0.orig.tar.gz
|
||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0-0ubuntu8.debian.tar.xz
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0-0ubuntu8.dsc
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0.orig.tar.gz
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0-0ubuntu8.debian.tar.xz
|
||||
dpkg-source -x dpdk_2.2.0-0ubuntu8.dsc
|
||||
|
||||
# copy from debian/control
|
||||
|
@ -29,15 +33,20 @@ sudo apt-get install -y debhelper \
|
|||
texlive-fonts-recommended \
|
||||
texlive-latex-extra
|
||||
|
||||
cd dpdk-2.2.0; rm -rf debian/patches/; debian/rules build; fakeroot debian/rules binary
|
||||
cd dpdk-2.2.0; rm -rf debian/patches/;
|
||||
cat << EOF > debian/changelog
|
||||
dpdk (2.2.0-1) unstable; urgency=low
|
||||
[ DPDK team]
|
||||
* New upstream version
|
||||
EOF
|
||||
debian/rules build; fakeroot debian/rules binary
|
||||
cd ${BUILD_HOME}; sudo dpkg -i *.deb
|
||||
|
||||
cd ${BUILD_HOME}
|
||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0.orig.tar.gz
|
||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0-0ubuntu1.dsc
|
||||
wget https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0-0ubuntu1.debian.tar.xz
|
||||
dpkg-source -x openvswitch-dpdk_2.4.0-0ubuntu1.dsc
|
||||
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0.orig.tar.gz
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0-0ubuntu1.dsc
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0-0ubuntu1.debian.tar.xz
|
||||
dpkg-source -x openvswitch-dpdk_2.4.0-0ubuntu1.dsc
|
||||
|
||||
# copy from debian/control
|
||||
sudo apt-get intall -y autoconf \
|
||||
|
@ -56,16 +65,27 @@ sudo apt-get intall -y autoconf \
|
|||
python-all \
|
||||
python-qt4 \
|
||||
python-twisted-conch \
|
||||
python-zopeinterface
|
||||
python-zopeinterface \
|
||||
python-six
|
||||
|
||||
git clone https://github.com/openvswitch/ovs.git
|
||||
cd ovs; git checkout ${OVS_COMMIT}
|
||||
cd ${BUILD_HOME}; tar czvf ovs.tar.gz ovs
|
||||
rm -rf openvswitch-dpdk-2.5.0*
|
||||
cd openvswitch-dpdk-2.4.0; uupdate -v 2.5.0 ../ovs.tar.gz
|
||||
cd ../openvswitch-dpdk-2.5.0
|
||||
rm -rf openvswitch-dpdk-${OVS_VER}*
|
||||
cd openvswitch-dpdk-2.4.0; uupdate -v ${OVS_VER} ../ovs.tar.gz
|
||||
cd ../openvswitch-dpdk-${OVS_VER}
|
||||
sed -i "s/include\/rte_config.h/include\/dpdk\/rte_config.h/" acinclude.m4
|
||||
sed -i 's/DPDK_INCLUDE=.*/DPDK_INCLUDE=$RTE_SDK\/include\/dpdk/' acinclude.m4
|
||||
autoreconf --install
|
||||
rm -rf debian/patches/ .git;
|
||||
cat << EOF > debian/changelog
|
||||
openvswitch-dpdk (${OVS_VER}-1) unstable; urgency=low
|
||||
[ Open vSwitch team ]
|
||||
* Open vSwitch Upstream
|
||||
EOF
|
||||
debian/rules build; fakeroot debian/rules binary
|
||||
|
||||
cd ${BUILD_HOME}/ovs
|
||||
debian/rules build; fakeroot debian/rules binary
|
||||
|
||||
cp ${BUILD_HOME}/*.deb ${BUILD_DEST}
|
||||
|
|
|
@ -1,43 +1,97 @@
|
|||
#!/bin/bash
|
||||
|
||||
DPDK_VER=2.1.0
|
||||
BUILD_HOME=`pwd`/tmp
|
||||
|
||||
export RTE_TARGET=x86_64-native-linuxapp-gcc
|
||||
export RTE_SDK=${BUILD_HOME}/dpdk-${DPDK_VER}
|
||||
export DPDK_BUILD=${RTE_SDK}/${RTE_TARGET}
|
||||
|
||||
OVS_COMMIT=121daded51b9798fe3722824b27a05c16806cbd1
|
||||
PATCHES="060679 060680 060681 060682 060683 060684 060685"
|
||||
OVS_COMMIT=7d433ae57ebb90cd68e8fa948a096f619ac4e2d8
|
||||
URL_OVS=https://github.com/openvswitch/ovs.git
|
||||
URL_DPDK=http://dpdk.org/browse/dpdk/snapshot/dpdk-${DPDK_VER}.tar.gz
|
||||
OVS_VER=${OVS_VER:-2.5.90}
|
||||
BUILD_HOME=$HOME/nsh
|
||||
BUILD_DEST=${BUILD_DEST:-/deb}
|
||||
|
||||
mkdir -p ${BUILD_HOME}
|
||||
cd ${BUILD_HOME}
|
||||
wget ${URL_DPDK}
|
||||
tar -xzvf dpdk-${DPDK_VER}.tar.gz
|
||||
cd dpdk-${DPDK_VER}
|
||||
sed -i -e 's/CONFIG_RTE_LIBRTE_VHOST=n/CONFIG_RTE_LIBRTE_VHOST=y/' \
|
||||
-e 's/CONFIG_RTE_BUILD_COMBINE_LIBS=n/CONFIG_RTE_BUILD_COMBINE_LIBS=y/' \
|
||||
-e 's/CONFIG_RTE_PKTMBUF_HEADROOM=128/CONFIG_RTE_PKTMBUF_HEADROOM=256/' \
|
||||
config/common_linuxapp
|
||||
make install T=${RTE_TARGET}
|
||||
sudo apt-get build-dep openvswitch -y
|
||||
sudo apt-get -y install devscripts dpkg-dev git wget
|
||||
|
||||
rm -rf ${BUILD_HOME}; mkdir -p ${BUILD_HOME}
|
||||
|
||||
cd ${BUILD_HOME}
|
||||
git clone ${URL_OVS} openvswitch
|
||||
cd openvswitch
|
||||
git checkout ${OVS_COMMIT} -b development
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0-0ubuntu8.dsc
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0.orig.tar.gz
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/dpdk_2.2.0-0ubuntu8.debian.tar.xz
|
||||
dpkg-source -x dpdk_2.2.0-0ubuntu8.dsc
|
||||
|
||||
# copy from debian/control
|
||||
sudo apt-get install -y debhelper \
|
||||
dh-python \
|
||||
dh-systemd \
|
||||
doxygen \
|
||||
graphviz \
|
||||
inkscape \
|
||||
libcap-dev \
|
||||
libpcap-dev \
|
||||
libxen-dev \
|
||||
libxenstore3.0 \
|
||||
python \
|
||||
python-sphinx \
|
||||
texlive-fonts-recommended \
|
||||
texlive-latex-extra
|
||||
|
||||
cd dpdk-2.2.0; rm -rf debian/patches/;
|
||||
cat << EOF > debian/changelog
|
||||
dpdk (2.2.0-1) unstable; urgency=low
|
||||
[ DPDK team]
|
||||
* New upstream version
|
||||
EOF
|
||||
debian/rules build; fakeroot debian/rules binary
|
||||
cd ${BUILD_HOME}; sudo dpkg -i *.deb
|
||||
|
||||
cd ${BUILD_HOME}
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0.orig.tar.gz
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0-0ubuntu1.dsc
|
||||
wget -c https://launchpad.net/ubuntu/+archive/primary/+files/openvswitch-dpdk_2.4.0-0ubuntu1.debian.tar.xz
|
||||
dpkg-source -x openvswitch-dpdk_2.4.0-0ubuntu1.dsc
|
||||
|
||||
# copy from debian/control
|
||||
sudo apt-get intall -y autoconf \
|
||||
automake \
|
||||
bzip2 \
|
||||
debhelper \
|
||||
dh-autoreconf \
|
||||
dh-systemd \
|
||||
graphviz \
|
||||
libdpdk-dev \
|
||||
libfuse-dev \
|
||||
libssl-dev \
|
||||
libtool \
|
||||
openssl \
|
||||
procps \
|
||||
python-all \
|
||||
python-qt4 \
|
||||
python-twisted-conch \
|
||||
python-zopeinterface \
|
||||
python-six
|
||||
|
||||
git clone https://github.com/openvswitch/ovs.git
|
||||
cd ovs; git checkout ${OVS_COMMIT}
|
||||
DIR="$(dirname `readlink -f $0`)"
|
||||
PATCHES=$(cd patches; echo *patch; cd ..)
|
||||
for patch in ${PATCHES}
|
||||
do
|
||||
patch -p1 < /ovs_build/patches/${patch}.patch
|
||||
patch -p1 < {DIR}/patches/${patch}
|
||||
done
|
||||
export DEB_BUILD_OPTIONS='parallel=8 nocheck'
|
||||
sed -i "s/2.4.90/2.4.90.nshdpdk/g" debian/changelog
|
||||
sed -i "s/DATAPATH_CONFIGURE_OPTS.*=.*//" debian/rules
|
||||
sed -i "2iDATAPATH_CONFIGURE_OPTS='--with-dpdk=$DPDK_BUILD'" debian/rules
|
||||
sed -i "s/DATAPATH_CONFIGURE_OPTS.*=.*//" debian/rules.modules
|
||||
sed -i "2iDATAPATH_CONFIGURE_OPTS='--with-dpdk=$DPDK_BUILD'" debian/rules.modules
|
||||
debian/rules build
|
||||
fakeroot debian/rules binary
|
||||
cd ${BUILD_HOME}; tar czvf ovs.tar.gz ovs
|
||||
rm -rf openvswitch-dpdk-${OVS_VER}*
|
||||
cd openvswitch-dpdk-2.4.0; uupdate -v ${OVS_VER} ../ovs.tar.gz
|
||||
cd ../openvswitch-dpdk-${OVS_VER}
|
||||
sed -i "s/include\/rte_config.h/include\/dpdk\/rte_config.h/" acinclude.m4
|
||||
sed -i 's/DPDK_INCLUDE=.*/DPDK_INCLUDE=$RTE_SDK\/include\/dpdk/' acinclude.m4
|
||||
autoreconf --install
|
||||
rm -rf debian/patches/ .git;
|
||||
cat << EOF > debian/changelog
|
||||
openvswitch-dpdk (${OVS_VER}-1) unstable; urgency=low
|
||||
[ Open vSwitch team ]
|
||||
* Support NSH
|
||||
EOF
|
||||
debian/rules build; fakeroot debian/rules binary
|
||||
|
||||
cp ${BUILD_HOME}/*.deb /deb
|
||||
cd ${BUILD_HOME}/ovs
|
||||
debian/rules build; fakeroot debian/rules binary
|
||||
|
||||
cp ${BUILD_HOME}/*.deb ${BUILD_DEST}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
#!/bin/bash
|
||||
|
||||
BUILD_HOME=`pwd`/tmp
|
||||
|
||||
OVS_COMMIT=121daded51b9798fe3722824b27a05c16806cbd1
|
||||
PATCHES="060679 060680 060681 060682 060683 060684 060685"
|
||||
URL_OVS=https://github.com/openvswitch/ovs.git
|
||||
|
||||
mkdir -p ${BUILD_HOME}
|
||||
cd ${BUILD_HOME}
|
||||
git clone ${URL_OVS} openvswitch
|
||||
cd openvswitch
|
||||
git checkout ${OVS_COMMIT} -b development
|
||||
for patch in ${PATCHES}
|
||||
do
|
||||
patch -p1 < /ovs_build/patches/${patch}.patch
|
||||
done
|
||||
|
||||
export DEB_BUILD_OPTIONS='parallel=8 nocheck'
|
||||
sed -i "s/2.4.90/2.4.90.nsh/g" debian/changelog
|
||||
debian/rules build
|
||||
fakeroot debian/rules binary
|
||||
cp ${BUILD_HOME}/*.deb /deb
|
|
@ -0,0 +1,732 @@
|
|||
From 5d79831435ec4e5bea20cc36c3f83eacf6fd065c Mon Sep 17 00:00:00 2001
|
||||
From: Yi Yang <yi.y.yang@intel.com>
|
||||
Date: Mon, 11 Apr 2016 15:58:14 +0800
|
||||
Subject: [PATCH 1/5] ovs-vxlan-gpe: vxlan extension to support vxlan-gpe
|
||||
tunnel port
|
||||
|
||||
Signed-off-by: Mengke Liu <mengke.liu@intel.com>
|
||||
Signed-off-by: Ricky Li <ricky.li@intel.com>
|
||||
Signed-off-by: Johnson Li <johnson.li@intel.com>
|
||||
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
|
||||
---
|
||||
datapath/flow_netlink.c | 8 +-
|
||||
datapath/linux/compat/include/linux/openvswitch.h | 1 +
|
||||
datapath/linux/compat/include/net/vxlan.h | 73 +++++++++++++++++++
|
||||
datapath/linux/compat/vxlan.c | 30 ++++++++
|
||||
datapath/vport-vxlan.c | 15 ++++
|
||||
lib/flow.c | 8 ++
|
||||
lib/match.c | 34 +++++++++
|
||||
lib/match.h | 4 +
|
||||
lib/meta-flow.c | 36 +++++++++
|
||||
lib/meta-flow.h | 28 +++++++
|
||||
lib/netdev-vport.c | 2 +
|
||||
lib/nx-match.c | 4 +
|
||||
lib/odp-util.c | 89 ++++++++++++++++++++++-
|
||||
lib/packets.h | 4 +-
|
||||
tests/ofproto.at | 4 +-
|
||||
tests/ovs-ofctl.at | 4 +
|
||||
16 files changed, 340 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/datapath/flow_netlink.c b/datapath/flow_netlink.c
|
||||
index 6ffcc53..351a504 100644
|
||||
--- a/datapath/flow_netlink.c
|
||||
+++ b/datapath/flow_netlink.c
|
||||
@@ -309,6 +309,7 @@ size_t ovs_key_attr_size(void)
|
||||
|
||||
static const struct ovs_len_tbl ovs_vxlan_ext_key_lens[OVS_VXLAN_EXT_MAX + 1] = {
|
||||
[OVS_VXLAN_EXT_GBP] = { .len = sizeof(u32) },
|
||||
+ [OVS_VXLAN_EXT_GPE] = { .len = sizeof(u32) },
|
||||
};
|
||||
|
||||
static const struct ovs_len_tbl ovs_tunnel_key_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
|
||||
@@ -521,6 +522,9 @@ static int vxlan_tun_opt_from_nlattr(const struct nlattr *attr,
|
||||
case OVS_VXLAN_EXT_GBP:
|
||||
opts.gbp = nla_get_u32(a);
|
||||
break;
|
||||
+ case OVS_VXLAN_EXT_GPE:
|
||||
+ opts.gpe = nla_get_u32(a);
|
||||
+ break;
|
||||
default:
|
||||
OVS_NLERR(log, "Unknown VXLAN extension attribute %d",
|
||||
type);
|
||||
@@ -677,7 +681,9 @@ static int vxlan_opt_to_nlattr(struct sk_buff *skb,
|
||||
if (!nla)
|
||||
return -EMSGSIZE;
|
||||
|
||||
- if (nla_put_u32(skb, OVS_VXLAN_EXT_GBP, opts->gbp) < 0)
|
||||
+ if (opts->gbp && nla_put_u32(skb, OVS_VXLAN_EXT_GBP, opts->gbp) < 0)
|
||||
+ return -EMSGSIZE;
|
||||
+ else if (opts->gpe && nla_put_u32(skb, OVS_VXLAN_EXT_GPE, opts->gpe) < 0)
|
||||
return -EMSGSIZE;
|
||||
|
||||
nla_nest_end(skb, nla);
|
||||
diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
|
||||
index 3b39ebb..44adb81 100644
|
||||
--- a/datapath/linux/compat/include/linux/openvswitch.h
|
||||
+++ b/datapath/linux/compat/include/linux/openvswitch.h
|
||||
@@ -287,6 +287,7 @@ enum ovs_vport_attr {
|
||||
enum {
|
||||
OVS_VXLAN_EXT_UNSPEC,
|
||||
OVS_VXLAN_EXT_GBP, /* Flag or __u32 */
|
||||
+ OVS_VXLAN_EXT_GPE,
|
||||
__OVS_VXLAN_EXT_MAX,
|
||||
};
|
||||
|
||||
diff --git a/datapath/linux/compat/include/net/vxlan.h b/datapath/linux/compat/include/net/vxlan.h
|
||||
index 75a5a7a..2bfc3f8 100644
|
||||
--- a/datapath/linux/compat/include/net/vxlan.h
|
||||
+++ b/datapath/linux/compat/include/net/vxlan.h
|
||||
@@ -84,6 +84,75 @@ struct vxlanhdr_gbp {
|
||||
#define VXLAN_GBP_POLICY_APPLIED (BIT(3) << 16)
|
||||
#define VXLAN_GBP_ID_MASK (0xFFFF)
|
||||
|
||||
+/*
|
||||
+ * VXLAN Generic Protocol Extension Extension:
|
||||
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
+ * |R|R|Ver|I|P|R|O|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R| Next Proto |
|
||||
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
+ * | VXLAN Network Identifier (VNI) | Reserved |
|
||||
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
+ * Ver = Version. Indicates VXLAN GPE protocol version. The initial
|
||||
+ * version is 0. If a receiver does not support the version
|
||||
+ * indicated it MUST drop the packet.
|
||||
+ *
|
||||
+ * I = Instance Bit. The I bit MUST be set to indicate a valid VNI.
|
||||
+ *
|
||||
+ * P = Next Protocol Bit. The P bit is set to indicate that the
|
||||
+ * Next Protocol field is present.
|
||||
+ *
|
||||
+ * O = OAM Flag Bit. The O bit is set to indicate that the packet
|
||||
+ * is an OAM packet.
|
||||
+ *
|
||||
+ * [1] https://www.ietf.org/id/draft-ietf-nvo3-vxlan-gpe-01.txt
|
||||
+ */
|
||||
+
|
||||
+struct vxlanhdr_gpe {
|
||||
+#ifdef __LITTLE_ENDIAN_BITFIELD
|
||||
+ uint8_t oam_flag:1;
|
||||
+ uint8_t reserved_flags1:1;
|
||||
+ uint8_t np_applied:1;
|
||||
+ uint8_t instance_applied:1;
|
||||
+ uint8_t gpe_version:2;
|
||||
+ uint8_t reserved_flags2:2;
|
||||
+#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
+ uint8_t reserved_flags2:2;
|
||||
+ uint8_t gpe_version:2;
|
||||
+ uint8_t instance_applied:1;
|
||||
+ uint8_t np_applied:1;
|
||||
+ uint8_t reserved_flags1:1;
|
||||
+ uint8_t oam_flag:1;
|
||||
+#else
|
||||
+#error "Please fix <asm/byteorder.h>"
|
||||
+#endif
|
||||
+ uint8_t reserved_flags3;
|
||||
+ uint8_t reserved_flags4;
|
||||
+ uint8_t next_proto;
|
||||
+ __be32 vx_vni;
|
||||
+};
|
||||
+
|
||||
+/* VxLAN-GPE Header Next Protocol */
|
||||
+#define VXLAN_GPE_NP_IPV4 0x01
|
||||
+#define VXLAN_GPE_NP_IPV6 0x02
|
||||
+#define VXLAN_GPE_NP_ETHERNET 0x03
|
||||
+#define VXLAN_GPE_NP_NSH 0x04
|
||||
+
|
||||
+/* skb->mark mapping
|
||||
+ *
|
||||
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
+ * |R|R|Ver|I|P|R|O|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R|R| Next Proto |
|
||||
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
+ */
|
||||
+
|
||||
+#define VXLAN_GPE_OAM_FLAG (BIT(0) << 24)
|
||||
+#define VXLAN_GPE_NP_APPLIED (BIT(0) << 26)
|
||||
+#define VXLAN_GPE_INSTANCE_APPLIED (BIT(0) << 27)
|
||||
+#define VXLAN_GPE_VERSION ((BIT(0) << 28) | (BIT(0) << 29))
|
||||
+
|
||||
+#define VXLAN_GPE_NP_MASK (0xFF)
|
||||
+
|
||||
+#define VXLAN_GPE_USED_BITS (VXLAN_GPE_OAM_FLAG | VXLAN_GPE_NP_APPLIED \
|
||||
+ | VXLAN_GPE_INSTANCE_APPLIED | VXLAN_GPE_VERSION | 0xFF)
|
||||
+
|
||||
/* VXLAN protocol header:
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* |G|R|R|R|I|R|R|C| Reserved |
|
||||
@@ -104,6 +173,7 @@ struct vxlanhdr {
|
||||
#define VXLAN_HF_RCO BIT(21)
|
||||
#define VXLAN_HF_VNI BIT(27)
|
||||
#define VXLAN_HF_GBP BIT(31)
|
||||
+#define VXLAN_HF_GPE BIT(26)
|
||||
|
||||
/* Remote checksum offload header option */
|
||||
#define VXLAN_RCO_MASK 0x7f /* Last byte of vni field */
|
||||
@@ -120,6 +190,7 @@ struct vxlanhdr {
|
||||
struct vxlan_metadata {
|
||||
__be32 vni;
|
||||
u32 gbp;
|
||||
+ u32 gpe;
|
||||
};
|
||||
|
||||
#define VNI_HASH_BITS 10
|
||||
@@ -205,11 +276,13 @@ struct vxlan_dev {
|
||||
#define VXLAN_F_GBP 0x800
|
||||
#define VXLAN_F_REMCSUM_NOPARTIAL 0x1000
|
||||
#define VXLAN_F_COLLECT_METADATA 0x2000
|
||||
+#define VXLAN_F_GPE 0x4000
|
||||
|
||||
/* Flags that are used in the receive path. These flags must match in
|
||||
* order for a socket to be shareable
|
||||
*/
|
||||
#define VXLAN_F_RCV_FLAGS (VXLAN_F_GBP | \
|
||||
+ VXLAN_F_GPE | \
|
||||
VXLAN_F_UDP_ZERO_CSUM6_RX | \
|
||||
VXLAN_F_REMCSUM_RX | \
|
||||
VXLAN_F_REMCSUM_NOPARTIAL | \
|
||||
diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c
|
||||
index 4faa18f..7ef051c 100644
|
||||
--- a/datapath/linux/compat/vxlan.c
|
||||
+++ b/datapath/linux/compat/vxlan.c
|
||||
@@ -971,6 +971,18 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
|
||||
md->gbp |= VXLAN_GBP_POLICY_APPLIED;
|
||||
|
||||
flags &= ~VXLAN_GBP_USED_BITS;
|
||||
+ } else if ((flags & VXLAN_HF_GPE) && (vs->flags & VXLAN_F_GPE)) {
|
||||
+ struct vxlanhdr_gpe *gpe;
|
||||
+
|
||||
+ gpe = (struct vxlanhdr_gpe *)vxh;
|
||||
+ md->gpe = ntohs(gpe->next_proto);
|
||||
+
|
||||
+ buf.dst.u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;
|
||||
+
|
||||
+ if (gpe->oam_flag)
|
||||
+ md->gpe |= VXLAN_GPE_OAM_FLAG;
|
||||
+
|
||||
+ flags &= ~VXLAN_GPE_USED_BITS;
|
||||
}
|
||||
|
||||
if (flags || vni & ~VXLAN_VNI_MASK) {
|
||||
@@ -1023,6 +1035,22 @@ static void vxlan_build_gbp_hdr(struct vxlanhdr *vxh, u32 vxflags,
|
||||
gbp->policy_id = htons(md->gbp & VXLAN_GBP_ID_MASK);
|
||||
}
|
||||
|
||||
+static void vxlan_build_gpe_hdr(struct vxlanhdr *vxh, u32 vxflags,
|
||||
+ struct vxlan_metadata *md)
|
||||
+{
|
||||
+ struct vxlanhdr_gpe *gpe;
|
||||
+
|
||||
+ if (!md->gpe)
|
||||
+ return;
|
||||
+
|
||||
+ gpe = (struct vxlanhdr_gpe*)vxh;
|
||||
+ vxh->vx_flags |= htonl(VXLAN_HF_GPE);
|
||||
+
|
||||
+ if (md->gpe & VXLAN_GPE_OAM_FLAG)
|
||||
+ gpe->oam_flag = 1;
|
||||
+ gpe->next_proto = md->gpe & VXLAN_GPE_NP_MASK;
|
||||
+}
|
||||
+
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
|
||||
struct sk_buff *skb,
|
||||
@@ -1106,6 +1134,8 @@ static int vxlan6_xmit_skb(struct dst_entry *dst, struct sock *sk,
|
||||
|
||||
if (vxflags & VXLAN_F_GBP)
|
||||
vxlan_build_gbp_hdr(vxh, vxflags, md);
|
||||
+ else if (vxflags & VXLAN_F_GPE)
|
||||
+ vxlan_build_gpe_hdr(vxh, vxflags, md);
|
||||
|
||||
ovs_skb_set_inner_protocol(skb, htons(ETH_P_TEB));
|
||||
|
||||
diff --git a/datapath/vport-vxlan.c b/datapath/vport-vxlan.c
|
||||
index c05f5d4..5d775cc 100644
|
||||
--- a/datapath/vport-vxlan.c
|
||||
+++ b/datapath/vport-vxlan.c
|
||||
@@ -52,6 +52,18 @@ static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
|
||||
return -EMSGSIZE;
|
||||
|
||||
nla_nest_end(skb, exts);
|
||||
+ } else if (vxlan->flags & VXLAN_F_GPE) {
|
||||
+ struct nlattr *exts;
|
||||
+
|
||||
+ exts = nla_nest_start(skb, OVS_TUNNEL_ATTR_EXTENSION);
|
||||
+ if (!exts)
|
||||
+ return -EMSGSIZE;
|
||||
+
|
||||
+ if (vxlan->flags & VXLAN_F_GPE &&
|
||||
+ nla_put_flag(skb, OVS_VXLAN_EXT_GPE))
|
||||
+ return -EMSGSIZE;
|
||||
+
|
||||
+ nla_nest_end(skb, exts);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -59,6 +71,7 @@ static int vxlan_get_options(const struct vport *vport, struct sk_buff *skb)
|
||||
|
||||
static const struct nla_policy exts_policy[OVS_VXLAN_EXT_MAX + 1] = {
|
||||
[OVS_VXLAN_EXT_GBP] = { .type = NLA_FLAG, },
|
||||
+ [OVS_VXLAN_EXT_GPE] = { .type = NLA_FLAG, },
|
||||
};
|
||||
|
||||
static int vxlan_configure_exts(struct vport *vport, struct nlattr *attr,
|
||||
@@ -76,6 +89,8 @@ static int vxlan_configure_exts(struct vport *vport, struct nlattr *attr,
|
||||
|
||||
if (exts[OVS_VXLAN_EXT_GBP])
|
||||
conf->flags |= VXLAN_F_GBP;
|
||||
+ else if (exts[OVS_VXLAN_EXT_GPE])
|
||||
+ conf->flags |= VXLAN_F_GPE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/lib/flow.c b/lib/flow.c
|
||||
index b9ce331..d24bdc9 100644
|
||||
--- a/lib/flow.c
|
||||
+++ b/lib/flow.c
|
||||
@@ -870,6 +870,12 @@ flow_get_metadata(const struct flow *flow, struct match *flow_metadata)
|
||||
if (flow->tunnel.gbp_flags) {
|
||||
match_set_tun_gbp_flags(flow_metadata, flow->tunnel.gbp_flags);
|
||||
}
|
||||
+ if (flow->tunnel.gpe_np != htons(0)) {
|
||||
+ match_set_tun_gpe_np(flow_metadata, flow->tunnel.gpe_np);
|
||||
+ }
|
||||
+ if (flow->tunnel.gpe_flags) {
|
||||
+ match_set_tun_gpe_flags(flow_metadata, flow->tunnel.gpe_flags);
|
||||
+ }
|
||||
tun_metadata_get_fmd(&flow->tunnel, flow_metadata);
|
||||
if (flow->metadata != htonll(0)) {
|
||||
match_set_metadata(flow_metadata, flow->metadata);
|
||||
@@ -1265,6 +1271,8 @@ void flow_wildcards_init_for_packet(struct flow_wildcards *wc,
|
||||
WC_MASK_FIELD(wc, tunnel.tp_dst);
|
||||
WC_MASK_FIELD(wc, tunnel.gbp_id);
|
||||
WC_MASK_FIELD(wc, tunnel.gbp_flags);
|
||||
+ WC_MASK_FIELD(wc, tunnel.gpe_np);
|
||||
+ WC_MASK_FIELD(wc, tunnel.gpe_flags);
|
||||
|
||||
if (!(flow->tunnel.flags & FLOW_TNL_F_UDPIF)) {
|
||||
if (flow->tunnel.metadata.present.map) {
|
||||
diff --git a/lib/match.c b/lib/match.c
|
||||
index fd571d9..52437c9 100644
|
||||
--- a/lib/match.c
|
||||
+++ b/lib/match.c
|
||||
@@ -289,6 +289,32 @@ match_set_tun_gbp_flags(struct match *match, uint8_t flags)
|
||||
}
|
||||
|
||||
void
|
||||
+match_set_tun_gpe_np_masked(struct match *match, uint8_t np, uint8_t mask)
|
||||
+{
|
||||
+ match->wc.masks.tunnel.gpe_np = mask;
|
||||
+ match->flow.tunnel.gpe_np = np & mask;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+match_set_tun_gpe_np(struct match *match, uint8_t np)
|
||||
+{
|
||||
+ match_set_tun_gpe_np_masked(match, np, UINT8_MAX);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+match_set_tun_gpe_flags_masked(struct match *match, uint8_t flags, uint8_t mask)
|
||||
+{
|
||||
+ match->wc.masks.tunnel.gpe_flags = mask;
|
||||
+ match->flow.tunnel.gpe_flags = flags & mask;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+match_set_tun_gpe_flags(struct match *match, uint8_t flags)
|
||||
+{
|
||||
+ match_set_tun_gpe_flags_masked(match, flags, UINT8_MAX);
|
||||
+}
|
||||
+
|
||||
+void
|
||||
match_set_in_port(struct match *match, ofp_port_t ofp_port)
|
||||
{
|
||||
match->wc.masks.in_port.ofp_port = u16_to_ofp(UINT16_MAX);
|
||||
@@ -1013,6 +1039,14 @@ format_flow_tunnel(struct ds *s, const struct match *match)
|
||||
ds_put_format(s, "tun_gbp_flags=%#"PRIx8",", tnl->gbp_flags);
|
||||
}
|
||||
|
||||
+ if (wc->masks.tunnel.gpe_np) {
|
||||
+ ds_put_format(s, "tun_gpe_np=%#"PRIx8",", tnl->gpe_np);
|
||||
+ }
|
||||
+
|
||||
+ if (wc->masks.tunnel.gpe_flags) {
|
||||
+ ds_put_format(s, "tun_gpe_flags=%#"PRIx8",", tnl->gpe_flags);
|
||||
+ }
|
||||
+
|
||||
if (wc->masks.tunnel.ip_tos) {
|
||||
ds_put_format(s, "tun_tos=%"PRIx8",", tnl->ip_tos);
|
||||
}
|
||||
diff --git a/lib/match.h b/lib/match.h
|
||||
index 0a6ac29..48aa0b1 100644
|
||||
--- a/lib/match.h
|
||||
+++ b/lib/match.h
|
||||
@@ -86,6 +86,10 @@ void match_set_tun_gbp_id_masked(struct match *match, ovs_be16 gbp_id, ovs_be16
|
||||
void match_set_tun_gbp_id(struct match *match, ovs_be16 gbp_id);
|
||||
void match_set_tun_gbp_flags_masked(struct match *match, uint8_t flags, uint8_t mask);
|
||||
void match_set_tun_gbp_flags(struct match *match, uint8_t flags);
|
||||
+void match_set_tun_gpe_np_masked(struct match *match, uint8_t gpe_np, uint8_t mask);
|
||||
+void match_set_tun_gpe_np(struct match *match, uint8_t gpe_np);
|
||||
+void match_set_tun_gpe_flags_masked(struct match *match, uint8_t flags, uint8_t mask);
|
||||
+void match_set_tun_gpe_flags(struct match *match, uint8_t flags);
|
||||
void match_set_in_port(struct match *, ofp_port_t ofp_port);
|
||||
void match_set_pkt_mark(struct match *, uint32_t pkt_mark);
|
||||
void match_set_pkt_mark_masked(struct match *, uint32_t pkt_mark, uint32_t mask);
|
||||
diff --git a/lib/meta-flow.c b/lib/meta-flow.c
|
||||
index 721152c..ab77fca 100644
|
||||
--- a/lib/meta-flow.c
|
||||
+++ b/lib/meta-flow.c
|
||||
@@ -213,6 +213,10 @@ mf_is_all_wild(const struct mf_field *mf, const struct flow_wildcards *wc)
|
||||
return !wc->masks.tunnel.gbp_id;
|
||||
case MFF_TUN_GBP_FLAGS:
|
||||
return !wc->masks.tunnel.gbp_flags;
|
||||
+ case MFF_TUN_GPE_NP:
|
||||
+ return !wc->masks.tunnel.gpe_np;
|
||||
+ case MFF_TUN_GPE_FLAGS:
|
||||
+ return !wc->masks.tunnel.gpe_flags;
|
||||
CASE_MFF_TUN_METADATA:
|
||||
return !ULLONG_GET(wc->masks.tunnel.metadata.present.map,
|
||||
mf->id - MFF_TUN_METADATA0);
|
||||
@@ -515,6 +519,8 @@ mf_is_value_valid(const struct mf_field *mf, const union mf_value *value)
|
||||
case MFF_TUN_TTL:
|
||||
case MFF_TUN_GBP_ID:
|
||||
case MFF_TUN_GBP_FLAGS:
|
||||
+ case MFF_TUN_GPE_NP:
|
||||
+ case MFF_TUN_GPE_FLAGS:
|
||||
CASE_MFF_TUN_METADATA:
|
||||
case MFF_METADATA:
|
||||
case MFF_IN_PORT:
|
||||
@@ -648,6 +654,12 @@ mf_get_value(const struct mf_field *mf, const struct flow *flow,
|
||||
case MFF_TUN_GBP_FLAGS:
|
||||
value->u8 = flow->tunnel.gbp_flags;
|
||||
break;
|
||||
+ case MFF_TUN_GPE_NP:
|
||||
+ value->u8 = flow->tunnel.gpe_np;
|
||||
+ break;
|
||||
+ case MFF_TUN_GPE_FLAGS:
|
||||
+ value->u8 = flow->tunnel.gpe_flags;
|
||||
+ break;
|
||||
case MFF_TUN_TTL:
|
||||
value->u8 = flow->tunnel.ip_ttl;
|
||||
break;
|
||||
@@ -899,6 +911,12 @@ mf_set_value(const struct mf_field *mf,
|
||||
case MFF_TUN_GBP_FLAGS:
|
||||
match_set_tun_gbp_flags(match, value->u8);
|
||||
break;
|
||||
+ case MFF_TUN_GPE_NP:
|
||||
+ match_set_tun_gpe_np(match, value->u8);
|
||||
+ break;
|
||||
+ case MFF_TUN_GPE_FLAGS:
|
||||
+ match_set_tun_gpe_flags(match, value->u8);
|
||||
+ break;
|
||||
case MFF_TUN_TOS:
|
||||
match_set_tun_tos(match, value->u8);
|
||||
break;
|
||||
@@ -1216,6 +1234,12 @@ mf_set_flow_value(const struct mf_field *mf,
|
||||
case MFF_TUN_GBP_FLAGS:
|
||||
flow->tunnel.gbp_flags = value->u8;
|
||||
break;
|
||||
+ case MFF_TUN_GPE_NP:
|
||||
+ flow->tunnel.gpe_np= value->u8;
|
||||
+ break;
|
||||
+ case MFF_TUN_GPE_FLAGS:
|
||||
+ flow->tunnel.gpe_flags= value->u8;
|
||||
+ break;
|
||||
case MFF_TUN_TOS:
|
||||
flow->tunnel.ip_tos = value->u8;
|
||||
break;
|
||||
@@ -1535,6 +1559,12 @@ mf_set_wild(const struct mf_field *mf, struct match *match, char **err_str)
|
||||
case MFF_TUN_GBP_FLAGS:
|
||||
match_set_tun_gbp_flags_masked(match, 0, 0);
|
||||
break;
|
||||
+ case MFF_TUN_GPE_NP:
|
||||
+ match_set_tun_gpe_np_masked(match, 0, 0);
|
||||
+ break;
|
||||
+ case MFF_TUN_GPE_FLAGS:
|
||||
+ match_set_tun_gpe_flags_masked(match, 0, 0);
|
||||
+ break;
|
||||
case MFF_TUN_TOS:
|
||||
match_set_tun_tos_masked(match, 0, 0);
|
||||
break;
|
||||
@@ -1838,6 +1868,12 @@ mf_set(const struct mf_field *mf,
|
||||
case MFF_TUN_GBP_FLAGS:
|
||||
match_set_tun_gbp_flags_masked(match, value->u8, mask->u8);
|
||||
break;
|
||||
+ case MFF_TUN_GPE_NP:
|
||||
+ match_set_tun_gpe_np_masked(match, value->u8, mask->u8);
|
||||
+ break;
|
||||
+ case MFF_TUN_GPE_FLAGS:
|
||||
+ match_set_tun_gpe_flags_masked(match, value->u8, mask->u8);
|
||||
+ break;
|
||||
case MFF_TUN_TTL:
|
||||
match_set_tun_ttl_masked(match, value->u8, mask->u8);
|
||||
break;
|
||||
diff --git a/lib/meta-flow.h b/lib/meta-flow.h
|
||||
index c73a1af..4bd9ff6 100644
|
||||
--- a/lib/meta-flow.h
|
||||
+++ b/lib/meta-flow.h
|
||||
@@ -491,6 +491,34 @@ enum OVS_PACKED_ENUM mf_field_id {
|
||||
*/
|
||||
MFF_TUN_GBP_FLAGS,
|
||||
|
||||
+ /* "tun_gpe_np".
|
||||
+ *
|
||||
+ * VXLAN Generic Protocol Extension next_proto
|
||||
+ *
|
||||
+ * Type: u8.
|
||||
+ * Maskable: bitwise.
|
||||
+ * Formatting: hexadecimal.
|
||||
+ * Prerequisites: none.
|
||||
+ * Access: read/write.
|
||||
+ * NXM: NXM_NX_TUN_GPE_NP(111) since v2.4.
|
||||
+ * OXM: none.
|
||||
+ */
|
||||
+ MFF_TUN_GPE_NP,
|
||||
+
|
||||
+ /* "tun_gpe_flags".
|
||||
+ *
|
||||
+ * VXLAN Generic Protocol Extension flag
|
||||
+ *
|
||||
+ * Type: u8.
|
||||
+ * Maskable: bitwise.
|
||||
+ * Formatting: hexadecimal.
|
||||
+ * Prerequisites: none.
|
||||
+ * Access: read/write.
|
||||
+ * NXM: NXM_NX_TUN_GPE_FLAGS(112) since v2.4.
|
||||
+ * OXM: none.
|
||||
+ */
|
||||
+ MFF_TUN_GPE_FLAGS,
|
||||
+
|
||||
#if TUN_METADATA_NUM_OPTS == 64
|
||||
/* "tun_metadata<N>".
|
||||
*
|
||||
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
|
||||
index e398562..92ceec1 100644
|
||||
--- a/lib/netdev-vport.c
|
||||
+++ b/lib/netdev-vport.c
|
||||
@@ -583,6 +583,8 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
|
||||
while (ext) {
|
||||
if (!strcmp(type, "vxlan") && !strcmp(ext, "gbp")) {
|
||||
tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GBP);
|
||||
+ } else if (!strcmp(type, "vxlan") && !strcmp(ext, "gpe")) {
|
||||
+ tnl_cfg.exts |= (1 << OVS_VXLAN_EXT_GPE);
|
||||
} else {
|
||||
VLOG_WARN("%s: unknown extension '%s'", name, ext);
|
||||
}
|
||||
diff --git a/lib/nx-match.c b/lib/nx-match.c
|
||||
index 9f0f452..0eecac7 100644
|
||||
--- a/lib/nx-match.c
|
||||
+++ b/lib/nx-match.c
|
||||
@@ -1037,6 +1037,10 @@ nx_put_raw(struct ofpbuf *b, enum ofp_version oxm, const struct match *match,
|
||||
flow->tunnel.gbp_id, match->wc.masks.tunnel.gbp_id);
|
||||
nxm_put_8m(b, MFF_TUN_GBP_FLAGS, oxm,
|
||||
flow->tunnel.gbp_flags, match->wc.masks.tunnel.gbp_flags);
|
||||
+ nxm_put_8m(b, MFF_TUN_GPE_NP, oxm,
|
||||
+ flow->tunnel.gpe_np, match->wc.masks.tunnel.gpe_np);
|
||||
+ nxm_put_8m(b, MFF_TUN_GPE_FLAGS, oxm,
|
||||
+ flow->tunnel.gpe_flags, match->wc.masks.tunnel.gpe_flags);
|
||||
tun_metadata_to_nx_match(b, oxm, match);
|
||||
|
||||
/* Registers. */
|
||||
diff --git a/lib/odp-util.c b/lib/odp-util.c
|
||||
index b4689cc..7983720 100644
|
||||
--- a/lib/odp-util.c
|
||||
+++ b/lib/odp-util.c
|
||||
@@ -1727,6 +1727,7 @@ odp_actions_from_string(const char *s, const struct simap *port_names,
|
||||
|
||||
static const struct attr_len_tbl ovs_vxlan_ext_attr_lens[OVS_VXLAN_EXT_MAX + 1] = {
|
||||
[OVS_VXLAN_EXT_GBP] = { .len = 4 },
|
||||
+ [OVS_VXLAN_EXT_GPE] = { .len = 4 },
|
||||
};
|
||||
|
||||
static const struct attr_len_tbl ovs_tun_key_attr_lens[OVS_TUNNEL_KEY_ATTR_MAX + 1] = {
|
||||
@@ -1888,7 +1889,10 @@ odp_tun_key_from_attr__(const struct nlattr *attr,
|
||||
break;
|
||||
case OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS: {
|
||||
static const struct nl_policy vxlan_opts_policy[] = {
|
||||
- [OVS_VXLAN_EXT_GBP] = { .type = NL_A_U32 },
|
||||
+ [OVS_VXLAN_EXT_GBP] = { .type = NL_A_U32 ,
|
||||
+ .optional = true },
|
||||
+ [OVS_VXLAN_EXT_GPE] = { .type = NL_A_U32 ,
|
||||
+ .optional = true },
|
||||
};
|
||||
struct nlattr *ext[ARRAY_SIZE(vxlan_opts_policy)];
|
||||
|
||||
@@ -1902,6 +1906,12 @@ odp_tun_key_from_attr__(const struct nlattr *attr,
|
||||
tun->gbp_id = htons(gbp & 0xFFFF);
|
||||
tun->gbp_flags = (gbp >> 16) & 0xFF;
|
||||
}
|
||||
+ if (ext[OVS_VXLAN_EXT_GPE]) {
|
||||
+ uint32_t gpe = nl_attr_get_u32(ext[OVS_VXLAN_EXT_GPE]);
|
||||
+
|
||||
+ tun->gpe_np = gpe & 0xFF;
|
||||
+ tun->gpe_flags = gpe >> 24;
|
||||
+ }
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -1988,6 +1998,13 @@ tun_key_to_attr(struct ofpbuf *a, const struct flow_tnl *tun_key,
|
||||
nl_msg_put_u32(a, OVS_VXLAN_EXT_GBP,
|
||||
(tun_key->gbp_flags << 16) | ntohs(tun_key->gbp_id));
|
||||
nl_msg_end_nested(a, vxlan_opts_ofs);
|
||||
+ } else if (tun_key->gpe_flags || tun_key->gpe_np) {
|
||||
+ size_t vxlan_opts_ofs;
|
||||
+
|
||||
+ vxlan_opts_ofs = nl_msg_start_nested(a, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
|
||||
+ nl_msg_put_u32(a, OVS_VXLAN_EXT_GPE,
|
||||
+ (tun_key->gpe_flags << 24) | (tun_key->gpe_np));
|
||||
+ nl_msg_end_nested(a, vxlan_opts_ofs);
|
||||
}
|
||||
tun_metadata_to_geneve_nlattr(tun_key, tun_flow_key, key_buf, a);
|
||||
|
||||
@@ -2383,6 +2400,26 @@ format_odp_tun_vxlan_opt(const struct nlattr *attr,
|
||||
ds_put_cstr(ds, "),");
|
||||
break;
|
||||
}
|
||||
+ case OVS_VXLAN_EXT_GPE: {
|
||||
+ uint32_t key = nl_attr_get_u32(a);
|
||||
+ uint8_t np, np_mask;
|
||||
+ uint8_t flags, flags_mask;
|
||||
+
|
||||
+ np = key & 0xFF;
|
||||
+ flags = (key >> 24) & 0xFF;
|
||||
+ if (ma) {
|
||||
+ uint32_t mask = nl_attr_get_u32(ma);
|
||||
+ np_mask = mask & 0xFF;
|
||||
+ flags_mask = (mask >> 24) & 0xFF;
|
||||
+ }
|
||||
+
|
||||
+ ds_put_cstr(ds, "gpe(");
|
||||
+ format_u8x(ds, "np", np, ma ? &np_mask : NULL, verbose);
|
||||
+ format_u8x(ds, "flags", flags, ma ? &flags_mask : NULL, verbose);
|
||||
+ ds_chomp(ds, ',');
|
||||
+ ds_put_cstr(ds, "),");
|
||||
+ break;
|
||||
+ }
|
||||
|
||||
default:
|
||||
format_unknown_key(ds, a, ma);
|
||||
@@ -3670,6 +3707,40 @@ scan_vxlan_gbp(const char *s, uint32_t *key, uint32_t *mask)
|
||||
}
|
||||
|
||||
static int
|
||||
+scan_vxlan_gpe(const char *s, uint32_t *key, uint32_t *mask)
|
||||
+{
|
||||
+ const char *s_base = s;
|
||||
+ uint8_t np = 0, np_mask = 0;
|
||||
+ uint8_t flags = 0, flags_mask = 0;
|
||||
+
|
||||
+ if (!strncmp(s, "np=", 3)) {
|
||||
+ s += 3;
|
||||
+ s += scan_u8(s, &np, mask ? &np_mask : NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (s[0] == ',') {
|
||||
+ s++;
|
||||
+ }
|
||||
+ if (!strncmp(s, "flags=", 6)) {
|
||||
+ s += 6;
|
||||
+ s += scan_u8(s, &flags, mask ? &flags_mask : NULL);
|
||||
+ }
|
||||
+
|
||||
+ if (!strncmp(s, "))", 2)) {
|
||||
+ s += 2;
|
||||
+
|
||||
+ *key = (flags << 24) | np;
|
||||
+ if (mask) {
|
||||
+ *mask = (flags_mask << 24) | np_mask;
|
||||
+ }
|
||||
+
|
||||
+ return s - s_base;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
scan_geneve(const char *s, struct geneve_scan *key, struct geneve_scan *mask)
|
||||
{
|
||||
const char *s_base = s;
|
||||
@@ -3796,6 +3867,21 @@ vxlan_gbp_to_attr(struct ofpbuf *a, const void *data_)
|
||||
}
|
||||
|
||||
static void
|
||||
+vxlan_gpe_to_attr(struct ofpbuf *a, const void *data_)
|
||||
+{
|
||||
+ const uint32_t *gpe = data_;
|
||||
+
|
||||
+ if (*gpe) {
|
||||
+ size_t vxlan_opts_ofs;
|
||||
+
|
||||
+ vxlan_opts_ofs = nl_msg_start_nested(a, OVS_TUNNEL_KEY_ATTR_VXLAN_OPTS);
|
||||
+ nl_msg_put_u32(a, OVS_VXLAN_EXT_GPE, *gpe);
|
||||
+ nl_msg_end_nested(a, vxlan_opts_ofs);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void
|
||||
geneve_to_attr(struct ofpbuf *a, const void *data_)
|
||||
{
|
||||
const struct geneve_scan *geneve = data_;
|
||||
@@ -4031,6 +4117,7 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
|
||||
SCAN_FIELD_NESTED("tp_src=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_SRC);
|
||||
SCAN_FIELD_NESTED("tp_dst=", ovs_be16, be16, OVS_TUNNEL_KEY_ATTR_TP_DST);
|
||||
SCAN_FIELD_NESTED_FUNC("vxlan(gbp(", uint32_t, vxlan_gbp, vxlan_gbp_to_attr);
|
||||
+ SCAN_FIELD_NESTED_FUNC("vxlan(gpe(", uint32_t, vxlan_gpe, vxlan_gpe_to_attr);
|
||||
SCAN_FIELD_NESTED_FUNC("geneve(", struct geneve_scan, geneve,
|
||||
geneve_to_attr);
|
||||
SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr);
|
||||
diff --git a/lib/packets.h b/lib/packets.h
|
||||
index a8ea24b..dc97333 100644
|
||||
--- a/lib/packets.h
|
||||
+++ b/lib/packets.h
|
||||
@@ -49,7 +49,9 @@ struct flow_tnl {
|
||||
ovs_be16 tp_dst;
|
||||
ovs_be16 gbp_id;
|
||||
uint8_t gbp_flags;
|
||||
- uint8_t pad1[5]; /* Pad to 64 bits. */
|
||||
+ uint8_t gpe_np;
|
||||
+ uint8_t gpe_flags;
|
||||
+ uint8_t pad1[3]; /* Pad to 64 bits. */
|
||||
struct tun_metadata metadata;
|
||||
};
|
||||
|
||||
diff --git a/tests/ofproto.at b/tests/ofproto.at
|
||||
index fbb6d71..6c7217d 100644
|
||||
--- a/tests/ofproto.at
|
||||
+++ b/tests/ofproto.at
|
||||
@@ -1775,7 +1775,7 @@ head_table () {
|
||||
instructions: meter,apply_actions,clear_actions,write_actions,write_metadata,goto_table
|
||||
Write-Actions and Apply-Actions features:
|
||||
actions: output group set_field strip_vlan push_vlan mod_nw_ttl dec_ttl set_mpls_ttl dec_mpls_ttl push_mpls pop_mpls set_queue
|
||||
- supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_metadata0 dnl
|
||||
+ supported on Set-Field: tun_id tun_src tun_dst tun_ipv6_src tun_ipv6_dst tun_flags tun_gbp_id tun_gbp_flags tun_gpe_np tun_gpe_flags tun_metadata0 dnl
|
||||
tun_metadata1 tun_metadata2 tun_metadata3 tun_metadata4 tun_metadata5 tun_metadata6 tun_metadata7 tun_metadata8 tun_metadata9 tun_metadata10 tun_metadata11 tun_metadata12 tun_metadata13 tun_metadata14 tun_metadata15 tun_metadata16 tun_metadata17 tun_metadata18 tun_metadata19 tun_metadata20 tun_metadata21 tun_metadata22 tun_metadata23 tun_metadata24 tun_metadata25 tun_metadata26 tun_metadata27 tun_metadata28 tun_metadata29 tun_metadata30 tun_metadata31 tun_metadata32 tun_metadata33 tun_metadata34 tun_metadata35 tun_metadata36 tun_metadata37 tun_metadata38 tun_metadata39 tun_metadata40 tun_metadata41 tun_metadata42 tun_metadata43 tun_metadata44 tun_metadata45 tun_metadata46 tun_metadata47 tun_metadata48 tun_metadata49 tun_metadata50 tun_metadata51 tun_metadata52 tun_metadata53 tun_metadata54 tun_metadata55 tun_metadata56 tun_metadata57 tun_metadata58 tun_metadata59 tun_metadata60 tun_metadata61 tun_metadata62 tun_metadata63 dnl
|
||||
metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4 reg5 reg6 reg7 xreg0 xreg1 xreg2 xreg3 eth_src eth_dst vlan_tci vlan_vid vlan_pcp mpls_label mpls_tc mpls_ttl ip_src ip_dst ipv6_src ipv6_dst ipv6_label nw_tos ip_dscp nw_ecn nw_ttl arp_op arp_spa arp_tpa arp_sha arp_tha tcp_src tcp_dst udp_src udp_dst sctp_src sctp_dst icmp_type icmp_code icmpv6_type icmpv6_code nd_target nd_sll nd_tll
|
||||
matching:
|
||||
@@ -1790,6 +1790,8 @@ metadata in_port in_port_oxm pkt_mark ct_mark ct_label reg0 reg1 reg2 reg3 reg4
|
||||
tun_flags: arbitrary mask
|
||||
tun_gbp_id: arbitrary mask
|
||||
tun_gbp_flags: arbitrary mask
|
||||
+ tun_gpe_np: arbitrary mask
|
||||
+ tun_gpe_flags: arbitrary mask
|
||||
tun_metadata0: arbitrary mask
|
||||
tun_metadata1: arbitrary mask
|
||||
tun_metadata2: arbitrary mask
|
||||
diff --git a/tests/ovs-ofctl.at b/tests/ovs-ofctl.at
|
||||
index f26f622..dde603d 100644
|
||||
--- a/tests/ovs-ofctl.at
|
||||
+++ b/tests/ovs-ofctl.at
|
||||
@@ -17,6 +17,10 @@ for test_case in \
|
||||
'tun_gbp_id=0/0x1 NXM,OXM' \
|
||||
'tun_gbp_flags=0 NXM,OXM' \
|
||||
'tun_gbp_flags=0/0x1 NXM,OXM' \
|
||||
+ 'tun_gpe_np=0 NXM,OXM' \
|
||||
+ 'tun_gpe_np=0/0x1 NXM,OXM' \
|
||||
+ 'tun_gpe_flags=0 NXM,OXM' \
|
||||
+ 'tun_gpe_flags=0/0x1 NXM,OXM' \
|
||||
'tun_metadata0=0 NXM,OXM' \
|
||||
'tun_metadata0=0/0x1 NXM,OXM' \
|
||||
'tun_metadata0 NXM,OXM' \
|
||||
--
|
||||
1.9.3
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,264 @@
|
|||
From e6f9b1f96a3ac4066c9d7d4c0a9da7e8abb1597f Mon Sep 17 00:00:00 2001
|
||||
From: Yi Yang <yi.y.yang@intel.com>
|
||||
Date: Wed, 13 Apr 2016 18:17:21 +0800
|
||||
Subject: [PATCH 4/5] Fix too large stack frame size
|
||||
|
||||
Signed-off-by: Yi Yang <yi.y.yang@intel.com>
|
||||
---
|
||||
datapath/datapath.c | 92 +++++++++++++++++++++++++++++++++++++++++++++--------
|
||||
1 file changed, 78 insertions(+), 14 deletions(-)
|
||||
|
||||
diff --git a/datapath/datapath.c b/datapath/datapath.c
|
||||
index 5bec072..4baf242 100644
|
||||
--- a/datapath/datapath.c
|
||||
+++ b/datapath/datapath.c
|
||||
@@ -928,7 +928,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
struct sw_flow_mask mask;
|
||||
struct sk_buff *reply;
|
||||
struct datapath *dp;
|
||||
- struct sw_flow_key key;
|
||||
+ struct sw_flow_key *key = NULL;
|
||||
struct sw_flow_actions *acts;
|
||||
struct sw_flow_match match;
|
||||
u32 ufid_flags = ovs_nla_get_ufid_flags(a[OVS_FLOW_ATTR_UFID_FLAGS]);
|
||||
@@ -946,6 +946,12 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
goto error;
|
||||
}
|
||||
|
||||
+ error = -ENOMEM;
|
||||
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
||||
+ if (key == NULL) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
/* Most of the time we need to allocate a new flow, do it before
|
||||
* locking.
|
||||
*/
|
||||
@@ -956,17 +962,17 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
/* Extract key. */
|
||||
- ovs_match_init(&match, &key, &mask);
|
||||
+ ovs_match_init(&match, key, &mask);
|
||||
error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
|
||||
a[OVS_FLOW_ATTR_MASK], log);
|
||||
if (error)
|
||||
goto err_kfree_flow;
|
||||
|
||||
- ovs_flow_mask_key(&new_flow->key, &key, true, &mask);
|
||||
+ ovs_flow_mask_key(&new_flow->key, key, true, &mask);
|
||||
|
||||
/* Extract flow identifier. */
|
||||
error = ovs_nla_get_identifier(&new_flow->id, a[OVS_FLOW_ATTR_UFID],
|
||||
- &key, log);
|
||||
+ key, log);
|
||||
if (error)
|
||||
goto err_kfree_flow;
|
||||
|
||||
@@ -996,7 +1002,7 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
if (ovs_identifier_is_ufid(&new_flow->id))
|
||||
flow = ovs_flow_tbl_lookup_ufid(&dp->table, &new_flow->id);
|
||||
if (!flow)
|
||||
- flow = ovs_flow_tbl_lookup(&dp->table, &key);
|
||||
+ flow = ovs_flow_tbl_lookup(&dp->table, key);
|
||||
if (likely(!flow)) {
|
||||
rcu_assign_pointer(new_flow->sf_acts, acts);
|
||||
|
||||
@@ -1066,6 +1072,10 @@ static int ovs_flow_cmd_new(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
if (reply)
|
||||
ovs_notify(&dp_flow_genl_family, &ovs_dp_flow_multicast_group, reply, info);
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return 0;
|
||||
|
||||
err_unlock_ovs:
|
||||
@@ -1076,6 +1086,10 @@ err_kfree_acts:
|
||||
err_kfree_flow:
|
||||
ovs_flow_free(new_flow, false);
|
||||
error:
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1106,7 +1120,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
struct net *net = sock_net(skb->sk);
|
||||
struct nlattr **a = info->attrs;
|
||||
struct ovs_header *ovs_header = info->userhdr;
|
||||
- struct sw_flow_key key;
|
||||
+ struct sw_flow_key *key = NULL;
|
||||
struct sw_flow *flow;
|
||||
struct sw_flow_mask mask;
|
||||
struct sk_buff *reply = NULL;
|
||||
@@ -1119,6 +1133,12 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
bool log = !a[OVS_FLOW_ATTR_PROBE];
|
||||
bool ufid_present;
|
||||
|
||||
+ error = -ENOMEM;
|
||||
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
||||
+ if (key == NULL) {
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
/* Extract key. */
|
||||
error = -EINVAL;
|
||||
if (!a[OVS_FLOW_ATTR_KEY]) {
|
||||
@@ -1127,7 +1147,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
ufid_present = ovs_nla_get_ufid(&sfid, a[OVS_FLOW_ATTR_UFID], log);
|
||||
- ovs_match_init(&match, &key, &mask);
|
||||
+ ovs_match_init(&match, key, &mask);
|
||||
error = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
|
||||
a[OVS_FLOW_ATTR_MASK], log);
|
||||
if (error)
|
||||
@@ -1135,7 +1155,7 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
|
||||
/* Validate actions. */
|
||||
if (a[OVS_FLOW_ATTR_ACTIONS]) {
|
||||
- acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], &key,
|
||||
+ acts = get_flow_actions(net, a[OVS_FLOW_ATTR_ACTIONS], key,
|
||||
&mask, log);
|
||||
if (IS_ERR(acts)) {
|
||||
error = PTR_ERR(acts);
|
||||
@@ -1203,6 +1223,10 @@ static int ovs_flow_cmd_set(struct sk_buff *skb, struct genl_info *info)
|
||||
if (old_acts)
|
||||
ovs_nla_free_flow_actions_rcu(old_acts);
|
||||
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return 0;
|
||||
|
||||
err_unlock_ovs:
|
||||
@@ -1211,6 +1235,10 @@ err_unlock_ovs:
|
||||
err_kfree_acts:
|
||||
ovs_nla_free_flow_actions(acts);
|
||||
error:
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1219,7 +1247,7 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
||||
struct nlattr **a = info->attrs;
|
||||
struct ovs_header *ovs_header = info->userhdr;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
- struct sw_flow_key key;
|
||||
+ struct sw_flow_key *key = NULL;
|
||||
struct sk_buff *reply;
|
||||
struct sw_flow *flow;
|
||||
struct datapath *dp;
|
||||
@@ -1230,9 +1258,15 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
||||
bool log = !a[OVS_FLOW_ATTR_PROBE];
|
||||
bool ufid_present;
|
||||
|
||||
+ err = -ENOMEM;
|
||||
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
||||
+ if (key == NULL) {
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
|
||||
if (a[OVS_FLOW_ATTR_KEY]) {
|
||||
- ovs_match_init(&match, &key, NULL);
|
||||
+ ovs_match_init(&match, key, NULL);
|
||||
err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY], NULL,
|
||||
log);
|
||||
} else if (!ufid_present) {
|
||||
@@ -1240,9 +1274,13 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
||||
"Flow get message rejected, Key attribute missing.");
|
||||
err = -EINVAL;
|
||||
}
|
||||
- if (err)
|
||||
+ if (err) {
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return err;
|
||||
-
|
||||
+ }
|
||||
ovs_lock();
|
||||
dp = get_dp(sock_net(skb->sk), ovs_header->dp_ifindex);
|
||||
if (!dp) {
|
||||
@@ -1267,9 +1305,17 @@ static int ovs_flow_cmd_get(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
ovs_unlock();
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return genlmsg_reply(reply, info);
|
||||
unlock:
|
||||
ovs_unlock();
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1278,7 +1324,7 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
||||
struct nlattr **a = info->attrs;
|
||||
struct ovs_header *ovs_header = info->userhdr;
|
||||
struct net *net = sock_net(skb->sk);
|
||||
- struct sw_flow_key key;
|
||||
+ struct sw_flow_key *key = NULL;
|
||||
struct sk_buff *reply;
|
||||
struct sw_flow *flow = NULL;
|
||||
struct datapath *dp;
|
||||
@@ -1289,12 +1335,22 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
||||
bool log = !a[OVS_FLOW_ATTR_PROBE];
|
||||
bool ufid_present;
|
||||
|
||||
+ err = -ENOMEM;
|
||||
+ key = kzalloc(sizeof(struct sw_flow_key), GFP_KERNEL);
|
||||
+ if (key == NULL) {
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
ufid_present = ovs_nla_get_ufid(&ufid, a[OVS_FLOW_ATTR_UFID], log);
|
||||
if (a[OVS_FLOW_ATTR_KEY]) {
|
||||
- ovs_match_init(&match, &key, NULL);
|
||||
+ ovs_match_init(&match, key, NULL);
|
||||
err = ovs_nla_get_match(net, &match, a[OVS_FLOW_ATTR_KEY],
|
||||
NULL, log);
|
||||
if (unlikely(err))
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -1344,9 +1400,17 @@ static int ovs_flow_cmd_del(struct sk_buff *skb, struct genl_info *info)
|
||||
}
|
||||
|
||||
ovs_flow_free(flow, true);
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return 0;
|
||||
unlock:
|
||||
ovs_unlock();
|
||||
+ if (key != NULL) {
|
||||
+ kfree(key);
|
||||
+ key = NULL;
|
||||
+ }
|
||||
return err;
|
||||
}
|
||||
|
||||
--
|
||||
1.9.3
|
||||
|
|
@ -0,0 +1,815 @@
|
|||
|
||||
|
||||
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" class="">
|
||||
<head prefix="og: http://ogp.me/ns# fb: http://ogp.me/ns/fb# object: http://ogp.me/ns/object# article: http://ogp.me/ns/article# profile: http://ogp.me/ns/profile#">
|
||||
<meta charset='utf-8'>
|
||||
|
||||
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/frameworks-536bcdee57776d99649d118d29a291c9d7b41d101696162d6456c87b07314253.css" media="all" rel="stylesheet" />
|
||||
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/github-62cdd177894e003285e5b8b6fa72b4a92fb79f11a1ec44c2f2ae0f6f4ad2e724.css" media="all" rel="stylesheet" />
|
||||
|
||||
|
||||
<link crossorigin="anonymous" href="https://assets-cdn.github.com/assets/site-c4b4365da282e51c06e107368db8502a2ecf82e64094d29d791b797372212de2.css" media="all" rel="stylesheet" />
|
||||
|
||||
|
||||
<link as="script" href="https://assets-cdn.github.com/assets/frameworks-b0aaa1e644508a5d5c3f7509d91f5f950c180e1d933a999f21747c5ec5411d92.js" rel="preload" />
|
||||
|
||||
<link as="script" href="https://assets-cdn.github.com/assets/github-7c9ed6fd84382ad236d74c9ec5853f75fca061537cb1914241807b12c289216e.js" rel="preload" />
|
||||
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta http-equiv="Content-Language" content="en">
|
||||
<meta name="viewport" content="width=device-width">
|
||||
|
||||
|
||||
<title>ovs_nsh_patches/0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch at master · yyang13/ovs_nsh_patches · GitHub</title>
|
||||
<link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">
|
||||
<link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
|
||||
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/apple-touch-icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/apple-touch-icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/apple-touch-icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/apple-touch-icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/apple-touch-icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon-180x180.png">
|
||||
<meta property="fb:app_id" content="1401488693436528">
|
||||
|
||||
<meta content="https://avatars0.githubusercontent.com/u/1381010?v=3&s=400" name="twitter:image:src" /><meta content="@github" name="twitter:site" /><meta content="summary" name="twitter:card" /><meta content="yyang13/ovs_nsh_patches" name="twitter:title" /><meta content="Contribute to ovs_nsh_patches development by creating an account on GitHub." name="twitter:description" />
|
||||
<meta content="https://avatars0.githubusercontent.com/u/1381010?v=3&s=400" property="og:image" /><meta content="GitHub" property="og:site_name" /><meta content="object" property="og:type" /><meta content="yyang13/ovs_nsh_patches" property="og:title" /><meta content="https://github.com/yyang13/ovs_nsh_patches" property="og:url" /><meta content="Contribute to ovs_nsh_patches development by creating an account on GitHub." property="og:description" />
|
||||
<meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">
|
||||
<meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">
|
||||
<link rel="assets" href="https://assets-cdn.github.com/">
|
||||
|
||||
<meta name="pjax-timeout" content="1000">
|
||||
|
||||
|
||||
<meta name="msapplication-TileImage" content="/windows-tile.png">
|
||||
<meta name="msapplication-TileColor" content="#ffffff">
|
||||
<meta name="selected-link" value="repo_source" data-pjax-transient>
|
||||
|
||||
<meta name="google-site-verification" content="KT5gs8h0wvaagLKAVWq8bbeNwnZZK1r1XQysX3xurLU">
|
||||
<meta name="google-site-verification" content="ZzhVyEFwb7w3e0-uOTltm8Jsck2F5StVihD0exw2fsA">
|
||||
<meta name="google-analytics" content="UA-3769691-2">
|
||||
|
||||
<meta content="collector.githubapp.com" name="octolytics-host" /><meta content="github" name="octolytics-app-id" /><meta content="C0C69725:55E6:90FE12E:57427806" name="octolytics-dimension-request_id" />
|
||||
<meta content="/<user-name>/<repo-name>/blob/show" data-pjax-transient="true" name="analytics-location" />
|
||||
|
||||
|
||||
|
||||
<meta class="js-ga-set" name="dimension1" content="Logged Out">
|
||||
|
||||
|
||||
|
||||
<meta name="hostname" content="github.com">
|
||||
<meta name="user-login" content="">
|
||||
|
||||
<meta name="expected-hostname" content="github.com">
|
||||
<meta name="js-proxy-site-detection-payload" content="OWZlYzg2YjY2MGNkZWMzYWIyMjEyODRmYjUxZDc3NDQ2NmZiMDU4MjIzOTM0YTM0M2QxN2UxMDI5ZThiYmMwZnx7InJlbW90ZV9hZGRyZXNzIjoiMTkyLjE5OC4xNTEuMzciLCJyZXF1ZXN0X2lkIjoiQzBDNjk3MjU6NTVFNjo5MEZFMTJFOjU3NDI3ODA2IiwidGltZXN0YW1wIjoxNDYzOTczODk5fQ==">
|
||||
|
||||
|
||||
<link rel="mask-icon" href="https://assets-cdn.github.com/pinned-octocat.svg" color="#4078c0">
|
||||
<link rel="icon" type="image/x-icon" href="https://assets-cdn.github.com/favicon.ico">
|
||||
|
||||
<meta name="html-safe-nonce" content="d5a3f38662558f7acd81904f7ac14af9db6f4815">
|
||||
<meta content="336822eb21d878aecfe61a4b1500927049b82186" name="form-nonce" />
|
||||
|
||||
<meta http-equiv="x-pjax-version" content="7af64f947f90d1be70195bdfb0943dda">
|
||||
|
||||
|
||||
|
||||
<meta name="description" content="Contribute to ovs_nsh_patches development by creating an account on GitHub.">
|
||||
<meta name="go-import" content="github.com/yyang13/ovs_nsh_patches git https://github.com/yyang13/ovs_nsh_patches.git">
|
||||
|
||||
<meta content="1381010" name="octolytics-dimension-user_id" /><meta content="yyang13" name="octolytics-dimension-user_login" /><meta content="55125011" name="octolytics-dimension-repository_id" /><meta content="yyang13/ovs_nsh_patches" name="octolytics-dimension-repository_nwo" /><meta content="true" name="octolytics-dimension-repository_public" /><meta content="false" name="octolytics-dimension-repository_is_fork" /><meta content="55125011" name="octolytics-dimension-repository_network_root_id" /><meta content="yyang13/ovs_nsh_patches" name="octolytics-dimension-repository_network_root_nwo" />
|
||||
<link href="https://github.com/yyang13/ovs_nsh_patches/commits/master.atom" rel="alternate" title="Recent Commits to ovs_nsh_patches:master" type="application/atom+xml">
|
||||
|
||||
|
||||
<link rel="canonical" href="https://github.com/yyang13/ovs_nsh_patches/blob/master/0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch" data-pjax-transient>
|
||||
</head>
|
||||
|
||||
|
||||
<body class="logged-out env-production vis-public page-blob">
|
||||
<div id="js-pjax-loader-bar" class="pjax-loader-bar"></div>
|
||||
<a href="#start-of-content" tabindex="1" class="accessibility-aid js-skip-to-content">Skip to content</a>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<header class="site-header js-details-container" role="banner">
|
||||
<div class="container-responsive">
|
||||
<a class="header-logo-invertocat" href="https://github.com/" aria-label="Homepage" data-ga-click="(Logged out) Header, go to homepage, icon:logo-wordmark">
|
||||
<svg aria-hidden="true" class="octicon octicon-mark-github" height="32" version="1.1" viewBox="0 0 16 16" width="32"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59 0.4 0.07 0.55-0.17 0.55-0.38 0-0.19-0.01-0.82-0.01-1.49-2.01 0.37-2.53-0.49-2.69-0.94-0.09-0.23-0.48-0.94-0.82-1.13-0.28-0.15-0.68-0.52-0.01-0.53 0.63-0.01 1.08 0.58 1.23 0.82 0.72 1.21 1.87 0.87 2.33 0.66 0.07-0.52 0.28-0.87 0.51-1.07-1.78-0.2-3.64-0.89-3.64-3.95 0-0.87 0.31-1.59 0.82-2.15-0.08-0.2-0.36-1.02 0.08-2.12 0 0 0.67-0.21 2.2 0.82 0.64-0.18 1.32-0.27 2-0.27 0.68 0 1.36 0.09 2 0.27 1.53-1.04 2.2-0.82 2.2-0.82 0.44 1.1 0.16 1.92 0.08 2.12 0.51 0.56 0.82 1.27 0.82 2.15 0 3.07-1.87 3.75-3.65 3.95 0.29 0.25 0.54 0.73 0.54 1.48 0 1.07-0.01 1.93-0.01 2.2 0 0.21 0.15 0.46 0.55 0.38C13.71 14.53 16 11.53 16 8 16 3.58 12.42 0 8 0z"></path></svg>
|
||||
</a>
|
||||
|
||||
<button class="btn-link right site-header-toggle js-details-target" type="button" aria-label="Toggle navigation">
|
||||
<svg aria-hidden="true" class="octicon octicon-three-bars" height="24" version="1.1" viewBox="0 0 12 16" width="18"><path d="M11.41 9H0.59c-0.59 0-0.59-0.41-0.59-1s0-1 0.59-1h10.81c0.59 0 0.59 0.41 0.59 1s0 1-0.59 1z m0-4H0.59c-0.59 0-0.59-0.41-0.59-1s0-1 0.59-1h10.81c0.59 0 0.59 0.41 0.59 1s0 1-0.59 1zM0.59 11h10.81c0.59 0 0.59 0.41 0.59 1s0 1-0.59 1H0.59c-0.59 0-0.59-0.41-0.59-1s0-1 0.59-1z"></path></svg>
|
||||
</button>
|
||||
|
||||
<div class="site-header-menu">
|
||||
<nav class="site-header-nav site-header-nav-main">
|
||||
<a href="/personal" class="js-selected-navigation-item nav-item nav-item-personal" data-ga-click="Header, click, Nav menu - item:personal" data-selected-links="/personal /personal">
|
||||
Personal
|
||||
</a> <a href="/open-source" class="js-selected-navigation-item nav-item nav-item-opensource" data-ga-click="Header, click, Nav menu - item:opensource" data-selected-links="/open-source /open-source">
|
||||
Open source
|
||||
</a> <a href="/business" class="js-selected-navigation-item nav-item nav-item-business" data-ga-click="Header, click, Nav menu - item:business" data-selected-links="/business /business/features /business/customers /business">
|
||||
Business
|
||||
</a> <a href="/explore" class="js-selected-navigation-item nav-item nav-item-explore" data-ga-click="Header, click, Nav menu - item:explore" data-selected-links="/explore /trending /trending/developers /integrations /integrations/feature/code /integrations/feature/collaborate /integrations/feature/ship /explore">
|
||||
Explore
|
||||
</a> </nav>
|
||||
|
||||
<div class="site-header-actions">
|
||||
<a class="btn btn-primary site-header-actions-btn" href="/join?source=header-repo" data-ga-click="(Logged out) Header, clicked Sign up, text:sign-up">Sign up</a>
|
||||
<a class="btn site-header-actions-btn mr-2" href="/login?return_to=%2Fyyang13%2Fovs_nsh_patches%2Fblob%2Fmaster%2F0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch" data-ga-click="(Logged out) Header, clicked Sign in, text:sign-in">Sign in</a>
|
||||
</div>
|
||||
|
||||
<nav class="site-header-nav site-header-nav-secondary">
|
||||
<a class="nav-item" href="/pricing">Pricing</a>
|
||||
<a class="nav-item" href="/blog">Blog</a>
|
||||
<a class="nav-item" href="https://help.github.com">Support</a>
|
||||
<a class="nav-item header-search-link" href="https://github.com/search">Search GitHub</a>
|
||||
<div class="header-search scoped-search site-scoped-search js-site-search" role="search">
|
||||
<!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="/yyang13/ovs_nsh_patches/search" class="js-site-search-form" data-scoped-search-url="/yyang13/ovs_nsh_patches/search" data-unscoped-search-url="/search" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
|
||||
<label class="form-control header-search-wrapper js-chromeless-input-container">
|
||||
<div class="header-search-scope">This repository</div>
|
||||
<input type="text"
|
||||
class="form-control header-search-input js-site-search-focus js-site-search-field is-clearable"
|
||||
data-hotkey="s"
|
||||
name="q"
|
||||
placeholder="Search"
|
||||
aria-label="Search this repository"
|
||||
data-unscoped-placeholder="Search GitHub"
|
||||
data-scoped-placeholder="Search"
|
||||
tabindex="1"
|
||||
autocapitalize="off">
|
||||
</label>
|
||||
</form></div>
|
||||
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
||||
|
||||
<div id="start-of-content" class="accessibility-aid"></div>
|
||||
|
||||
<div id="js-flash-container">
|
||||
</div>
|
||||
|
||||
|
||||
<div role="main" class="main-content">
|
||||
<div itemscope itemtype="http://schema.org/SoftwareSourceCode">
|
||||
<div id="js-repo-pjax-container" data-pjax-container>
|
||||
|
||||
<div class="pagehead repohead instapaper_ignore readability-menu experiment-repo-nav">
|
||||
<div class="container repohead-details-container">
|
||||
|
||||
|
||||
|
||||
<ul class="pagehead-actions">
|
||||
|
||||
<li>
|
||||
<a href="/login?return_to=%2Fyyang13%2Fovs_nsh_patches"
|
||||
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
|
||||
aria-label="You must be signed in to watch a repository" rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-eye" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M8.06 2C3 2 0 8 0 8s3 6 8.06 6c4.94 0 7.94-6 7.94-6S13 2 8.06 2z m-0.06 10c-2.2 0-4-1.78-4-4 0-2.2 1.8-4 4-4 2.22 0 4 1.8 4 4 0 2.22-1.78 4-4 4z m2-4c0 1.11-0.89 2-2 2s-2-0.89-2-2 0.89-2 2-2 2 0.89 2 2z"></path></svg>
|
||||
Watch
|
||||
</a>
|
||||
<a class="social-count" href="/yyang13/ovs_nsh_patches/watchers">
|
||||
3
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/login?return_to=%2Fyyang13%2Fovs_nsh_patches"
|
||||
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
|
||||
aria-label="You must be signed in to star a repository" rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-star" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M14 6l-4.9-0.64L7 1 4.9 5.36 0 6l3.6 3.26L2.67 14l4.33-2.33 4.33 2.33L10.4 9.26 14 6z"></path></svg>
|
||||
Star
|
||||
</a>
|
||||
|
||||
<a class="social-count js-social-count" href="/yyang13/ovs_nsh_patches/stargazers">
|
||||
3
|
||||
</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<a href="/login?return_to=%2Fyyang13%2Fovs_nsh_patches"
|
||||
class="btn btn-sm btn-with-count tooltipped tooltipped-n"
|
||||
aria-label="You must be signed in to fork a repository" rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-repo-forked" height="16" version="1.1" viewBox="0 0 10 16" width="10"><path d="M8 1c-1.11 0-2 0.89-2 2 0 0.73 0.41 1.38 1 1.72v1.28L5 8 3 6v-1.28c0.59-0.34 1-0.98 1-1.72 0-1.11-0.89-2-2-2S0 1.89 0 3c0 0.73 0.41 1.38 1 1.72v1.78l3 3v1.78c-0.59 0.34-1 0.98-1 1.72 0 1.11 0.89 2 2 2s2-0.89 2-2c0-0.73-0.41-1.38-1-1.72V9.5l3-3V4.72c0.59-0.34 1-0.98 1-1.72 0-1.11-0.89-2-2-2zM2 4.2c-0.66 0-1.2-0.55-1.2-1.2s0.55-1.2 1.2-1.2 1.2 0.55 1.2 1.2-0.55 1.2-1.2 1.2z m3 10c-0.66 0-1.2-0.55-1.2-1.2s0.55-1.2 1.2-1.2 1.2 0.55 1.2 1.2-0.55 1.2-1.2 1.2z m3-10c-0.66 0-1.2-0.55-1.2-1.2s0.55-1.2 1.2-1.2 1.2 0.55 1.2 1.2-0.55 1.2-1.2 1.2z"></path></svg>
|
||||
Fork
|
||||
</a>
|
||||
|
||||
<a href="/yyang13/ovs_nsh_patches/network" class="social-count">
|
||||
2
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h1 class="entry-title public ">
|
||||
<svg aria-hidden="true" class="octicon octicon-repo" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M4 9h-1v-1h1v1z m0-3h-1v1h1v-1z m0-2h-1v1h1v-1z m0-2h-1v1h1v-1z m8-1v12c0 0.55-0.45 1-1 1H6v2l-1.5-1.5-1.5 1.5V14H1c-0.55 0-1-0.45-1-1V1C0 0.45 0.45 0 1 0h10c0.55 0 1 0.45 1 1z m-1 10H1v2h2v-1h3v1h5V11z m0-10H2v9h9V1z"></path></svg>
|
||||
<span class="author" itemprop="author"><a href="/yyang13" class="url fn" rel="author">yyang13</a></span><!--
|
||||
--><span class="path-divider">/</span><!--
|
||||
--><strong itemprop="name"><a href="/yyang13/ovs_nsh_patches" data-pjax="#js-repo-pjax-container">ovs_nsh_patches</a></strong>
|
||||
|
||||
</h1>
|
||||
|
||||
</div>
|
||||
<div class="container">
|
||||
|
||||
<nav class="reponav js-repo-nav js-sidenav-container-pjax"
|
||||
itemscope
|
||||
itemtype="http://schema.org/BreadcrumbList"
|
||||
role="navigation"
|
||||
data-pjax="#js-repo-pjax-container">
|
||||
|
||||
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
|
||||
<a href="/yyang13/ovs_nsh_patches" aria-selected="true" class="js-selected-navigation-item selected reponav-item" data-hotkey="g c" data-selected-links="repo_source repo_downloads repo_commits repo_releases repo_tags repo_branches /yyang13/ovs_nsh_patches" itemprop="url">
|
||||
<svg aria-hidden="true" class="octicon octicon-code" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M9.5 3l-1.5 1.5 3.5 3.5L8 11.5l1.5 1.5 4.5-5L9.5 3zM4.5 3L0 8l4.5 5 1.5-1.5L2.5 8l3.5-3.5L4.5 3z"></path></svg>
|
||||
<span itemprop="name">Code</span>
|
||||
<meta itemprop="position" content="1">
|
||||
</a> </span>
|
||||
|
||||
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
|
||||
<a href="/yyang13/ovs_nsh_patches/issues" class="js-selected-navigation-item reponav-item" data-hotkey="g i" data-selected-links="repo_issues repo_labels repo_milestones /yyang13/ovs_nsh_patches/issues" itemprop="url">
|
||||
<svg aria-hidden="true" class="octicon octicon-issue-opened" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M7 2.3c3.14 0 5.7 2.56 5.7 5.7S10.14 13.7 7 13.7 1.3 11.14 1.3 8s2.56-5.7 5.7-5.7m0-1.3C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7S10.86 1 7 1z m1 3H6v5h2V4z m0 6H6v2h2V10z"></path></svg>
|
||||
<span itemprop="name">Issues</span>
|
||||
<span class="counter">1</span>
|
||||
<meta itemprop="position" content="2">
|
||||
</a> </span>
|
||||
|
||||
<span itemscope itemtype="http://schema.org/ListItem" itemprop="itemListElement">
|
||||
<a href="/yyang13/ovs_nsh_patches/pulls" class="js-selected-navigation-item reponav-item" data-hotkey="g p" data-selected-links="repo_pulls /yyang13/ovs_nsh_patches/pulls" itemprop="url">
|
||||
<svg aria-hidden="true" class="octicon octicon-git-pull-request" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M11 11.28c0-1.73 0-6.28 0-6.28-0.03-0.78-0.34-1.47-0.94-2.06s-1.28-0.91-2.06-0.94c0 0-1.02 0-1 0V0L4 3l3 3V4h1c0.27 0.02 0.48 0.11 0.69 0.31s0.3 0.42 0.31 0.69v6.28c-0.59 0.34-1 0.98-1 1.72 0 1.11 0.89 2 2 2s2-0.89 2-2c0-0.73-0.41-1.38-1-1.72z m-1 2.92c-0.66 0-1.2-0.55-1.2-1.2s0.55-1.2 1.2-1.2 1.2 0.55 1.2 1.2-0.55 1.2-1.2 1.2zM4 3c0-1.11-0.89-2-2-2S0 1.89 0 3c0 0.73 0.41 1.38 1 1.72 0 1.55 0 5.56 0 6.56-0.59 0.34-1 0.98-1 1.72 0 1.11 0.89 2 2 2s2-0.89 2-2c0-0.73-0.41-1.38-1-1.72V4.72c0.59-0.34 1-0.98 1-1.72z m-0.8 10c0 0.66-0.55 1.2-1.2 1.2s-1.2-0.55-1.2-1.2 0.55-1.2 1.2-1.2 1.2 0.55 1.2 1.2z m-1.2-8.8c-0.66 0-1.2-0.55-1.2-1.2s0.55-1.2 1.2-1.2 1.2 0.55 1.2 1.2-0.55 1.2-1.2 1.2z"></path></svg>
|
||||
<span itemprop="name">Pull requests</span>
|
||||
<span class="counter">0</span>
|
||||
<meta itemprop="position" content="3">
|
||||
</a> </span>
|
||||
|
||||
|
||||
|
||||
<a href="/yyang13/ovs_nsh_patches/pulse" class="js-selected-navigation-item reponav-item" data-selected-links="pulse /yyang13/ovs_nsh_patches/pulse">
|
||||
<svg aria-hidden="true" class="octicon octicon-pulse" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M11.5 8L8.8 5.4 6.6 8.5 5.5 1.6 2.38 8H0V10h3.6L4.5 8.2l0.9 5.4L9 8.5l1.6 1.5H14V8H11.5z"></path></svg>
|
||||
Pulse
|
||||
</a>
|
||||
<a href="/yyang13/ovs_nsh_patches/graphs" class="js-selected-navigation-item reponav-item" data-selected-links="repo_graphs repo_contributors /yyang13/ovs_nsh_patches/graphs">
|
||||
<svg aria-hidden="true" class="octicon octicon-graph" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M16 14v1H0V0h1v14h15z m-11-1H3V8h2v5z m4 0H7V3h2v10z m4 0H11V6h2v7z"></path></svg>
|
||||
Graphs
|
||||
</a>
|
||||
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container new-discussion-timeline experiment-repo-nav">
|
||||
<div class="repository-content">
|
||||
|
||||
|
||||
|
||||
<a href="/yyang13/ovs_nsh_patches/blob/98e1d3d6b1ed49d902edaede11820853b0ad5037/0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch" class="hidden js-permalink-shortcut" data-hotkey="y">Permalink</a>
|
||||
|
||||
<!-- blob contrib key: blob_contributors:v21:9e16b7492ae4319416c7dc2e26b52f73 -->
|
||||
|
||||
<div class="file-navigation js-zeroclipboard-container">
|
||||
|
||||
<div class="select-menu branch-select-menu js-menu-container js-select-menu left">
|
||||
<button class="btn btn-sm select-menu-button js-menu-target css-truncate" data-hotkey="w"
|
||||
title="master"
|
||||
type="button" aria-label="Switch branches or tags" tabindex="0" aria-haspopup="true">
|
||||
<i>Branch:</i>
|
||||
<span class="js-select-button css-truncate-target">master</span>
|
||||
</button>
|
||||
|
||||
<div class="select-menu-modal-holder js-menu-content js-navigation-container" data-pjax aria-hidden="true">
|
||||
|
||||
<div class="select-menu-modal">
|
||||
<div class="select-menu-header">
|
||||
<svg aria-label="Close" class="octicon octicon-x js-menu-close" height="16" role="img" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48-3.75-3.75-3.75 3.75-1.48-1.48 3.75-3.75L0.77 4.25l1.48-1.48 3.75 3.75 3.75-3.75 1.48 1.48-3.75 3.75z"></path></svg>
|
||||
<span class="select-menu-title">Switch branches/tags</span>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-filters">
|
||||
<div class="select-menu-text-filter">
|
||||
<input type="text" aria-label="Filter branches/tags" id="context-commitish-filter-field" class="form-control js-filterable-field js-navigation-enable" placeholder="Filter branches/tags">
|
||||
</div>
|
||||
<div class="select-menu-tabs">
|
||||
<ul>
|
||||
<li class="select-menu-tab">
|
||||
<a href="#" data-tab-filter="branches" data-filter-placeholder="Filter branches/tags" class="js-select-menu-tab" role="tab">Branches</a>
|
||||
</li>
|
||||
<li class="select-menu-tab">
|
||||
<a href="#" data-tab-filter="tags" data-filter-placeholder="Find a tag…" class="js-select-menu-tab" role="tab">Tags</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="branches" role="menu">
|
||||
|
||||
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
|
||||
|
||||
|
||||
<a class="select-menu-item js-navigation-item js-navigation-open selected"
|
||||
href="/yyang13/ovs_nsh_patches/blob/master/0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch"
|
||||
data-name="master"
|
||||
data-skip-pjax="true"
|
||||
rel="nofollow">
|
||||
<svg aria-hidden="true" class="octicon octicon-check select-menu-item-icon" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M12 5L4 13 0 9l1.5-1.5 2.5 2.5 6.5-6.5 1.5 1.5z"></path></svg>
|
||||
<span class="select-menu-item-text css-truncate-target js-select-menu-filter-text" title="master">
|
||||
master
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-no-results">Nothing to show</div>
|
||||
</div>
|
||||
|
||||
<div class="select-menu-list select-menu-tab-bucket js-select-menu-tab-bucket" data-tab-filter="tags">
|
||||
<div data-filterable-for="context-commitish-filter-field" data-filterable-type="substring">
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="select-menu-no-results">Nothing to show</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="btn-group right">
|
||||
<a href="/yyang13/ovs_nsh_patches/find/master"
|
||||
class="js-pjax-capture-input btn btn-sm"
|
||||
data-pjax
|
||||
data-hotkey="t">
|
||||
Find file
|
||||
</a>
|
||||
<button aria-label="Copy file path to clipboard" class="js-zeroclipboard btn btn-sm zeroclipboard-button tooltipped tooltipped-s" data-copied-hint="Copied!" type="button">Copy path</button>
|
||||
</div>
|
||||
<div class="breadcrumb js-zeroclipboard-target">
|
||||
<span class="repo-root js-repo-root"><span class="js-path-segment"><a href="/yyang13/ovs_nsh_patches"><span>ovs_nsh_patches</span></a></span></span><span class="separator">/</span><strong class="final-path">0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="commit-tease">
|
||||
<span class="right">
|
||||
<a class="commit-tease-sha" href="/yyang13/ovs_nsh_patches/commit/9f8ad552bbfb7f9678f1b6195b2d2c0f34a38352" data-pjax>
|
||||
9f8ad55
|
||||
</a>
|
||||
<relative-time datetime="2016-04-15T07:18:08Z">Apr 15, 2016</relative-time>
|
||||
</span>
|
||||
<div>
|
||||
<img alt="" class="avatar" height="20" src="https://1.gravatar.com/avatar/4dbafb666390db3bde85995883557645?d=https%3A%2F%2Fassets-cdn.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png&r=x&s=140" width="20" />
|
||||
<span class="user-mention">Yi Yang</span>
|
||||
<a href="/yyang13/ovs_nsh_patches/commit/9f8ad552bbfb7f9678f1b6195b2d2c0f34a38352" class="message" data-pjax="true" title="ovs nsh patches
|
||||
|
||||
Signed-off-by: Yi Yang <yi.y.yang@intel.com>">ovs nsh patches</a>
|
||||
</div>
|
||||
|
||||
<div class="commit-tease-contributors">
|
||||
<button type="button" class="btn-link muted-link contributors-toggle" data-facebox="#blob_contributors_box">
|
||||
<strong>0</strong>
|
||||
contributors
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="blob_contributors_box" style="display:none">
|
||||
<h2 class="facebox-header" data-facebox-id="facebox-header">Users who have contributed to this file</h2>
|
||||
<ul class="facebox-user-list" data-facebox-id="facebox-description">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file">
|
||||
<div class="file-header">
|
||||
<div class="file-actions">
|
||||
|
||||
<div class="btn-group">
|
||||
<a href="/yyang13/ovs_nsh_patches/raw/master/0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch" class="btn btn-sm " id="raw-url">Raw</a>
|
||||
<a href="/yyang13/ovs_nsh_patches/blame/master/0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch" class="btn btn-sm js-update-url-with-hash">Blame</a>
|
||||
<a href="/yyang13/ovs_nsh_patches/commits/master/0005-Ethernet-header-must-be-kept-in-VxLAN-gpe-eth-NSH-fo.patch" class="btn btn-sm " rel="nofollow">History</a>
|
||||
</div>
|
||||
|
||||
|
||||
<button type="button" class="btn-octicon disabled tooltipped tooltipped-nw"
|
||||
aria-label="You must be signed in to make or propose changes">
|
||||
<svg aria-hidden="true" class="octicon octicon-pencil" height="16" version="1.1" viewBox="0 0 14 16" width="14"><path d="M0 12v3h3l8-8-3-3L0 12z m3 2H1V12h1v1h1v1z m10.3-9.3l-1.3 1.3-3-3 1.3-1.3c0.39-0.39 1.02-0.39 1.41 0l1.59 1.59c0.39 0.39 0.39 1.02 0 1.41z"></path></svg>
|
||||
</button>
|
||||
<button type="button" class="btn-octicon btn-octicon-danger disabled tooltipped tooltipped-nw"
|
||||
aria-label="You must be signed in to make or propose changes">
|
||||
<svg aria-hidden="true" class="octicon octicon-trashcan" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M10 2H8c0-0.55-0.45-1-1-1H4c-0.55 0-1 0.45-1 1H1c-0.55 0-1 0.45-1 1v1c0 0.55 0.45 1 1 1v9c0 0.55 0.45 1 1 1h7c0.55 0 1-0.45 1-1V5c0.55 0 1-0.45 1-1v-1c0-0.55-0.45-1-1-1z m-1 12H2V5h1v8h1V5h1v8h1V5h1v8h1V5h1v9z m1-10H1v-1h9v1z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="file-info">
|
||||
75 lines (61 sloc)
|
||||
<span class="file-info-divider"></span>
|
||||
2.85 KB
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div itemprop="text" class="blob-wrapper data type-diff">
|
||||
<table class="highlight tab-size js-file-line-container" data-tab-size="8">
|
||||
<tr>
|
||||
<td id="L1" class="blob-num js-line-number" data-line-number="1"></td>
|
||||
<td id="LC1" class="blob-code blob-code-inner js-file-line">From 604bcfaf5211513f665ca05a370bc7f0c0dab39f Mon Sep 17 00:00:00 2001</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L2" class="blob-num js-line-number" data-line-number="2"></td>
|
||||
<td id="LC2" class="blob-code blob-code-inner js-file-line">From: Yi Yang <yi.y.yang@intel.com></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L3" class="blob-num js-line-number" data-line-number="3"></td>
|
||||
<td id="LC3" class="blob-code blob-code-inner js-file-line">Date: Fri, 15 Apr 2016 14:17:54 +0800</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L4" class="blob-num js-line-number" data-line-number="4"></td>
|
||||
<td id="LC4" class="blob-code blob-code-inner js-file-line">Subject: [PATCH 5/5] Ethernet header must be kept in VxLAN-gpe + eth + NSH for</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L5" class="blob-num js-line-number" data-line-number="5"></td>
|
||||
<td id="LC5" class="blob-code blob-code-inner js-file-line"> new ovs lwtunnel implementation</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L6" class="blob-num js-line-number" data-line-number="6"></td>
|
||||
<td id="LC6" class="blob-code blob-code-inner js-file-line">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L7" class="blob-num js-line-number" data-line-number="7"></td>
|
||||
<td id="LC7" class="blob-code blob-code-inner js-file-line">Signed-off-by: Yi Yang <yi.y.yang@intel.com></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L8" class="blob-num js-line-number" data-line-number="8"></td>
|
||||
<td id="LC8" class="blob-code blob-code-inner js-file-line"><span class="pl-ms">---</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L9" class="blob-num js-line-number" data-line-number="9"></td>
|
||||
<td id="LC9" class="blob-code blob-code-inner js-file-line"> datapath/linux/compat/vxlan.c | 16 ++++++++++------</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L10" class="blob-num js-line-number" data-line-number="10"></td>
|
||||
<td id="LC10" class="blob-code blob-code-inner js-file-line"> 1 file changed, 10 insertions(+), 6 deletions(-)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L11" class="blob-num js-line-number" data-line-number="11"></td>
|
||||
<td id="LC11" class="blob-code blob-code-inner js-file-line">
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L12" class="blob-num js-line-number" data-line-number="12"></td>
|
||||
<td id="LC12" class="blob-code blob-code-inner js-file-line"><span class="pl-c1">diff --git a/datapath/linux/compat/vxlan.c b/datapath/linux/compat/vxlan.c</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L13" class="blob-num js-line-number" data-line-number="13"></td>
|
||||
<td id="LC13" class="blob-code blob-code-inner js-file-line">index 888d431..3c05141 100644</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L14" class="blob-num js-line-number" data-line-number="14"></td>
|
||||
<td id="LC14" class="blob-code blob-code-inner js-file-line"><span class="pl-md">--- a/datapath/linux/compat/vxlan.c</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L15" class="blob-num js-line-number" data-line-number="15"></td>
|
||||
<td id="LC15" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+++ b/datapath/linux/compat/vxlan.c</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L16" class="blob-num js-line-number" data-line-number="16"></td>
|
||||
<td id="LC16" class="blob-code blob-code-inner js-file-line"><span class="pl-mdr">@@ -821,7 +821,7 @@</span> static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb,</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L17" class="blob-num js-line-number" data-line-number="17"></td>
|
||||
<td id="LC17" class="blob-code blob-code-inner js-file-line"> struct vxlan_dev *vxlan;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L18" class="blob-num js-line-number" data-line-number="18"></td>
|
||||
<td id="LC18" class="blob-code blob-code-inner js-file-line"> struct pcpu_sw_netstats *stats;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L19" class="blob-num js-line-number" data-line-number="19"></td>
|
||||
<td id="LC19" class="blob-code blob-code-inner js-file-line"> union vxlan_addr saddr;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L20" class="blob-num js-line-number" data-line-number="20"></td>
|
||||
<td id="LC20" class="blob-code blob-code-inner js-file-line"><span class="pl-md">- struct eth_nsh_hdr *eth_nsh_header = NULL;</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L21" class="blob-num js-line-number" data-line-number="21"></td>
|
||||
<td id="LC21" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ //struct eth_nsh_hdr *eth_nsh_header = NULL;</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L22" class="blob-num js-line-number" data-line-number="22"></td>
|
||||
<td id="LC22" class="blob-code blob-code-inner js-file-line"> int err = 0;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L23" class="blob-num js-line-number" data-line-number="23"></td>
|
||||
<td id="LC23" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L24" class="blob-num js-line-number" data-line-number="24"></td>
|
||||
<td id="LC24" class="blob-code blob-code-inner js-file-line"> /* For flow based devices, map all packets to VNI 0 */</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L25" class="blob-num js-line-number" data-line-number="25"></td>
|
||||
<td id="LC25" class="blob-code blob-code-inner js-file-line"><span class="pl-mdr">@@ -891,12 +891,13 @@</span> static void vxlan_rcv(struct vxlan_sock *vs, struct sk_buff *skb,</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L26" class="blob-num js-line-number" data-line-number="26"></td>
|
||||
<td id="LC26" class="blob-code blob-code-inner js-file-line"> u64_stats_update_end(&stats->syncp);</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L27" class="blob-num js-line-number" data-line-number="27"></td>
|
||||
<td id="LC27" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L28" class="blob-num js-line-number" data-line-number="28"></td>
|
||||
<td id="LC28" class="blob-code blob-code-inner js-file-line"> /* Add a faked encap_eth_header for NSH */</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L29" class="blob-num js-line-number" data-line-number="29"></td>
|
||||
<td id="LC29" class="blob-code blob-code-inner js-file-line"><span class="pl-md">- if (md && ((md->gpe & VXLAN_GPE_NP_MASK) == VXLAN_GPE_NP_NSH)) {</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L30" class="blob-num js-line-number" data-line-number="30"></td>
|
||||
<td id="LC30" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ /* ovs changes have ensured it is here, so needn't add it any more */</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L31" class="blob-num js-line-number" data-line-number="31"></td>
|
||||
<td id="LC31" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ /*if (md && ((md->gpe & VXLAN_GPE_NP_MASK) == VXLAN_GPE_NP_NSH)) {</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L32" class="blob-num js-line-number" data-line-number="32"></td>
|
||||
<td id="LC32" class="blob-code blob-code-inner js-file-line"> skb_push(skb, ENCAP_ETH_LEN);</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L33" class="blob-num js-line-number" data-line-number="33"></td>
|
||||
<td id="LC33" class="blob-code blob-code-inner js-file-line"> eth_nsh_header = (struct eth_nsh_hdr *)skb->data;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L34" class="blob-num js-line-number" data-line-number="34"></td>
|
||||
<td id="LC34" class="blob-code blob-code-inner js-file-line"> memmove(eth_nsh_header->encap_eth_header.encap_eth_dst, skb_mac_header(skb), ENCAP_ETH_LEN);</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L35" class="blob-num js-line-number" data-line-number="35"></td>
|
||||
<td id="LC35" class="blob-code blob-code-inner js-file-line"> eth_nsh_header->encap_eth_header.encap_eth_type = htons(ETH_P_NSH);</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L36" class="blob-num js-line-number" data-line-number="36"></td>
|
||||
<td id="LC36" class="blob-code blob-code-inner js-file-line"><span class="pl-md">- }</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L37" class="blob-num js-line-number" data-line-number="37"></td>
|
||||
<td id="LC37" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ }*/</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L38" class="blob-num js-line-number" data-line-number="38"></td>
|
||||
<td id="LC38" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L39" class="blob-num js-line-number" data-line-number="39"></td>
|
||||
<td id="LC39" class="blob-code blob-code-inner js-file-line"> netdev_port_receive(skb, skb_tunnel_info(skb));</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L40" class="blob-num js-line-number" data-line-number="40"></td>
|
||||
<td id="LC40" class="blob-code blob-code-inner js-file-line"> return;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L41" class="blob-num js-line-number" data-line-number="41"></td>
|
||||
<td id="LC41" class="blob-code blob-code-inner js-file-line"><span class="pl-mdr">@@ -985,7 +986,7 @@</span> static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L42" class="blob-num js-line-number" data-line-number="42"></td>
|
||||
<td id="LC42" class="blob-code blob-code-inner js-file-line"> struct vxlanhdr_gpe *gpe;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L43" class="blob-num js-line-number" data-line-number="43"></td>
|
||||
<td id="LC43" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L44" class="blob-num js-line-number" data-line-number="44"></td>
|
||||
<td id="LC44" class="blob-code blob-code-inner js-file-line"> gpe = (struct vxlanhdr_gpe *)vxh;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L45" class="blob-num js-line-number" data-line-number="45"></td>
|
||||
<td id="LC45" class="blob-code blob-code-inner js-file-line"><span class="pl-md">- md->gpe = ntohs(gpe->next_proto);</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L46" class="blob-num js-line-number" data-line-number="46"></td>
|
||||
<td id="LC46" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ md->gpe = gpe->next_proto;</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L47" class="blob-num js-line-number" data-line-number="47"></td>
|
||||
<td id="LC47" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L48" class="blob-num js-line-number" data-line-number="48"></td>
|
||||
<td id="LC48" class="blob-code blob-code-inner js-file-line"> buf.dst.u.tun_info.key.tun_flags |= TUNNEL_VXLAN_OPT;</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L49" class="blob-num js-line-number" data-line-number="49"></td>
|
||||
<td id="LC49" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L50" class="blob-num js-line-number" data-line-number="50"></td>
|
||||
<td id="LC50" class="blob-code blob-code-inner js-file-line"><span class="pl-mdr">@@ -1189,9 +1190,10 @@</span> static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L51" class="blob-num js-line-number" data-line-number="51"></td>
|
||||
<td id="LC51" class="blob-code blob-code-inner js-file-line"> }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L52" class="blob-num js-line-number" data-line-number="52"></td>
|
||||
<td id="LC52" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L53" class="blob-num js-line-number" data-line-number="53"></td>
|
||||
<td id="LC53" class="blob-code blob-code-inner js-file-line"> /* Skip encap_eth_header on sending Eth+NSH to vxlan-gpe port */</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L54" class="blob-num js-line-number" data-line-number="54"></td>
|
||||
<td id="LC54" class="blob-code blob-code-inner js-file-line"><span class="pl-md">- if (md && ((md->gpe & VXLAN_GPE_NP_MASK) == VXLAN_GPE_NP_NSH)) {</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L55" class="blob-num js-line-number" data-line-number="55"></td>
|
||||
<td id="LC55" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ /* ovs needs to keep eth header here */</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L56" class="blob-num js-line-number" data-line-number="56"></td>
|
||||
<td id="LC56" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ /*if (md && ((md->gpe & VXLAN_GPE_NP_MASK) == VXLAN_GPE_NP_NSH)) {</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L57" class="blob-num js-line-number" data-line-number="57"></td>
|
||||
<td id="LC57" class="blob-code blob-code-inner js-file-line"> skb_pull(skb, ENCAP_ETH_LEN);</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L58" class="blob-num js-line-number" data-line-number="58"></td>
|
||||
<td id="LC58" class="blob-code blob-code-inner js-file-line"><span class="pl-md">- }</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L59" class="blob-num js-line-number" data-line-number="59"></td>
|
||||
<td id="LC59" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ }*/</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L60" class="blob-num js-line-number" data-line-number="60"></td>
|
||||
<td id="LC60" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L61" class="blob-num js-line-number" data-line-number="61"></td>
|
||||
<td id="LC61" class="blob-code blob-code-inner js-file-line"> min_headroom = LL_RESERVED_SPACE(rt->dst.dev) + rt->dst.header_len</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L62" class="blob-num js-line-number" data-line-number="62"></td>
|
||||
<td id="LC62" class="blob-code blob-code-inner js-file-line"> + VXLAN_HLEN + sizeof(struct iphdr)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L63" class="blob-num js-line-number" data-line-number="63"></td>
|
||||
<td id="LC63" class="blob-code blob-code-inner js-file-line"><span class="pl-mdr">@@ -1236,6 +1238,8 @@</span> static int vxlan_xmit_skb(struct rtable *rt, struct sock *sk, struct sk_buff *sk</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L64" class="blob-num js-line-number" data-line-number="64"></td>
|
||||
<td id="LC64" class="blob-code blob-code-inner js-file-line"> }</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L65" class="blob-num js-line-number" data-line-number="65"></td>
|
||||
<td id="LC65" class="blob-code blob-code-inner js-file-line"> if (vxflags & VXLAN_F_GBP)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L66" class="blob-num js-line-number" data-line-number="66"></td>
|
||||
<td id="LC66" class="blob-code blob-code-inner js-file-line"> vxlan_build_gbp_hdr(vxh, vxflags, md);</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L67" class="blob-num js-line-number" data-line-number="67"></td>
|
||||
<td id="LC67" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ else if (vxflags & VXLAN_F_GPE)</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L68" class="blob-num js-line-number" data-line-number="68"></td>
|
||||
<td id="LC68" class="blob-code blob-code-inner js-file-line"><span class="pl-mi1">+ vxlan_build_gpe_hdr(vxh, vxflags, md);</span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L69" class="blob-num js-line-number" data-line-number="69"></td>
|
||||
<td id="LC69" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L70" class="blob-num js-line-number" data-line-number="70"></td>
|
||||
<td id="LC70" class="blob-code blob-code-inner js-file-line"> ovs_skb_set_inner_protocol(skb, htons(ETH_P_TEB));</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L71" class="blob-num js-line-number" data-line-number="71"></td>
|
||||
<td id="LC71" class="blob-code blob-code-inner js-file-line"> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L72" class="blob-num js-line-number" data-line-number="72"></td>
|
||||
<td id="LC72" class="blob-code blob-code-inner js-file-line"><span class="pl-md">-- </span></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L73" class="blob-num js-line-number" data-line-number="73"></td>
|
||||
<td id="LC73" class="blob-code blob-code-inner js-file-line">1.9.3</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td id="L74" class="blob-num js-line-number" data-line-number="74"></td>
|
||||
<td id="LC74" class="blob-code blob-code-inner js-file-line">
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<button type="button" data-facebox="#jump-to-line" data-facebox-class="linejump" data-hotkey="l" class="hidden">Jump to Line</button>
|
||||
<div id="jump-to-line" style="display:none">
|
||||
<!-- </textarea> --><!-- '"` --><form accept-charset="UTF-8" action="" class="js-jump-to-line-form" method="get"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div>
|
||||
<input class="form-control linejump-input js-jump-to-line-field" type="text" placeholder="Jump to line…" aria-label="Jump to line" autofocus>
|
||||
<button type="submit" class="btn">Go</button>
|
||||
</form></div>
|
||||
|
||||
</div>
|
||||
<div class="modal-backdrop"></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="container site-footer-container">
|
||||
<div class="site-footer" role="contentinfo">
|
||||
<ul class="site-footer-links right">
|
||||
<li><a href="https://status.github.com/" data-ga-click="Footer, go to status, text:status">Status</a></li>
|
||||
<li><a href="https://developer.github.com" data-ga-click="Footer, go to api, text:api">API</a></li>
|
||||
<li><a href="https://training.github.com" data-ga-click="Footer, go to training, text:training">Training</a></li>
|
||||
<li><a href="https://shop.github.com" data-ga-click="Footer, go to shop, text:shop">Shop</a></li>
|
||||
<li><a href="https://github.com/blog" data-ga-click="Footer, go to blog, text:blog">Blog</a></li>
|
||||
<li><a href="https://github.com/about" data-ga-click="Footer, go to about, text:about">About</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<a href="https://github.com" aria-label="Homepage" class="site-footer-mark" title="GitHub">
|
||||
<svg aria-hidden="true" class="octicon octicon-mark-github" height="24" version="1.1" viewBox="0 0 16 16" width="24"><path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59 0.4 0.07 0.55-0.17 0.55-0.38 0-0.19-0.01-0.82-0.01-1.49-2.01 0.37-2.53-0.49-2.69-0.94-0.09-0.23-0.48-0.94-0.82-1.13-0.28-0.15-0.68-0.52-0.01-0.53 0.63-0.01 1.08 0.58 1.23 0.82 0.72 1.21 1.87 0.87 2.33 0.66 0.07-0.52 0.28-0.87 0.51-1.07-1.78-0.2-3.64-0.89-3.64-3.95 0-0.87 0.31-1.59 0.82-2.15-0.08-0.2-0.36-1.02 0.08-2.12 0 0 0.67-0.21 2.2 0.82 0.64-0.18 1.32-0.27 2-0.27 0.68 0 1.36 0.09 2 0.27 1.53-1.04 2.2-0.82 2.2-0.82 0.44 1.1 0.16 1.92 0.08 2.12 0.51 0.56 0.82 1.27 0.82 2.15 0 3.07-1.87 3.75-3.65 3.95 0.29 0.25 0.54 0.73 0.54 1.48 0 1.07-0.01 1.93-0.01 2.2 0 0.21 0.15 0.46 0.55 0.38C13.71 14.53 16 11.53 16 8 16 3.58 12.42 0 8 0z"></path></svg>
|
||||
</a>
|
||||
<ul class="site-footer-links">
|
||||
<li>© 2016 <span title="0.04211s from github-fe139-cp1-prd.iad.github.net">GitHub</span>, Inc.</li>
|
||||
<li><a href="https://github.com/site/terms" data-ga-click="Footer, go to terms, text:terms">Terms</a></li>
|
||||
<li><a href="https://github.com/site/privacy" data-ga-click="Footer, go to privacy, text:privacy">Privacy</a></li>
|
||||
<li><a href="https://github.com/security" data-ga-click="Footer, go to security, text:security">Security</a></li>
|
||||
<li><a href="https://github.com/contact" data-ga-click="Footer, go to contact, text:contact">Contact</a></li>
|
||||
<li><a href="https://help.github.com" data-ga-click="Footer, go to help, text:help">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="ajax-error-message" class="ajax-error-message flash flash-error">
|
||||
<svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M15.72 12.5l-6.85-11.98C8.69 0.21 8.36 0.02 8 0.02s-0.69 0.19-0.87 0.5l-6.85 11.98c-0.18 0.31-0.18 0.69 0 1C0.47 13.81 0.8 14 1.15 14h13.7c0.36 0 0.69-0.19 0.86-0.5S15.89 12.81 15.72 12.5zM9 12H7V10h2V12zM9 9H7V5h2V9z"></path></svg>
|
||||
<button type="button" class="flash-close js-flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
|
||||
<svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48-3.75-3.75-3.75 3.75-1.48-1.48 3.75-3.75L0.77 4.25l1.48-1.48 3.75 3.75 3.75-3.75 1.48 1.48-3.75 3.75z"></path></svg>
|
||||
</button>
|
||||
Something went wrong with that request. Please try again.
|
||||
</div>
|
||||
|
||||
|
||||
<script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/compat-7db58f8b7b91111107fac755dd8b178fe7db0f209ced51fc339c446ad3f8da2b.js"></script>
|
||||
<script crossorigin="anonymous" src="https://assets-cdn.github.com/assets/frameworks-b0aaa1e644508a5d5c3f7509d91f5f950c180e1d933a999f21747c5ec5411d92.js"></script>
|
||||
<script async="async" crossorigin="anonymous" src="https://assets-cdn.github.com/assets/github-7c9ed6fd84382ad236d74c9ec5853f75fca061537cb1914241807b12c289216e.js"></script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="js-stale-session-flash stale-session-flash flash flash-warn flash-banner hidden">
|
||||
<svg aria-hidden="true" class="octicon octicon-alert" height="16" version="1.1" viewBox="0 0 16 16" width="16"><path d="M15.72 12.5l-6.85-11.98C8.69 0.21 8.36 0.02 8 0.02s-0.69 0.19-0.87 0.5l-6.85 11.98c-0.18 0.31-0.18 0.69 0 1C0.47 13.81 0.8 14 1.15 14h13.7c0.36 0 0.69-0.19 0.86-0.5S15.89 12.81 15.72 12.5zM9 12H7V10h2V12zM9 9H7V5h2V9z"></path></svg>
|
||||
<span class="signed-in-tab-flash">You signed in with another tab or window. <a href="">Reload</a> to refresh your session.</span>
|
||||
<span class="signed-out-tab-flash">You signed out in another tab or window. <a href="">Reload</a> to refresh your session.</span>
|
||||
</div>
|
||||
<div class="facebox" id="facebox" style="display:none;">
|
||||
<div class="facebox-popup">
|
||||
<div class="facebox-content" role="dialog" aria-labelledby="facebox-header" aria-describedby="facebox-description">
|
||||
</div>
|
||||
<button type="button" class="facebox-close js-facebox-close" aria-label="Close modal">
|
||||
<svg aria-hidden="true" class="octicon octicon-x" height="16" version="1.1" viewBox="0 0 12 16" width="12"><path d="M7.48 8l3.75 3.75-1.48 1.48-3.75-3.75-3.75 3.75-1.48-1.48 3.75-3.75L0.77 4.25l1.48-1.48 3.75 3.75 3.75-3.75 1.48 1.48-3.75 3.75z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,788 +0,0 @@
|
|||
at data plane level in user space and modify the related codes at control plane
|
||||
level in user space.
|
||||
|
||||
The design is based on basic VxLAN impletation. When packets are received at
|
||||
data plane level in user space, function 'dp_netdev_input' will be called for
|
||||
processing the packets at data plane level in user space.
|
||||
|
||||
When VXLAN-GPE NSH packets are received, decapsulation will be implemented. For
|
||||
the first time, the packets are sent to control plane by function 'upcall_cb',
|
||||
and tunnel port will be lookuped by matching the UDP port which is 4790 for
|
||||
VxLAN-GPE NSH port, if VxLAN-GPE NSH tunnel port are matched
|
||||
successfully, the tunnel pop action will be appended and implemented at data
|
||||
plane level, and the NSH related field will be parsed, then packets will be
|
||||
reprocessed by function 'dp_netdev_input'.
|
||||
|
||||
When original packets are sent to VxLAN-GPE NSH port, the encapsulation will
|
||||
be implemented. For the first time, in the control plane the tunnel
|
||||
tunnel_push_data are built according to VxLAN-GPE NSH port configuration and
|
||||
related rules, then the tunnel push actions are appended and implemented at
|
||||
data plane level. Finally packets will be reprocessed by function
|
||||
'dp_netdev_input'.
|
||||
|
||||
Signed-off-by: Ricky Li <<A HREF="http://openvswitch.org/mailman/listinfo/dev">ricky.li at intel.com</A>>
|
||||
Signed-off-by: Mengke Liu <<A HREF="http://openvswitch.org/mailman/listinfo/dev">mengke.liu at intel.com</A>>
|
||||
---
|
||||
lib/netdev-vport.c | 166 +++++++++++++++++++++++++++++++++++-----
|
||||
lib/odp-util.c | 175 ++++++++++++++++++++++++++++++-------------
|
||||
lib/packets.h | 115 +++++++++++++++++++++++++++-
|
||||
ofproto/ofproto-dpif-xlate.c | 1 -
|
||||
tests/tunnel.at | 118 +++++++++++++++++++++++++++++
|
||||
5 files changed, 500 insertions(+), 75 deletions(-)
|
||||
|
||||
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
|
||||
index 3f85386..a0a4da2 100644
|
||||
--- a/lib/netdev-vport.c
|
||||
+++ b/lib/netdev-vport.c
|
||||
@@ -67,6 +67,12 @@ static struct vlog_rate_limit err_rl = VLOG_RATE_LIMIT_INIT(60, 5);
|
||||
sizeof(struct udp_header) + \
|
||||
sizeof(struct genevehdr))
|
||||
|
||||
+#define VXNSH_HLEN (sizeof(struct eth_header) + \
|
||||
+ sizeof(struct ip_header) + \
|
||||
+ sizeof(struct udp_header) + \
|
||||
+ sizeof(struct vxgpehdr) + \
|
||||
+ sizeof(struct nshhdr))
|
||||
+
|
||||
#define DEFAULT_TTL 64
|
||||
|
||||
struct netdev_vport {
|
||||
@@ -1462,29 +1468,69 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
|
||||
{
|
||||
struct pkt_metadata *md = &packet->md;
|
||||
struct flow_tnl *tnl = &md->tunnel;
|
||||
- struct vxlanhdr *vxh;
|
||||
+ struct udp_header *udp;
|
||||
|
||||
pkt_metadata_init_tnl(md);
|
||||
if (VXLAN_HLEN > dp_packet_size(packet)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
- vxh = udp_extract_tnl_md(packet, tnl);
|
||||
- if (!vxh) {
|
||||
- return EINVAL;
|
||||
+ udp = ip_extract_tnl_md(packet, tnl);
|
||||
+ if (!udp) {
|
||||
+ return EINVAL;;
|
||||
}
|
||||
|
||||
- if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
|
||||
- (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
|
||||
- VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
|
||||
- ntohl(get_16aligned_be32(&vxh->vx_flags)),
|
||||
- ntohl(get_16aligned_be32(&vxh->vx_vni)));
|
||||
- return EINVAL;
|
||||
- }
|
||||
- tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
|
||||
- tnl->flags |= FLOW_TNL_F_KEY;
|
||||
+ if (ntohs(udp->udp_dst) == VXGPE_DST_PORT) {
|
||||
+
|
||||
+ struct vxgpehdr *vxg = (struct vxgpehdr *) (udp + 1);
|
||||
+
|
||||
+ if (get_16aligned_be32(&vxg->vx_vni) & htonl(0xff)) {
|
||||
+ VLOG_WARN_RL(&err_rl, "invalid vxlan-gpe vni=%#x\n",
|
||||
+ ntohl(get_16aligned_be32(&vxg->vx_vni)));
|
||||
+ return EINVAL;;
|
||||
+ }
|
||||
+
|
||||
+ tnl->tp_src = udp->udp_src;
|
||||
+ tnl->tp_dst = udp->udp_dst;
|
||||
+ tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxg->vx_vni)) >> 8);
|
||||
+
|
||||
+ if (vxg->p == 0x01 && vxg->proto == VXG_P_NSH) {
|
||||
+ struct nshhdr *nsh = (struct nshhdr *) (vxg + 1);
|
||||
+
|
||||
+ tnl->nsp = nsh->b.b2 << 8;
|
||||
+ tnl->nsi = nsh->b.svc_idx;
|
||||
+ tnl->nshc1 = nsh->c.nshc1;
|
||||
+ tnl->nshc2 = nsh->c.nshc2;
|
||||
+ tnl->nshc3 = nsh->c.nshc3;
|
||||
+ tnl->nshc4 = nsh->c.nshc4;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSP;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSI;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSH_C1 | FLOW_TNL_F_NSH_C2 | \
|
||||
+ FLOW_TNL_F_NSH_C3 | FLOW_TNL_F_NSH_C4;
|
||||
+
|
||||
+ dp_packet_reset_packet(packet, VXNSH_HLEN);
|
||||
+ } else {
|
||||
+ VLOG_WARN("Unsupported vxlan GPE + NSH format!");
|
||||
+ return EINVAL;;
|
||||
+ }
|
||||
+
|
||||
+ } else {
|
||||
+
|
||||
+ struct vxlanhdr *vxh = (struct vxlanhdr *) (udp + 1);
|
||||
|
||||
- dp_packet_reset_packet(packet, VXLAN_HLEN);
|
||||
+ if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
|
||||
+ (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
|
||||
+ VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_flags)),
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_vni)));
|
||||
+ return EINVAL;;
|
||||
+ }
|
||||
+
|
||||
+ tnl->tp_src = udp->udp_src;
|
||||
+ tnl->tp_dst = udp->udp_dst;
|
||||
+ tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
|
||||
+ dp_packet_reset_packet(packet, VXLAN_HLEN);
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1496,23 +1542,103 @@ netdev_vxlan_build_header(const struct netdev *netdev,
|
||||
{
|
||||
struct netdev_vport *dev = netdev_vport_cast(netdev);
|
||||
struct netdev_tunnel_config *tnl_cfg;
|
||||
- struct vxlanhdr *vxh;
|
||||
+ struct ip_header *ip;
|
||||
+ struct udp_header *udp;
|
||||
+ bool isnsh = false;
|
||||
|
||||
/* XXX: RCUfy tnl_cfg. */
|
||||
ovs_mutex_lock(&dev->mutex);
|
||||
tnl_cfg = &dev->tnl_cfg;
|
||||
|
||||
- vxh = udp_build_header(tnl_cfg, tnl_flow, data);
|
||||
+ ip = ip_hdr(data->header);
|
||||
+ ip->ip_proto = IPPROTO_UDP;
|
||||
+
|
||||
+ udp = (struct udp_header *) (ip + 1);
|
||||
+ udp->udp_dst = tnl_cfg->dst_port;
|
||||
+
|
||||
+ if (tnl_flow->tunnel.flags & FLOW_TNL_F_CSUM) {
|
||||
+ /* Write a value in now to mark that we should compute the checksum
|
||||
+ * later. 0xffff is handy because it is transparent to the
|
||||
+ * calculation. */
|
||||
+ udp->udp_csum = htons(0xffff);
|
||||
+ }
|
||||
+
|
||||
+ if (ntohs(udp->udp_dst) == VXGPE_DST_PORT){
|
||||
+ struct vxgpehdr *vxg = (struct vxgpehdr *) (udp + 1);
|
||||
|
||||
- put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
|
||||
- put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
|
||||
+ memset(vxg, 0, sizeof *vxg);
|
||||
+ vxg->i = 0x01;
|
||||
+ vxg->p = 0x01;
|
||||
+ vxg->ver = 0x01;
|
||||
+ vxg->proto = VXG_P_NSH;
|
||||
+ put_16aligned_be32(&vxg->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
|
||||
+
|
||||
+ if (vxg->p && vxg->proto == VXG_P_NSH){
|
||||
+ struct nshhdr *nsh = (struct nshhdr *) (vxg + 1);
|
||||
+
|
||||
+ memset(nsh, 0, sizeof *nsh);
|
||||
+ nsh->b.ver = 0x01;
|
||||
+ nsh->b.len = 6;
|
||||
+ nsh->b.mdtype = NSH_M_TYPE1;
|
||||
+ nsh->b.proto = NSH_P_ETHERNET;
|
||||
+
|
||||
+ nsh->b.b2 = tnl_flow->tunnel.nsp >> 8;
|
||||
+ nsh->b.svc_idx = tnl_flow->tunnel.nsi;
|
||||
+
|
||||
+ nsh->c.nshc1 = tnl_flow->tunnel.nshc1;
|
||||
+ nsh->c.nshc2 = tnl_flow->tunnel.nshc2;
|
||||
+ nsh->c.nshc3 = tnl_flow->tunnel.nshc3;
|
||||
+ nsh->c.nshc4 = tnl_flow->tunnel.nshc4;
|
||||
+
|
||||
+ isnsh = true;
|
||||
+ }
|
||||
+
|
||||
+ } else {
|
||||
+ struct vxlanhdr *vxh = (struct vxlanhdr *) (udp + 1);
|
||||
+ put_16aligned_be32(&vxh->vx_flags, htonl(VXLAN_FLAGS));
|
||||
+ put_16aligned_be32(&vxh->vx_vni, htonl(ntohll(tnl_flow->tunnel.tun_id) << 8));
|
||||
+ }
|
||||
|
||||
ovs_mutex_unlock(&dev->mutex);
|
||||
- data->header_len = VXLAN_HLEN;
|
||||
+
|
||||
+ if(isnsh)
|
||||
+ data->header_len = VXNSH_HLEN;
|
||||
+ else
|
||||
+ data->header_len = VXLAN_HLEN;
|
||||
data->tnl_type = OVS_VPORT_TYPE_VXLAN;
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void
|
||||
+netdev_vxlan_push_header(struct dp_packet *packet,
|
||||
+ const struct ovs_action_push_tnl *data)
|
||||
+{
|
||||
+ int ip_tot_size;
|
||||
+ int size = data->header_len;
|
||||
+ const void *header = data->header;
|
||||
+ struct udp_header *udp;
|
||||
+
|
||||
+ udp = push_ip_header(packet, header, size, &ip_tot_size);
|
||||
+
|
||||
+ /* set udp src port */
|
||||
+ udp->udp_src = get_src_port(packet);
|
||||
+ udp->udp_len = htons(ip_tot_size - sizeof (struct ip_header));
|
||||
+ /* udp_csum is zero */
|
||||
+
|
||||
+ if (udp->udp_csum) {
|
||||
+ uint32_t csum = packet_csum_pseudoheader(ip_hdr(dp_packet_data(packet)));
|
||||
+
|
||||
+ csum = csum_continue(csum, udp,
|
||||
+ ip_tot_size - sizeof (struct ip_header));
|
||||
+ udp->udp_csum = csum_finish(csum);
|
||||
+
|
||||
+ if (!udp->udp_csum) {
|
||||
+ udp->udp_csum = htons(0xffff);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int
|
||||
netdev_geneve_pop_header(struct dp_packet *packet)
|
||||
{
|
||||
@@ -1736,7 +1862,7 @@ netdev_vport_tunnel_register(void)
|
||||
netdev_gre_pop_header),
|
||||
TUNNEL_CLASS("ipsec_gre", "gre_sys", NULL, NULL, NULL),
|
||||
TUNNEL_CLASS("vxlan", "vxlan_sys", netdev_vxlan_build_header,
|
||||
- push_udp_header,
|
||||
+ netdev_vxlan_push_header,
|
||||
netdev_vxlan_pop_header),
|
||||
TUNNEL_CLASS("lisp", "lisp_sys", NULL, NULL, NULL),
|
||||
TUNNEL_CLASS("stt", "stt_sys", NULL, NULL, NULL),
|
||||
diff --git a/lib/odp-util.c b/lib/odp-util.c
|
||||
index e8bc86d..1696f77 100644
|
||||
--- a/lib/odp-util.c
|
||||
+++ b/lib/odp-util.c
|
||||
@@ -468,12 +468,42 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
|
||||
|
||||
if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) {
|
||||
const struct vxlanhdr *vxh;
|
||||
-
|
||||
- vxh = format_udp_tnl_push_header(ds, ip);
|
||||
-
|
||||
- ds_put_format(ds, "vxlan(flags=0x%"PRIx32",vni=0x%"PRIx32")",
|
||||
- ntohl(get_16aligned_be32(&vxh->vx_flags)),
|
||||
- ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
|
||||
+ const struct udp_header *udp;
|
||||
+ const struct vxgpehdr *vxg;
|
||||
+
|
||||
+ /* UDP */
|
||||
+ udp = (const struct udp_header *) (ip + 1);
|
||||
+ ds_put_format(ds, "udp(src=%"PRIu16",dst=%"PRIu16",csum=0x%"PRIx16"),",
|
||||
+ ntohs(udp->udp_src), ntohs(udp->udp_dst),
|
||||
+ ntohs(udp->udp_csum));
|
||||
+
|
||||
+ /* VxLan & VxLan GPE(UDP port: 4790) */
|
||||
+ if (ntohs(udp->udp_dst) == 4790) {
|
||||
+ vxg = (const struct vxgpehdr *) (udp + 1);
|
||||
+
|
||||
+ ds_put_format(ds, "vxlangpe(vni=0x%"PRIx32",",
|
||||
+ ntohl(get_16aligned_be32(&vxg->vx_vni)));
|
||||
+ ds_put_format(ds, "proto=%"PRIu8"),", vxg->proto);
|
||||
+ if (vxg->p == 0x01 && vxg->proto == VXG_P_NSH) {
|
||||
+ const struct nshhdr *nsh = (struct nshhdr *) (vxg + 1);
|
||||
+
|
||||
+ /* NSH */
|
||||
+ ds_put_format(ds, "nsh(mdtype=%"PRIu8",proto=%"PRIu8",",
|
||||
+ nsh->b.mdtype, nsh->b.proto);
|
||||
+ ds_put_format(ds, "nsp=%"PRIx32",nsi=%"PRIu8",",
|
||||
+ nsh->b.b2 & 0x00FFFFFF, nsh->b.svc_idx);
|
||||
+ ds_put_format(ds, "nshc1=%"PRIx32",nshc2=%"PRIx32",",
|
||||
+ ntohl(nsh->c.nshc1), ntohl(nsh->c.nshc2));
|
||||
+ ds_put_format(ds, "nshc3=%"PRIx32",nshc4=%"PRIx32",",
|
||||
+ ntohl(nsh->c.nshc3), ntohl(nsh->c.nshc4));
|
||||
+ ds_put_format(ds, ")");
|
||||
+ }
|
||||
+ } else {
|
||||
+ vxh = (const struct vxlanhdr *) (udp + 1);
|
||||
+ ds_put_format(ds, "vxlan(flags=0x%"PRIx32",vni=0x%"PRIx32")",
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_flags)),
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_vni))>>8);
|
||||
+ }
|
||||
} else if (data->tnl_type == OVS_VPORT_TYPE_GENEVE) {
|
||||
const struct genevehdr *gnh;
|
||||
|
||||
@@ -490,8 +520,8 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
|
||||
ds, false);
|
||||
ds_put_char(ds, ')');
|
||||
}
|
||||
-
|
||||
ds_put_char(ds, ')');
|
||||
+
|
||||
} else if (data->tnl_type == OVS_VPORT_TYPE_GRE) {
|
||||
const struct gre_base_hdr *greh;
|
||||
ovs_16aligned_be32 *options;
|
||||
@@ -504,7 +534,7 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
|
||||
ntohs(greh->flags), ntohs(greh->protocol));
|
||||
options = (ovs_16aligned_be32 *)(greh + 1);
|
||||
if (greh->flags & htons(GRE_CSUM)) {
|
||||
- ds_put_format(ds, ",csum=0x%"PRIx16, ntohs(*((ovs_be16 *)options)));
|
||||
+ ds_put_format(ds, ",csum=0x%"PRIx32, ntohl(get_16aligned_be32(options)));
|
||||
options++;
|
||||
}
|
||||
if (greh->flags & htons(GRE_KEY)) {
|
||||
@@ -791,8 +821,10 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data)
|
||||
struct ip_header *ip;
|
||||
struct udp_header *udp;
|
||||
struct gre_base_hdr *greh;
|
||||
+ struct nshhdr *nsh;
|
||||
uint16_t gre_proto, gre_flags, dl_type, udp_src, udp_dst, csum;
|
||||
- ovs_be32 sip, dip;
|
||||
+ ovs_be32 sip, dip, nsp, nshc1,nshc2,nshc3,nshc4;
|
||||
+ uint8_t nsi;
|
||||
uint32_t tnl_type = 0, header_len = 0;
|
||||
void *l3, *l4;
|
||||
int n = 0;
|
||||
@@ -837,71 +869,108 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data)
|
||||
udp = (struct udp_header *) l4;
|
||||
greh = (struct gre_base_hdr *) l4;
|
||||
if (ovs_scan_len(s, &n, "udp(src=%"SCNi16",dst=%"SCNi16",csum=0x%"SCNx16"),",
|
||||
- &udp_src, &udp_dst, &csum)) {
|
||||
- uint32_t vx_flags, vni;
|
||||
+ &udp_src, &udp_dst, &csum)) {
|
||||
+ struct vxlanhdr *vxh;
|
||||
+ struct vxgpehdr *vxg;
|
||||
+ uint32_t vx_flags, vx_vni;
|
||||
+ uint32_t geneve_vni;
|
||||
|
||||
udp->udp_src = htons(udp_src);
|
||||
udp->udp_dst = htons(udp_dst);
|
||||
udp->udp_len = 0;
|
||||
udp->udp_csum = htons(csum);
|
||||
|
||||
+ vxh = (struct vxlanhdr *) (udp + 1);
|
||||
+ vxg = (struct vxgpehdr *) (udp + 1);
|
||||
+
|
||||
if (ovs_scan_len(s, &n, "vxlan(flags=0x%"SCNx32",vni=0x%"SCNx32"))",
|
||||
- &vx_flags, &vni)) {
|
||||
- struct vxlanhdr *vxh = (struct vxlanhdr *) (udp + 1);
|
||||
+ &vx_flags, &vx_vni)) {
|
||||
+ tnl_type = OVS_VPORT_TYPE_VXLAN;
|
||||
|
||||
put_16aligned_be32(&vxh->vx_flags, htonl(vx_flags));
|
||||
- put_16aligned_be32(&vxh->vx_vni, htonl(vni << 8));
|
||||
- tnl_type = OVS_VPORT_TYPE_VXLAN;
|
||||
+ put_16aligned_be32(&vxh->vx_vni, htonl(vx_vni<<8));
|
||||
+
|
||||
header_len = sizeof *eth + sizeof *ip +
|
||||
sizeof *udp + sizeof *vxh;
|
||||
- } else if (ovs_scan_len(s, &n, "geneve(")) {
|
||||
- struct genevehdr *gnh = (struct genevehdr *) (udp + 1);
|
||||
|
||||
- memset(gnh, 0, sizeof *gnh);
|
||||
- header_len = sizeof *eth + sizeof *ip +
|
||||
- sizeof *udp + sizeof *gnh;
|
||||
+ } else if (ovs_scan_len(s, &n, "vxlangpe(vni=0x%"SCNx32",proto="SCNi8"),",
|
||||
+ &vx_vni, &vxg->proto)) {
|
||||
+ struct nshhdr *nsh = (struct nshhdr *) (vxg + 1);
|
||||
|
||||
- if (ovs_scan_len(s, &n, "oam,")) {
|
||||
- gnh->oam = 1;
|
||||
- }
|
||||
- if (ovs_scan_len(s, &n, "crit,")) {
|
||||
- gnh->critical = 1;
|
||||
- }
|
||||
- if (!ovs_scan_len(s, &n, "vni=%"SCNi32, &vni)) {
|
||||
+ tnl_type = OVS_VPORT_TYPE_VXLAN;
|
||||
+ vxg->i = 0x01;
|
||||
+ vxg->p = 0x01;
|
||||
+ vxg->ver = 0x01;
|
||||
+ put_16aligned_be32(&vxg->vx_vni, htonl(vx_vni));
|
||||
+
|
||||
+ if (ovs_scan_len(s, &n, "nsh(mdtype=%"SCNi8",proto=%"SCNi8",nsp=0x%"SCNx32
|
||||
+ ",nsi=%"SCNi8",nshc1=0x%"SCNx32",nshc2=0x%"SCNx32
|
||||
+ ",nshc3=0x%"SCNx32",nshc4=0x%"SCNx32"))",
|
||||
+ &nsh->b.mdtype, &nsh->b.proto,
|
||||
+ &nsp, &nsi,
|
||||
+ &nshc1, &nshc2,
|
||||
+ &nshc3, &nshc4)) {
|
||||
+ nsh->b.ver = 0x01;
|
||||
+ nsh->b.len = 6;
|
||||
+ nsh->b.b2 = nsp;
|
||||
+ nsh->b.svc_idx = nsi;
|
||||
+ nsh->c.nshc1=nshc1;
|
||||
+ nsh->c.nshc2=nshc2;
|
||||
+ nsh->c.nshc3=nshc3;
|
||||
+ nsh->c.nshc4=nshc4;
|
||||
+ header_len = sizeof *eth + sizeof *ip +
|
||||
+ sizeof *udp + sizeof *vxh + sizeof *nsh;
|
||||
+ } else {
|
||||
return -EINVAL;
|
||||
}
|
||||
- if (ovs_scan_len(s, &n, ",options(")) {
|
||||
- struct geneve_scan options;
|
||||
- int len;
|
||||
-
|
||||
- memset(&options, 0, sizeof options);
|
||||
- len = scan_geneve(s + n, &options, NULL);
|
||||
- if (!len) {
|
||||
- return -EINVAL;
|
||||
- }
|
||||
+ } else if (ovs_scan_len(s, &n, "geneve(")) {
|
||||
+ struct genevehdr *gnh = (struct genevehdr *) (udp + 1);
|
||||
|
||||
- memcpy(gnh->options, options.d, options.len);
|
||||
- gnh->opt_len = options.len / 4;
|
||||
- header_len += options.len;
|
||||
+ memset(gnh, 0, sizeof *gnh);
|
||||
+ header_len = sizeof *eth + sizeof *ip +
|
||||
+ sizeof *udp + sizeof *gnh;
|
||||
|
||||
- n += len;
|
||||
- }
|
||||
- if (!ovs_scan_len(s, &n, "))")) {
|
||||
+ if (ovs_scan_len(s, &n, "oam,")) {
|
||||
+ gnh->oam = 1;
|
||||
+ }
|
||||
+ if (ovs_scan_len(s, &n, "crit,")) {
|
||||
+ gnh->critical = 1;
|
||||
+ }
|
||||
+ if (!ovs_scan_len(s, &n, "vni=%"SCNi32, &geneve_vni)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (ovs_scan_len(s, &n, ",options(")) {
|
||||
+ struct geneve_scan options;
|
||||
+ int len;
|
||||
+
|
||||
+ memset(&options, 0, sizeof options);
|
||||
+ len = scan_geneve(s + n, &options, NULL);
|
||||
+ if (!len) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- gnh->proto_type = htons(ETH_TYPE_TEB);
|
||||
- put_16aligned_be32(&gnh->vni, htonl(vni << 8));
|
||||
- tnl_type = OVS_VPORT_TYPE_GENEVE;
|
||||
- } else {
|
||||
+ memcpy(gnh->options, options.d, options.len);
|
||||
+ gnh->opt_len = options.len / 4;
|
||||
+ header_len += options.len;
|
||||
+
|
||||
+ n += len;
|
||||
+ }
|
||||
+ if (!ovs_scan_len(s, &n, "))")) {
|
||||
return -EINVAL;
|
||||
}
|
||||
- } else if (ovs_scan_len(s, &n, "gre((flags=0x%"SCNx16",proto=0x%"SCNx16")",
|
||||
- &gre_flags, &gre_proto)){
|
||||
|
||||
- tnl_type = OVS_VPORT_TYPE_GRE;
|
||||
- greh->flags = htons(gre_flags);
|
||||
- greh->protocol = htons(gre_proto);
|
||||
+ gnh->proto_type = htons(ETH_TYPE_TEB);
|
||||
+ put_16aligned_be32(&gnh->vni, htonl(geneve_vni << 8));
|
||||
+ tnl_type = OVS_VPORT_TYPE_GENEVE;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+} else if (ovs_scan_len(s, &n, "gre((flags=0x%"SCNx16",proto=0x%"SCNx16")",
|
||||
+ &gre_flags, &gre_proto)){
|
||||
+
|
||||
+ tnl_type = OVS_VPORT_TYPE_GRE;
|
||||
+ greh->flags = htons(gre_flags);
|
||||
+ greh->protocol = htons(gre_proto);
|
||||
ovs_16aligned_be32 *options = (ovs_16aligned_be32 *) (greh + 1);
|
||||
|
||||
if (greh->flags & htons(GRE_CSUM)) {
|
||||
@@ -941,7 +1010,7 @@ ovs_parse_tnl_push(const char *s, struct ovs_action_push_tnl *data)
|
||||
((uint8_t *) options - (uint8_t *) greh);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
- }
|
||||
+ }
|
||||
|
||||
/* check tunnel meta data. */
|
||||
if (data->tnl_type != tnl_type) {
|
||||
@@ -1120,6 +1189,7 @@ parse_odp_action(const char *s, const struct simap *port_names,
|
||||
struct ovs_action_push_tnl data;
|
||||
int n;
|
||||
|
||||
+ memset(&data, 0, sizeof data);
|
||||
n = ovs_parse_tnl_push(s, &data);
|
||||
if (n > 0) {
|
||||
odp_put_tnl_push_action(actions, &data);
|
||||
@@ -3285,7 +3355,6 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names,
|
||||
SCAN_FIELD_NESTED_FUNC("flags(", uint16_t, tun_flags, tun_flags_to_attr);
|
||||
} SCAN_END_NESTED();
|
||||
|
||||
-
|
||||
SCAN_SINGLE_PORT("in_port(", uint32_t, OVS_KEY_ATTR_IN_PORT);
|
||||
|
||||
SCAN_BEGIN("eth(", struct ovs_key_ethernet) {
|
||||
diff --git a/lib/packets.h b/lib/packets.h
|
||||
index 12f2239..7f9ab98 100644
|
||||
--- a/lib/packets.h
|
||||
+++ b/lib/packets.h
|
||||
@@ -33,7 +33,6 @@
|
||||
struct dp_packet;
|
||||
struct ds;
|
||||
|
||||
-/* Tunnel information used in flow key and metadata. */
|
||||
struct flow_tnl {
|
||||
ovs_be32 ip_dst;
|
||||
ovs_be32 ip_src;
|
||||
@@ -913,6 +912,120 @@ struct vxlanhdr {
|
||||
/* VXLAN GPE UDP DST PORT */
|
||||
#define VXGPE_DST_PORT 4790
|
||||
|
||||
+/**
|
||||
+ * struct vxlan_gpehdr - Generic Protocol Extension for VXLAN header.
|
||||
+ * @p: Next Protocol field indicator bit
|
||||
+ * @o: Operations and Management Packet indicator bit.
|
||||
+ * @proto: IEEE Ethertypes to indicate the frame within.
|
||||
+ * @vni: VXLAN Network Identifier.
|
||||
+ */
|
||||
+struct vxgpehdr {
|
||||
+#ifdef WORDS_BIGENDIAN
|
||||
+ uint8_t res1:4;
|
||||
+ uint8_t i:1;
|
||||
+ uint8_t p:1;
|
||||
+ uint8_t res2:1;
|
||||
+ uint8_t o:1;
|
||||
+
|
||||
+ uint8_t ver:2;
|
||||
+ uint8_t res3:6;
|
||||
+#else
|
||||
+ uint8_t o:1;
|
||||
+ uint8_t res2:1;
|
||||
+ uint8_t p:1;
|
||||
+ uint8_t i:1;
|
||||
+ uint8_t res1:4;
|
||||
+
|
||||
+ uint8_t res3:6;
|
||||
+ uint8_t ver:2;
|
||||
+#endif
|
||||
+ uint8_t res4;
|
||||
+ uint8_t proto;
|
||||
+ ovs_16aligned_be32 vx_vni;
|
||||
+};
|
||||
+
|
||||
+/* VxLAN-GPE Header Next Protocol */
|
||||
+#define VXG_P_IPV4 0x01
|
||||
+#define VXG_P_IPV6 0x02
|
||||
+#define VXG_P_ETHERNET 0x03
|
||||
+#define VXG_P_NSH 0x04
|
||||
+
|
||||
+/**
|
||||
+ * struct nsh_bhdr - Network Service Base Header.
|
||||
+ * @o: Operations and Management Packet indicator bit
|
||||
+ * @c: If this bit is set then one or more contexts are in use.
|
||||
+ * @proto: IEEE Ethertypes to indicate the frame within.
|
||||
+ * @svc_idx: TTL functionality and location within service path.
|
||||
+ * @svc_path: To uniquely identify service path.
|
||||
+ */
|
||||
+struct nsh_base {
|
||||
+#ifdef WORDS_BIGENDIAN
|
||||
+ uint8_t ver:2;
|
||||
+ uint8_t o:1;
|
||||
+ uint8_t c:1;
|
||||
+ uint8_t res1:4;
|
||||
+
|
||||
+ uint8_t res2:2;
|
||||
+ uint8_t len:6;
|
||||
+#else
|
||||
+ uint8_t res1:4;
|
||||
+ uint8_t c:1;
|
||||
+ uint8_t o:1;
|
||||
+ uint8_t ver:2;
|
||||
+
|
||||
+ uint8_t len:6;
|
||||
+ uint8_t res2:2;
|
||||
+#endif
|
||||
+ uint8_t mdtype;
|
||||
+ uint8_t proto;
|
||||
+ union {
|
||||
+ struct {
|
||||
+ uint8_t svc_path[3];
|
||||
+ uint8_t svc_idx;
|
||||
+ };
|
||||
+ ovs_be32 b2;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct nsh_ctx - Keeps track of NSH context data
|
||||
+ * @npc: NSH network platform context
|
||||
+ * @nsc: NSH network shared context
|
||||
+ * @spc: NSH service platform context
|
||||
+ * @ssc: NSH service shared context
|
||||
+ */
|
||||
+struct nsh_ctx {
|
||||
+ ovs_be32 nshc1;
|
||||
+ ovs_be32 nshc2;
|
||||
+ ovs_be32 nshc3;
|
||||
+ ovs_be32 nshc4;
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * struct nshdr - Network Service header
|
||||
+ * @nsh_base: Network Service Base Header.
|
||||
+ * @nsh_ctx: Network Service Context Header.
|
||||
+ */
|
||||
+struct nshhdr {
|
||||
+ struct nsh_base b;
|
||||
+ struct nsh_ctx c;
|
||||
+};
|
||||
+
|
||||
+/* NSH Base Header Next Protocol */
|
||||
+#define NSH_P_IPV4 0x01
|
||||
+#define NSH_P_IPV6 0x02
|
||||
+#define NSH_P_ETHERNET 0x03
|
||||
+
|
||||
+/* MD Type Registry */
|
||||
+#define NSH_M_TYPE1 0x01
|
||||
+#define NSH_M_TYPE2 0x02
|
||||
+#define NSH_M_EXP1 0xFE
|
||||
+#define NSH_M_EXP2 0xFF
|
||||
+
|
||||
+/* Used for masking nsp and nsi values in field nsp below */
|
||||
+#define NSH_M_NSP 0xFFFFFF00 //uncertain
|
||||
+#define NSH_M_NSI 0x000000FF
|
||||
+
|
||||
#define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */
|
||||
|
||||
void format_ipv6_addr(char *addr_str, const struct in6_addr *addr);
|
||||
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
|
||||
index 4bb9801..9c64c24 100644
|
||||
--- a/ofproto/ofproto-dpif-xlate.c
|
||||
+++ b/ofproto/ofproto-dpif-xlate.c
|
||||
@@ -4780,7 +4780,6 @@ xlate_actions(struct xlate_in *xin, struct xlate_out *xout)
|
||||
if (!xbridge) {
|
||||
return;
|
||||
}
|
||||
-
|
||||
struct flow *flow = &xin->flow;
|
||||
|
||||
union mf_subvalue stack_stub[1024 / sizeof(union mf_subvalue)];
|
||||
diff --git a/tests/tunnel.at b/tests/tunnel.at
|
||||
index f43a07d..5ec5e6c 100644
|
||||
--- a/tests/tunnel.at
|
||||
+++ b/tests/tunnel.at
|
||||
@@ -527,6 +527,124 @@ AT_CHECK([tail -1 stdout], [0],
|
||||
OVS_VSWITCHD_STOP(["/receive tunnel port not found/d"])
|
||||
AT_CLEANUP
|
||||
|
||||
+AT_SETUP([tunnel - VXLAN-GPE NSH user space])
|
||||
+OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan \
|
||||
+ options:remote_ip=1.1.1.1 ofport_request=1 options:dst_port=4790])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
|
||||
+ br0 65534/100: (dummy)
|
||||
+ p1 1/4790: (vxlan: dst_port=4790, remote_ip=1.1.1.1)
|
||||
+])
|
||||
+OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
+AT_SETUP([tunnel VXLAN-GPE NSH - encap - nsh/nsi/nshc user space])
|
||||
+OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=1 \
|
||||
+ -- add-port br0 p2 -- set Interface p2 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=flow options:dst_port=4790 ofport_request=2 \
|
||||
+ -- add-port br0 p3 -- set Interface p3 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=2.2.2.2 options:dst_port=4790 options:nsp=111 options:nsi=11 options:nshc1=11 options:nshc2=12 options:nshc3=13 options:nshc4=14 ofport_request=3 \
|
||||
+ -- add-port br0 p4 -- set Interface p4 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=3.3.3.3 options:dst_port=4790 options:nsp=222 options:nsi=22 options:nshc1=flow options:nshc2=flow options:nshc3=flow options:nshc4=flow ofport_request=4 \
|
||||
+ -- add-port br0 p5 -- set Interface p5 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=4.4.4.4 options:dst_port=4790 options:nsp=flow options:nsi=flow options:nshc1=flow options:nshc2=flow options:nshc3=flow options:nshc4=flow ofport_request=5 \
|
||||
+ -- add-port br0 p6 -- set Interface p6 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=flow options:dst_port=4790 options:nsp=flow options:nsi=flow options:nshc1=flow options:nshc2=flow options:nshc3=flow options:nshc4=flow ofport_request=6])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 2.2.2.22/24], [0], [OK
|
||||
+])
|
||||
+AT_CHECK([ovs-vsctl add-port br0 p7 -- set Interface p7 type=dummy ofport_request=7])
|
||||
+AT_CHECK([ovs-vsctl add-port br0 p8 -- set Interface p8 type=dummy ofport_request=8])
|
||||
+
|
||||
+AT_CHECK([
|
||||
+ovs-appctl ovs/route/add 1.1.1.1/24 br0
|
||||
+ovs-appctl tnl/arp/set br0 1.1.1.1 68:05:ca:30:6b:d1
|
||||
+ovs-appctl ovs/route/add 2.2.2.2/24 br0
|
||||
+ovs-appctl tnl/arp/set br0 2.2.2.2 68:05:ca:30:6b:d2
|
||||
+ovs-appctl ovs/route/add 3.3.3.3/24 br0
|
||||
+ovs-appctl tnl/arp/set br0 3.3.3.3 68:05:ca:30:6b:d3
|
||||
+ovs-appctl ovs/route/add 4.4.4.4/24 br0
|
||||
+ovs-appctl tnl/arp/set br0 4.4.4.4 68:05:ca:30:6b:d4
|
||||
+ovs-appctl ovs/route/add 5.5.5.5/24 br0
|
||||
+ovs-appctl tnl/arp/set br0 5.5.5.5 68:05:ca:30:6b:d5
|
||||
+],[0],[stdout])
|
||||
+
|
||||
+AT_DATA([flows.txt], [dnl
|
||||
+in_port=7 actions=resubmit:1,resubmit:2,resubmit:3
|
||||
+in_port=1 actions=output:1
|
||||
+in_port=2 actions=set_field:3.3.3.3->tun_dst,output:2
|
||||
+in_port=3 actions=output:3
|
||||
+])
|
||||
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(7),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no), icmp(type=8,code=0)'], [0], [stdout])
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_push(tnl_port(4790),header(size=74,type=4,eth(dst=68:05:ca:30:6b:d1,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=1.1.1.1,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlangpe(vni=0x0,proto=4),nsh(mdtype=1,proto=3,nsp=0,nsi=1,nshc1=0,nshc2=0,nshc3=0,nshc4=0,)),out_port(100)),tnl_push(tnl_port(4790),header(size=74,type=4,eth(dst=68:05:ca:30:6b:d3,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=3.3.3.3,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlangpe(vni=0x0,proto=4),nsh(mdtype=1,proto=3,nsp=0,nsi=1,nshc1=0,nshc2=0,nshc3=0,nshc4=0,)),out_port(100)),tnl_push(tnl_port(4790),header(size=74,type=4,eth(dst=68:05:ca:30:6b:d2,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=2.2.2.2,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlangpe(vni=0x0,proto=4),nsh(mdtype=1,proto=3,nsp=6f0000,nsi=11,nshc1=b,nshc2=c,nshc3=d,nshc4=e,)),out_port(100))
|
||||
+])
|
||||
+
|
||||
+AT_DATA([flows.txt], [dnl
|
||||
+in_port=8 actions=resubmit:4,resubmit:5,resubmit:6
|
||||
+in_port=4 actions=set_nshc1:22,set_nshc2:23,set_nshc3:24,set_nshc4:25,output:4
|
||||
+in_port=5 actions=set_nsp:333,set_nsi:33,set_nshc1:33,set_nshc2:34,set_nshc3:35,set_nshc4:36,output:5
|
||||
+in_port=6 actions=set_field:5.5.5.5->tun_dst,set_nsp:444,set_nsi:44,set_nshc1:44,set_nshc2:45,set_nshc3:46,set_nshc4:47,output:6
|
||||
+])
|
||||
+AT_CHECK([ovs-ofctl add-flows br0 flows.txt])
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(8),eth(src=50:54:00:00:00:05,dst=50:54:00:00:00:07),eth_type(0x0800),ipv4(src=192.168.0.1,dst=192.168.0.2,proto=1,tos=0,ttl=128,frag=no), icmp(type=8,code=0)'], [0], [stdout])
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_push(tnl_port(4790),header(size=74,type=4,eth(dst=68:05:ca:30:6b:d3,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=3.3.3.3,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlangpe(vni=0x0,proto=4),nsh(mdtype=1,proto=3,nsp=de0000,nsi=22,nshc1=16,nshc2=17,nshc3=18,nshc4=19,)),out_port(100)),tnl_push(tnl_port(4790),header(size=74,type=4,eth(dst=68:05:ca:30:6b:d4,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=4.4.4.4,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlangpe(vni=0x0,proto=4),nsh(mdtype=1,proto=3,nsp=4d0100,nsi=33,nshc1=21,nshc2=22,nshc3=23,nshc4=24,)),out_port(100)),tnl_push(tnl_port(4790),header(size=74,type=4,eth(dst=68:05:ca:30:6b:d5,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=5.5.5.5,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlangpe(vni=0x0,proto=4),nsh(mdtype=1,proto=3,nsp=bc0100,nsi=44,nshc1=2c,nshc2=2d,nshc3=2e,nshc4=2f,)),out_port(100))
|
||||
+])
|
||||
+OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
+AT_SETUP([tunnel VXLAN-GPE NSH - decap - nsh/nsi/nshc user space])
|
||||
+OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
|
||||
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
|
||||
+AT_CHECK([ovs-vsctl add-port int-br p1 -- set Interface p1 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=1.1.1.1 options:dst_port=4790 options:nsp=111 options:nsi=11 options:nshc1=11 options:nshc2=12 options:nshc3=13 options:nshc4=14 ofport_request=2 \
|
||||
+ -- add-port int-br p2 -- set Interface p2 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=2.2.2.2 options:dst_port=4790 options:nsp=flow options:nsi=flow options:nshc1=flow options:nshc2=flow options:nshc3=flow options:nshc4=flow ofport_request=3 \
|
||||
+ -- add-port int-br p3 -- set Interface p3 type=vxlan options:key=flow \
|
||||
+ options:remote_ip=flow options:dst_port=4790 options:nsp=flow options:nsi=flow options:nshc1=flow options:nshc2=flow options:nshc3=flow options:nshc4=flow ofport_request=4], [0])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 2.2.2.22/24], [0], [OK
|
||||
+])
|
||||
+AT_CHECK([ovs-appctl ovs/route/add 1.1.1.1/24 br0], [0], [OK
|
||||
+])
|
||||
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
|
||||
+ br0 65534/100: (dummy)
|
||||
+ p0 1/1: (dummy)
|
||||
+ int-br:
|
||||
+ int-br 65534/2: (dummy)
|
||||
+ p1 2/4790: (vxlan: dst_port=4790, key=flow, nshc1=0xb, nshc2=0xc, nshc3=0xd, nshc4=0xe, nsi=11, nsp=0x6f, remote_ip=1.1.1.1)
|
||||
+ p2 3/4790: (vxlan: dst_port=4790, key=flow, nshc1=flow, nshc2=flow, nshc3=flow, nshc4=flow, nsi=flow, nsp=flow, remote_ip=2.2.2.2)
|
||||
+ p3 4/4790: (vxlan: dst_port=4790, key=flow, nshc1=flow, nshc2=flow, nshc3=flow, nshc4=flow, nsi=flow, nsp=flow, remote_ip=flow)
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
|
||||
+Listening ports:
|
||||
+vxlan_sys_4790 (4790)
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.1.1,dst=2.2.2.22,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4790)'], [0], [stdout])
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_pop(4790)
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=2.2.2.2,dst=2.2.2.22,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4790)'], [0], [stdout])
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_pop(4790)
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=50:54:00:00:00:05,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=3.4.5.6,dst=2.2.2.22,proto=17,tos=0,ttl=64,frag=no),udp(src=51283,dst=4790)'], [0], [stdout])
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_pop(4790)
|
||||
+])
|
||||
+
|
||||
+OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
AT_SETUP([tunnel - Geneve metadata])
|
||||
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \
|
||||
options:remote_ip=1.1.1.1 ofport_request=1 \
|
||||
--
|
||||
1.9.3
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,730 +0,0 @@
|
|||
Ethernet-NSH packet.
|
||||
|
||||
With this feature(options:nsh-convert=true),when VxLAN-GPE NSH packets (Outer
|
||||
MAC header + Outer IP header + UDP header + VxLAN-GPE + NSH + original packet)
|
||||
are received by VxLAN-GPE NSH port, the vport will remove Outer MAC header,
|
||||
Outer IP header, UDP header, VxLAN-GPE header, and then modify and push the
|
||||
outer MAC header. Then the packet with VxLAN-GPE+NSH format is converted to
|
||||
Outer MAC header + NSH header + original packet.
|
||||
|
||||
Signed-off-by: Ricky Li <<A HREF="http://openvswitch.org/mailman/listinfo/dev">ricky.li at intel.com</A>>
|
||||
Signed-off-by: Mengke Liu <<A HREF="http://openvswitch.org/mailman/listinfo/dev">mengke.liu at intel.com</A>>
|
||||
---
|
||||
datapath/linux/compat/include/linux/openvswitch.h | 6 +-
|
||||
lib/netdev-vport.c | 109 +++++++++++++++++++++-
|
||||
lib/netdev.h | 6 ++
|
||||
lib/odp-util.c | 80 ++++++++++++++--
|
||||
lib/ovs-router.c | 64 +++++++++++++
|
||||
lib/ovs-router.h | 1 +
|
||||
lib/packets.h | 13 ++-
|
||||
ofproto/ofproto-dpif-xlate.c | 64 ++++++++++++-
|
||||
ofproto/tunnel.c | 37 ++++++++
|
||||
ofproto/tunnel.h | 5 +
|
||||
tests/tunnel.at | 32 +++++++
|
||||
11 files changed, 398 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
|
||||
index b8ac152..3d588bb 100644
|
||||
--- a/datapath/linux/compat/include/linux/openvswitch.h
|
||||
+++ b/datapath/linux/compat/include/linux/openvswitch.h
|
||||
@@ -230,6 +230,7 @@ enum ovs_vport_type {
|
||||
OVS_VPORT_TYPE_GENEVE, /* Geneve tunnel. */
|
||||
OVS_VPORT_TYPE_LISP = 105, /* LISP tunnel */
|
||||
OVS_VPORT_TYPE_STT = 106, /* STT tunnel */
|
||||
+ OVS_VPORT_TYPE_NSH, /* L2+NSH ENCAP tunnel. */
|
||||
__OVS_VPORT_TYPE_MAX
|
||||
};
|
||||
|
||||
@@ -646,7 +647,10 @@ struct ovs_action_push_tnl {
|
||||
uint8_t header[TNL_PUSH_HEADER_SIZE];
|
||||
};
|
||||
|
||||
-#define OVS_POP_SPEC_ACTION_NO_DECAP 2
|
||||
+enum ovs_pop_spec_action_type {
|
||||
+ OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH,
|
||||
+ OVS_POP_SPEC_ACTION_NO_DECAP = 2,
|
||||
+};
|
||||
|
||||
/*
|
||||
* struct ovs_action_pop_tnl - %OVS_ACTION_ATTR_TUNNEL_POP_SPEC
|
||||
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
|
||||
index d926c00..6e0d5ba 100644
|
||||
--- a/lib/netdev-vport.c
|
||||
+++ b/lib/netdev-vport.c
|
||||
@@ -561,6 +561,23 @@ set_tunnel_config(struct netdev *dev_, const struct smap *args)
|
||||
} else {
|
||||
tnl_cfg.ip_dst = in_addr.s_addr;
|
||||
}
|
||||
+ } else if (!strcmp(node->key, "remote_mac")) {
|
||||
+ if (!strcmp(node->value, "flow")) {
|
||||
+ tnl_cfg.eth_dst_flow = true;
|
||||
+ VLOG_ERR("remote_mac doesn't support setting by flow");
|
||||
+ return EINVAL;
|
||||
+ } else if (eth_addr_from_string(node->value,&tnl_cfg.eth_dst)){
|
||||
+ tnl_cfg.eth_dst_present = true;
|
||||
+ } else {
|
||||
+ VLOG_WARN("%s: bad %s 'remote_mac'", name, type);
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+ } else if (!strcmp(node->key, "nsh_convert")) {
|
||||
+ if (!strcmp(node->value, "true")) {
|
||||
+ tnl_cfg.nsh_convert = true;
|
||||
+ } else {
|
||||
+ tnl_cfg.nsh_convert = false;
|
||||
+ }
|
||||
} else if (!strcmp(node->key, "tun_nodecap")) {
|
||||
if (!strcmp(node->value, "true")) {
|
||||
tnl_cfg.tun_nodecap = true;
|
||||
@@ -883,6 +900,13 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
|
||||
if (!tnl_cfg.dont_fragment) {
|
||||
smap_add(args, "df_default", "false");
|
||||
}
|
||||
+ if (tnl_cfg.eth_dst_present) {
|
||||
+ smap_add_format(args, "remote_mac", ETH_ADDR_FMT, ETH_ADDR_ARGS(tnl_cfg.eth_dst));
|
||||
+ }
|
||||
+
|
||||
+ if (tnl_cfg.nsh_convert) {
|
||||
+ smap_add(args, "nsh_convert", "true");
|
||||
+ }
|
||||
|
||||
if (tnl_cfg.tun_nodecap) {
|
||||
smap_add(args, "tun_nodecap", "true");
|
||||
@@ -1546,6 +1570,84 @@ netdev_vxlan_pop_header(struct dp_packet *packet)
|
||||
}
|
||||
|
||||
static int
|
||||
+vxlan_extract_md_convert_to_eth_nsh(struct dp_packet *packet, const struct ovs_action_pop_tnl *data)
|
||||
+{
|
||||
+ struct pkt_metadata *md = &packet->md;
|
||||
+ struct flow_tnl *tnl = &md->tunnel;
|
||||
+ struct udp_header *udp;
|
||||
+
|
||||
+ memset(md, 0, sizeof *md);
|
||||
+ if (VXLAN_HLEN > dp_packet_size(packet)) {
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ udp = ip_extract_tnl_md(packet, tnl);
|
||||
+ if (!udp) {
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (ntohs(udp->udp_dst) == VXGPE_DST_PORT) {
|
||||
+
|
||||
+ struct vxgpehdr *vxg = (struct vxgpehdr *) (udp + 1);
|
||||
+
|
||||
+ if (get_16aligned_be32(&vxg->vx_vni) & htonl(0xff)) {
|
||||
+ VLOG_WARN_RL(&err_rl, "invalid vxlan-gpe vni=%#x\n",
|
||||
+ ntohl(get_16aligned_be32(&vxg->vx_vni)));
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ tnl->tp_src = udp->udp_src;
|
||||
+ tnl->tp_dst = udp->udp_dst;
|
||||
+ tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxg->vx_vni)) >> 8);
|
||||
+
|
||||
+ if (vxg->p == 0x01 && vxg->proto == VXG_P_NSH) {
|
||||
+ struct nshhdr *nsh = (struct nshhdr *) (vxg + 1);
|
||||
+ struct eth_header *eth = NULL;
|
||||
+
|
||||
+ tnl->nsp = nsh->b.b2 << 8;
|
||||
+ tnl->nsi = nsh->b.svc_idx;
|
||||
+ tnl->nshc1 = nsh->c.nshc1;
|
||||
+ tnl->nshc2 = nsh->c.nshc2;
|
||||
+ tnl->nshc3 = nsh->c.nshc3;
|
||||
+ tnl->nshc4 = nsh->c.nshc4;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSP;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSI;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSH_C1 | FLOW_TNL_F_NSH_C2 | \
|
||||
+ FLOW_TNL_F_NSH_C3 | FLOW_TNL_F_NSH_C4;
|
||||
+ tnl->nsh_flags = NSH_TNL_F_ETHERNET;
|
||||
+
|
||||
+ dp_packet_reset_packet(packet, VXNSH_HLEN - sizeof (struct nshhdr));
|
||||
+ eth = (struct eth_header *) dp_packet_push_uninit(packet, data->header_len);
|
||||
+ memcpy(eth, data->header, data->header_len);
|
||||
+ eth->eth_type = htons(ETH_TYPE_NSH);
|
||||
+ } else {
|
||||
+ VLOG_WARN("Unsupported vxlan GPE + NSH format!");
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ } else {
|
||||
+
|
||||
+ struct vxlanhdr *vxh = (struct vxlanhdr *) (udp + 1);
|
||||
+
|
||||
+ if (get_16aligned_be32(&vxh->vx_flags) != htonl(VXLAN_FLAGS) ||
|
||||
+ (get_16aligned_be32(&vxh->vx_vni) & htonl(0xff))) {
|
||||
+ VLOG_WARN_RL(&err_rl, "invalid vxlan flags=%#x vni=%#x\n",
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_flags)),
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_vni)));
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ tnl->tp_src = udp->udp_src;
|
||||
+ tnl->tp_dst = udp->udp_dst;
|
||||
+ tnl->tun_id = htonll(ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
|
||||
+ dp_packet_reset_packet(packet, VXLAN_HLEN);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
vxlan_extract_md_no_decap(struct dp_packet *packet)
|
||||
{
|
||||
struct pkt_metadata *md = &packet->md;
|
||||
@@ -1595,6 +1697,7 @@ vxlan_extract_md_no_decap(struct dp_packet *packet)
|
||||
tnl->flags |= FLOW_TNL_F_NSI;
|
||||
tnl->flags |= FLOW_TNL_F_NSH_C1 | FLOW_TNL_F_NSH_C2 | \
|
||||
FLOW_TNL_F_NSH_C3 | FLOW_TNL_F_NSH_C4;
|
||||
+ tnl->tun_len = VXNSH_HLEN;
|
||||
tnl->nsh_flags = NSH_TNL_F_NODECAP;
|
||||
} else {
|
||||
VLOG_WARN("Unsupported vxlan GPE + NSH format!");
|
||||
@@ -1606,19 +1709,19 @@ vxlan_extract_md_no_decap(struct dp_packet *packet)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-
|
||||
static int
|
||||
netdev_vxlan_pop_header_spec(struct dp_packet *packet,
|
||||
const struct ovs_action_pop_tnl *data)
|
||||
{
|
||||
- if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
+ if (data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH) {
|
||||
+ return vxlan_extract_md_convert_to_eth_nsh(packet, data);
|
||||
+ } else if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
return vxlan_extract_md_no_decap(packet);
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
-
|
||||
static int
|
||||
netdev_vxlan_build_header(const struct netdev *netdev,
|
||||
struct ovs_action_push_tnl *data,
|
||||
diff --git a/lib/netdev.h b/lib/netdev.h
|
||||
index b30c932..26013ef 100644
|
||||
--- a/lib/netdev.h
|
||||
+++ b/lib/netdev.h
|
||||
@@ -150,6 +150,10 @@ struct netdev_tunnel_config {
|
||||
bool ipsec;
|
||||
bool dont_fragment;
|
||||
|
||||
+ bool eth_dst_present;
|
||||
+ bool eth_dst_flow;
|
||||
+ struct eth_addr eth_dst;
|
||||
+
|
||||
bool in_nshc1_present;
|
||||
bool in_nshc1_flow;
|
||||
ovs_be32 in_nshc1; /* incoming NSH context c1 */
|
||||
@@ -182,6 +186,7 @@ struct netdev_tunnel_config {
|
||||
bool out_nshc4_flow;
|
||||
ovs_be32 out_nshc4; /* outgoing NSH context c4 */
|
||||
|
||||
+ bool nsh_convert;
|
||||
bool tun_nodecap;
|
||||
|
||||
};
|
||||
@@ -247,6 +252,7 @@ int netdev_pop_header(struct netdev *netdev, struct dp_packet **buffers,
|
||||
int netdev_pop_header_spec(struct netdev *netdev,
|
||||
struct dp_packet **buffers, int cnt,
|
||||
const struct ovs_action_pop_tnl *data);
|
||||
+
|
||||
/* Hardware address. */
|
||||
int netdev_set_etheraddr(struct netdev *, const struct eth_addr mac);
|
||||
int netdev_get_etheraddr(const struct netdev *, struct eth_addr *mac);
|
||||
diff --git a/lib/odp-util.c b/lib/odp-util.c
|
||||
index 190117f..6da2d5b 100644
|
||||
--- a/lib/odp-util.c
|
||||
+++ b/lib/odp-util.c
|
||||
@@ -552,16 +552,22 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
|
||||
}
|
||||
|
||||
static void
|
||||
-format_odp_tnl_pop_spec_action(struct ds *ds, const struct nlattr *attr)
|
||||
+format_odp_tnl_pop_header(struct ds *ds, struct ovs_action_pop_tnl *data)
|
||||
{
|
||||
- struct ovs_action_pop_tnl *data;
|
||||
+ const struct eth_header *eth;
|
||||
|
||||
- data = (struct ovs_action_pop_tnl *) nl_attr_get(attr);
|
||||
+ eth = (const struct eth_header *)data->header;
|
||||
+ if (data->tnl_type == OVS_VPORT_TYPE_NSH) {
|
||||
+ const struct nshhdr *nsh = (const struct nshhdr *) (eth + 1);
|
||||
|
||||
- ds_put_format(ds, "tnl_pop_spec(tnl_port(%"PRIu32"),", data->tnl_port);
|
||||
- if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
- ds_put_format(ds, "pop_type=%"PRIu16")",
|
||||
- OVS_POP_SPEC_ACTION_NO_DECAP);
|
||||
+ /* Ethernet */
|
||||
+ ds_put_format(ds, "header(size=%"PRIu8",type=%"PRIu8",eth(dst=",
|
||||
+ data->header_len, data->tnl_type);
|
||||
+ ds_put_format(ds, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_dst));
|
||||
+ ds_put_format(ds, ",src=");
|
||||
+ ds_put_format(ds, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_src));
|
||||
+ ds_put_format(ds, ",dl_type=0x%04"PRIx16")", ntohs(eth->eth_type));
|
||||
+ ds_put_format(ds, "),");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -578,6 +584,26 @@ format_odp_tnl_push_action(struct ds *ds, const struct nlattr *attr)
|
||||
}
|
||||
|
||||
static void
|
||||
+format_odp_tnl_pop_spec_action(struct ds *ds, const struct nlattr *attr)
|
||||
+{
|
||||
+ struct ovs_action_pop_tnl *data;
|
||||
+
|
||||
+ data = (struct ovs_action_pop_tnl *) nl_attr_get(attr);
|
||||
+
|
||||
+ ds_put_format(ds, "tnl_pop_spec(tnl_port(%"PRIu32"),", data->tnl_port);
|
||||
+ if (data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH) {
|
||||
+ ds_put_format(ds, "pop_type=%"PRIu16",",
|
||||
+ OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH);
|
||||
+ format_odp_tnl_pop_header(ds, data);
|
||||
+ ds_put_format(ds, "out_port(%"PRIu32"))", data->out_port);
|
||||
+
|
||||
+ } else if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
+ ds_put_format(ds, "pop_type=%"PRIu16")",
|
||||
+ OVS_POP_SPEC_ACTION_NO_DECAP);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
format_odp_action(struct ds *ds, const struct nlattr *a)
|
||||
{
|
||||
int expected_len;
|
||||
@@ -1050,11 +1076,8 @@ static int
|
||||
ovs_parse_tnl_pop_spec(const char *s, struct ovs_action_pop_tnl *data)
|
||||
{
|
||||
struct eth_header *eth;
|
||||
- struct nshhdr *nsh;
|
||||
uint32_t tnl_type = 0, header_len = 0;
|
||||
uint16_t dl_type;
|
||||
- ovs_be32 nsp, nshc1, nshc2, nshc3, nshc4;
|
||||
- uint8_t nsi;
|
||||
int n = 0;
|
||||
if (!ovs_scan_len(s, &n, "tnl_pop_spec(tnl_port(%"SCNi32"),",
|
||||
&data->tnl_port)) {
|
||||
@@ -1068,6 +1091,42 @@ ovs_parse_tnl_pop_spec(const char *s, struct ovs_action_pop_tnl *data)
|
||||
|
||||
if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
return n;
|
||||
+
|
||||
+ } else if (data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH) {
|
||||
+
|
||||
+ eth = (struct eth_header *) data->header;
|
||||
+
|
||||
+ if (!ovs_scan_len(s, &n, ",header(size=%"SCNi32",type=%"SCNi32","
|
||||
+ "eth(dst="ETH_ADDR_SCAN_FMT",",
|
||||
+ &data->header_len,
|
||||
+ &data->tnl_type,
|
||||
+ ETH_ADDR_SCAN_ARGS(eth->eth_dst))) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (!ovs_scan_len(s, &n, "src="ETH_ADDR_SCAN_FMT",",
|
||||
+ ETH_ADDR_SCAN_ARGS(eth->eth_src))) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (!ovs_scan_len(s, &n, "dl_type=0x%"SCNx16"),", &dl_type)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ eth->eth_type = htons(dl_type);
|
||||
+
|
||||
+ tnl_type = OVS_VPORT_TYPE_NSH;
|
||||
+ header_len = sizeof *eth;
|
||||
+
|
||||
+ /* check tunnel meta data. */
|
||||
+ if (data->tnl_type != tnl_type) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (data->header_len != header_len) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Out port */
|
||||
+ if (!ovs_scan_len(s, &n, ",out_port(%"SCNi32"))", &data->out_port)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1075,6 +1134,7 @@ ovs_parse_tnl_pop_spec(const char *s, struct ovs_action_pop_tnl *data)
|
||||
return n;
|
||||
}
|
||||
|
||||
+
|
||||
static int
|
||||
parse_odp_action(const char *s, const struct simap *port_names,
|
||||
struct ofpbuf *actions)
|
||||
diff --git a/lib/ovs-router.c b/lib/ovs-router.c
|
||||
index d6c7652..9f61bac 100644
|
||||
--- a/lib/ovs-router.c
|
||||
+++ b/lib/ovs-router.c
|
||||
@@ -82,6 +82,24 @@ ovs_router_lookup(ovs_be32 ip_dst, char output_bridge[], ovs_be32 *gw)
|
||||
return route_table_fallback_lookup(ip_dst, output_bridge, gw);
|
||||
}
|
||||
|
||||
+bool
|
||||
+ovs_router_lookup_mac(const struct eth_addr *mac, char output_bridge[])
|
||||
+{
|
||||
+ const struct cls_rule *cr;
|
||||
+ struct flow s_flow;
|
||||
+
|
||||
+ memset(&s_flow, 0, sizeof (struct flow));
|
||||
+ memcpy(s_flow.dl_dst.ea, mac->ea, ETH_ADDR_LEN);
|
||||
+ cr = classifier_lookup(&cls,CLS_MAX_VERSION, &s_flow, NULL);
|
||||
+ if (cr) {
|
||||
+ struct ovs_router_entry *p = ovs_router_entry_cast(cr);
|
||||
+
|
||||
+ strncpy(output_bridge, p->output_bridge, IFNAMSIZ);
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static void
|
||||
rt_entry_free(struct ovs_router_entry *p)
|
||||
{
|
||||
@@ -133,6 +151,36 @@ ovs_router_insert__(uint8_t priority, ovs_be32 ip_dst, uint8_t plen,
|
||||
seq_change(tnl_conf_seq);
|
||||
}
|
||||
|
||||
+static void
|
||||
+ovs_router_insert_mac__(uint8_t priority, struct eth_addr *mac,
|
||||
+ const char output_bridge[])
|
||||
+{
|
||||
+ const struct cls_rule *cr;
|
||||
+ struct ovs_router_entry *p;
|
||||
+ struct match s_match;
|
||||
+
|
||||
+ memset(&s_match, 0, sizeof (struct match));
|
||||
+ memcpy(s_match.flow.dl_dst.ea, mac->ea, ETH_ADDR_LEN);
|
||||
+
|
||||
+ p = xzalloc(sizeof *p);
|
||||
+ strncpy(p->output_bridge, output_bridge, IFNAMSIZ);
|
||||
+ p->gw = 0;
|
||||
+ p->nw_addr = 0;
|
||||
+ p->plen = 32;
|
||||
+ p->priority = priority;
|
||||
+ cls_rule_init(&p->cr, &s_match, priority); /* Longest prefix matches first. */
|
||||
+
|
||||
+ ovs_mutex_lock(&mutex);
|
||||
+ cr = classifier_replace(&cls, &p->cr, CLS_MIN_VERSION, NULL, 0);
|
||||
+ ovs_mutex_unlock(&mutex);
|
||||
+
|
||||
+ if (cr) {
|
||||
+ /* An old rule with the same match was displaced. */
|
||||
+ ovsrcu_postpone(rt_entry_free, ovs_router_entry_cast(cr));
|
||||
+ }
|
||||
+ seq_change(tnl_conf_seq);
|
||||
+}
|
||||
+
|
||||
void
|
||||
ovs_router_insert(ovs_be32 ip_dst, uint8_t plen, const char output_bridge[],
|
||||
ovs_be32 gw)
|
||||
@@ -231,6 +279,20 @@ ovs_router_add(struct unixctl_conn *conn, int argc,
|
||||
}
|
||||
|
||||
static void
|
||||
+ovs_router_add_mac(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
||||
+ const char *argv[], void *aux OVS_UNUSED)
|
||||
+{
|
||||
+ struct eth_addr mac;
|
||||
+
|
||||
+ if (eth_addr_from_string(argv[1], &mac)) {
|
||||
+ ovs_router_insert_mac__(48, &mac, argv[2]);
|
||||
+ unixctl_command_reply(conn, "OK");
|
||||
+ } else {
|
||||
+ unixctl_command_reply(conn, "Invalid parameters");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
ovs_router_del(struct unixctl_conn *conn, int argc OVS_UNUSED,
|
||||
const char *argv[], void *aux OVS_UNUSED)
|
||||
{
|
||||
@@ -326,6 +388,8 @@ ovs_router_init(void)
|
||||
classifier_init(&cls, NULL);
|
||||
unixctl_command_register("ovs/route/add", "ipv4_addr/prefix_len out_br_name gw", 2, 3,
|
||||
ovs_router_add, NULL);
|
||||
+ unixctl_command_register("ovs/route/addmac", "mac_addr out_br_name", 2, 2,
|
||||
+ ovs_router_add_mac, NULL);
|
||||
unixctl_command_register("ovs/route/show", "", 0, 0, ovs_router_show, NULL);
|
||||
unixctl_command_register("ovs/route/del", "ipv4_addr/prefix_len", 1, 1, ovs_router_del,
|
||||
NULL);
|
||||
diff --git a/lib/ovs-router.h b/lib/ovs-router.h
|
||||
index cc0ebc2..3f5a504 100644
|
||||
--- a/lib/ovs-router.h
|
||||
+++ b/lib/ovs-router.h
|
||||
@@ -23,6 +23,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
+bool ovs_router_lookup_mac(const struct eth_addr *mac, char output_bridge[]);
|
||||
bool ovs_router_lookup(ovs_be32 ip_dst, char out_dev[], ovs_be32 *gw);
|
||||
void ovs_router_init(void);
|
||||
void ovs_router_insert(ovs_be32 ip_dst, uint8_t plen,
|
||||
diff --git a/lib/packets.h b/lib/packets.h
|
||||
index 87c955a..c586390 100644
|
||||
--- a/lib/packets.h
|
||||
+++ b/lib/packets.h
|
||||
@@ -33,6 +33,8 @@
|
||||
struct dp_packet;
|
||||
struct ds;
|
||||
|
||||
+#define ETH_ADDR_LEN 6
|
||||
+
|
||||
/* Tunnel information used in flow key and metadata. */
|
||||
struct flow_tnl {
|
||||
ovs_be32 ip_dst;
|
||||
@@ -52,7 +54,9 @@ struct flow_tnl {
|
||||
ovs_be32 nshc2;
|
||||
ovs_be32 nshc3;
|
||||
ovs_be32 nshc4;
|
||||
- uint8_t pad1[7]; /* Pad to 64 bits. */
|
||||
+ struct eth_addr eth_dst;
|
||||
+ uint8_t tun_len;
|
||||
+ uint8_t pad1[4]; /* Pad to 64 bits. */
|
||||
struct tun_metadata metadata;
|
||||
};
|
||||
|
||||
@@ -83,7 +87,9 @@ struct flow_tnl {
|
||||
#define FLOW_TNL_F_NSH_C3 (1 << 9)
|
||||
#define FLOW_TNL_F_NSH_C4 (1 << 10)
|
||||
|
||||
-#define NSH_TNL_F_NODECAP (1 << 1)
|
||||
+#define NSH_TNL_F_ETHERNET (1 << 0)
|
||||
+#define NSH_TNL_F_VXLAN (1 << 1)
|
||||
+#define NSH_TNL_F_NODECAP (1 << 2)
|
||||
|
||||
/* Returns an offset to 'src' covering all the meaningful fields in 'src'. */
|
||||
static inline size_t
|
||||
@@ -160,8 +166,6 @@ pkt_metadata_init(struct pkt_metadata *md, odp_port_t port)
|
||||
|
||||
bool dpid_from_string(const char *s, uint64_t *dpidp);
|
||||
|
||||
-#define ETH_ADDR_LEN 6
|
||||
-
|
||||
static const struct eth_addr eth_addr_broadcast OVS_UNUSED
|
||||
= { { { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } } };
|
||||
|
||||
@@ -352,6 +356,7 @@ ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos,
|
||||
#define ETH_TYPE_RARP 0x8035
|
||||
#define ETH_TYPE_MPLS 0x8847
|
||||
#define ETH_TYPE_MPLS_MCAST 0x8848
|
||||
+#define ETH_TYPE_NSH 0x894f
|
||||
|
||||
static inline bool eth_type_mpls(ovs_be16 eth_type)
|
||||
{
|
||||
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
|
||||
index 71e255e..bff0a83 100644
|
||||
--- a/ofproto/ofproto-dpif-xlate.c
|
||||
+++ b/ofproto/ofproto-dpif-xlate.c
|
||||
@@ -2690,6 +2690,36 @@ tnl_route_lookup_flow(const struct flow *oflow,
|
||||
}
|
||||
|
||||
static int
|
||||
+tnl_outdev_lookup_mac(const struct eth_addr *mac,
|
||||
+ struct xport **out_port)
|
||||
+{
|
||||
+ char out_dev[IFNAMSIZ];
|
||||
+ struct xbridge *xbridge;
|
||||
+ struct xlate_cfg *xcfg;
|
||||
+
|
||||
+ if (!ovs_router_lookup_mac(mac, out_dev)) {
|
||||
+ return -ENOENT;
|
||||
+ }
|
||||
+
|
||||
+ xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp);
|
||||
+ ovs_assert(xcfg);
|
||||
+
|
||||
+ HMAP_FOR_EACH (xbridge, hmap_node, &xcfg->xbridges) {
|
||||
+ if (!strncmp(xbridge->name, out_dev, IFNAMSIZ)) {
|
||||
+ struct xport *port;
|
||||
+
|
||||
+ HMAP_FOR_EACH (port, ofp_node, &xbridge->xports) {
|
||||
+ if (!strncmp(netdev_get_name(port->netdev), out_dev, IFNAMSIZ)) {
|
||||
+ *out_port = port;
|
||||
+ return 0;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ return -ENOENT;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
compose_table_xlate(struct xlate_ctx *ctx, const struct xport *out_dev,
|
||||
struct dp_packet *packet)
|
||||
{
|
||||
@@ -2795,7 +2825,39 @@ build_tunnel_pop(const struct xlate_ctx *ctx, odp_port_t tunnel_odp_port, struct
|
||||
cfg = tnl_port_cfg(tunnel_odp_port, flow);
|
||||
|
||||
if (cfg) {
|
||||
- if (cfg->tun_nodecap) {
|
||||
+ if (cfg->nsh_convert && (ntohs(cfg->dst_port) == VXGPE_DST_PORT)) {
|
||||
+ struct ovs_action_pop_tnl tnl_pop_data;
|
||||
+ struct xport *out_dev = NULL;
|
||||
+ struct eth_addr smac;
|
||||
+
|
||||
+ int err;
|
||||
+
|
||||
+ err = tnl_outdev_lookup_mac(&cfg->eth_dst, &out_dev);
|
||||
+ if (err) {
|
||||
+ VLOG_WARN("tnl_outdev_lookup_mac failed...");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Use mac addr of bridge port of the peer. */
|
||||
+ err = netdev_get_etheraddr(out_dev->netdev, &smac);
|
||||
+ if (err) {
|
||||
+ VLOG_WARN("netdev_get_etheraddr failed...");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = tnl_port_build_nsh_header_odport_popspec(tunnel_odp_port, flow,
|
||||
+ &cfg->eth_dst, &smac, &tnl_pop_data);
|
||||
+ if (err) {
|
||||
+ VLOG_WARN("tnl_port_build_nsh_header failed...");
|
||||
+ return err;
|
||||
+ }
|
||||
+ tnl_pop_data.tnl_port = odp_to_u32(tunnel_odp_port);
|
||||
+ tnl_pop_data.out_port = odp_to_u32(out_dev->odp_port);
|
||||
+ tnl_pop_data.pop_type = OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH;
|
||||
+ tnl_pop_data.tnl_type = OVS_VPORT_TYPE_NSH;
|
||||
+ odp_put_tnl_pop_spec_action(ctx->odp_actions, &tnl_pop_data);
|
||||
+
|
||||
+ } else if (cfg->tun_nodecap) {
|
||||
struct ovs_action_pop_tnl tnl_pop_data;
|
||||
memset(&tnl_pop_data, 0, sizeof tnl_pop_data);
|
||||
|
||||
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
|
||||
index 4606fb6..b0e46e6 100644
|
||||
--- a/ofproto/tunnel.c
|
||||
+++ b/ofproto/tunnel.c
|
||||
@@ -45,6 +45,8 @@ VLOG_DEFINE_THIS_MODULE(tunnel);
|
||||
/* skb mark used for IPsec tunnel packets */
|
||||
#define IPSEC_MARK 1
|
||||
|
||||
+#define ETH_NSH_HLEN (sizeof(struct eth_header) + \
|
||||
+ sizeof(struct nshhdr))
|
||||
struct tnl_match {
|
||||
ovs_be64 in_key;
|
||||
ovs_be32 in_nsp;
|
||||
@@ -568,6 +570,9 @@ tnl_port_cfg(odp_port_t odp_port, struct flow *flow) OVS_EXCLUDED(rwlock)
|
||||
cfg = netdev_get_tunnel_config(tnl_port->netdev);
|
||||
ovs_assert(cfg);
|
||||
|
||||
+ if (!cfg->eth_dst_flow) {
|
||||
+ memcpy(flow->tunnel.eth_dst.ea, cfg->eth_dst.ea, ETH_ADDR_LEN);
|
||||
+ }
|
||||
if (!cfg->out_nsp_flow) {
|
||||
flow->tunnel.nsp = cfg->out_nsp;
|
||||
}
|
||||
@@ -602,6 +607,7 @@ out:
|
||||
return cfg;
|
||||
}
|
||||
|
||||
+
|
||||
static uint32_t
|
||||
tnl_hash(struct tnl_match *match)
|
||||
{
|
||||
@@ -1063,3 +1069,34 @@ tnl_port_build_header(const struct ofport_dpif *ofport,
|
||||
|
||||
return res;
|
||||
}
|
||||
+
|
||||
+int
|
||||
+tnl_port_build_nsh_header_odport_popspec(const odp_port_t odp_port,
|
||||
+ const struct flow *tnl_flow OVS_UNUSED,
|
||||
+ const struct eth_addr *dmac,
|
||||
+ const struct eth_addr *smac,
|
||||
+ struct ovs_action_pop_tnl *data)
|
||||
+{
|
||||
+ struct tnl_port *tnl_port;
|
||||
+ struct eth_header *eth;
|
||||
+ int res = 0;
|
||||
+
|
||||
+ fat_rwlock_rdlock(&rwlock);
|
||||
+ tnl_port = tnl_find_odp_port(odp_port);
|
||||
+ ovs_assert(tnl_port);
|
||||
+
|
||||
+ /* Build Ethernet and IP headers. */
|
||||
+ memset(data->header, 0, sizeof data->header);
|
||||
+
|
||||
+ eth = (struct eth_header *)data->header;
|
||||
+ memcpy(eth->eth_dst.ea, dmac->ea, ETH_ADDR_LEN);
|
||||
+ memcpy(eth->eth_src.ea, smac->ea, ETH_ADDR_LEN);
|
||||
+ eth->eth_type = htons(ETH_TYPE_NSH);
|
||||
+
|
||||
+ data->header_len = ETH_NSH_HLEN - sizeof (struct nshhdr);
|
||||
+ data->tnl_type = OVS_VPORT_TYPE_NSH;
|
||||
+
|
||||
+ fat_rwlock_unlock(&rwlock);
|
||||
+
|
||||
+ return res;
|
||||
+}
|
||||
diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h
|
||||
index 2b608ce..0c51a4e 100644
|
||||
--- a/ofproto/tunnel.h
|
||||
+++ b/ofproto/tunnel.h
|
||||
@@ -59,4 +59,9 @@ int tnl_port_build_header(const struct ofport_dpif *ofport,
|
||||
const struct eth_addr dmac,
|
||||
const struct eth_addr smac,
|
||||
ovs_be32 ip_src, struct ovs_action_push_tnl *data);
|
||||
+int tnl_port_build_nsh_header_odport_popspec(const odp_port_t odp_port,
|
||||
+ const struct flow *tnl_flow OVS_UNUSED,
|
||||
+ const struct eth_addr *dmac,
|
||||
+ const struct eth_addr *smac,
|
||||
+ struct ovs_action_pop_tnl *data);
|
||||
#endif /* tunnel.h */
|
||||
diff --git a/tests/tunnel.at b/tests/tunnel.at
|
||||
index 851afdc..dc35809 100644
|
||||
--- a/tests/tunnel.at
|
||||
+++ b/tests/tunnel.at
|
||||
@@ -673,6 +673,38 @@ AT_CHECK([tail -1 stdout], [0],
|
||||
OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
AT_CLEANUP
|
||||
|
||||
+AT_SETUP([tunnel - VXLAN-GPE NSH - nsh_convert from VXLAN-GPE NSH to Ethernet NSH - user space])
|
||||
+OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
|
||||
+AT_CHECK([ovs-vsctl add-br int-br -- set bridge int-br datapath_type=dummy], [0])
|
||||
+AT_CHECK([ovs-vsctl add-port int-br p1 -- set interface p1 type=vxlan options:remote_ip=1.1.1.1 options:dst_port=4790 \
|
||||
+ options:nsh_convert=true options:nsi=flow options:nsp=flow options:nshc1=flow options:in_key=flow options:remote_mac=00:00:00:11:11:22 ofport_request=2])
|
||||
+AT_CHECK([ovs-vsctl add-port int-br p2 -- set Interface p2 type=dummy ofport_request=3])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 2.2.2.22/24], [0], [OK
|
||||
+])
|
||||
+AT_CHECK([ovs-appctl ovs/route/add 1.1.1.1/24 br0], [0], [OK
|
||||
+])
|
||||
+AT_CHECK([ovs-appctl ovs/route/addmac 00:00:00:11:11:22 br0],[0],[dnl
|
||||
+OK
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([ovs-ofctl add-flow br0 action=normal])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl tnl/ports/show |sort], [0], [dnl
|
||||
+Listening ports:
|
||||
+vxlan_sys_4790 (4790)
|
||||
+])
|
||||
+
|
||||
+dnl remote_ip p0
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(3),eth(src=50:54:00:00:00:05,dst=aa:55:aa:55:00:00),eth_type(0x0800),ipv4(src=1.1.1.1,dst=2.2.2.22,proto=17,tos=0,ttl=64,frag=no),udp(src=8,dst=4790)'], [0], [stdout])
|
||||
+
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_pop_spec(tnl_port(4790),pop_type=0,header(size=14,type=107,eth(dst=00:00:00:11:11:22,src=aa:55:aa:55:00:00,dl_type=0x894f)),out_port(100))
|
||||
+])
|
||||
+
|
||||
+OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
AT_SETUP([tunnel - Geneve metadata])
|
||||
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \
|
||||
options:remote_ip=1.1.1.1 ofport_request=1 \
|
||||
--
|
||||
1.9.3
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,151 +0,0 @@
|
|||
decapsulation-reencapsulation case.
|
||||
|
||||
When Ethernet NSH packets are received and then resent to Ethernet NSH port.
|
||||
The decapsulation and encapsulation will be implemented. However, tunnel pop
|
||||
and tunnel push actions are very time-consuming when decapsulation and
|
||||
encapsulation.
|
||||
|
||||
With this feature (options:tun_nodecap=true), tunnel port will parse the input
|
||||
tunnel packets, but the tunnel header will be kept. And the tunnel header can
|
||||
be modified by the set field actions. This feature can improve performance.
|
||||
|
||||
Signed-off-by: Ricky Li <<A HREF="http://openvswitch.org/mailman/listinfo/dev">ricky.li at intel.com</A>>
|
||||
Signed-off-by: Mengke Liu <<A HREF="http://openvswitch.org/mailman/listinfo/dev">mengke.liu at intel.com</A>>
|
||||
---
|
||||
lib/netdev-vport.c | 43 ++++++++++++++++++++++++++++++++++++++++++-
|
||||
lib/odp-util.c | 3 ++-
|
||||
lib/packets.c | 10 +++++++++-
|
||||
tests/tunnel.at | 21 +++++++++++++++++++++
|
||||
4 files changed, 74 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
|
||||
index 0a3da8d..038f1e1 100644
|
||||
--- a/lib/netdev-vport.c
|
||||
+++ b/lib/netdev-vport.c
|
||||
@@ -1865,6 +1865,47 @@ netdev_nsh_pop_header(struct dp_packet *packet)
|
||||
}
|
||||
|
||||
static int
|
||||
+netdev_nsh_pop_header_spec(struct dp_packet *packet,
|
||||
+ const struct ovs_action_pop_tnl *data)
|
||||
+{
|
||||
+ struct pkt_metadata *md = &packet->md;
|
||||
+ struct flow_tnl *tnl = &md->tunnel;
|
||||
+ struct eth_header *eth;
|
||||
+ struct nshhdr *nsh;
|
||||
+
|
||||
+ if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
+
|
||||
+ pkt_metadata_init_tnl(md);
|
||||
+ if (ETH_NSH_HLEN > dp_packet_size(packet)) {
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ eth = (struct eth_header *) dp_packet_data(packet);
|
||||
+ memcpy(tnl->eth_dst.ea, eth->eth_dst.ea, ETH_ADDR_LEN);
|
||||
+ memcpy(tnl->eth_src.ea, eth->eth_src.ea, ETH_ADDR_LEN);
|
||||
+
|
||||
+ nsh = (struct nshhdr *) (eth + 1);
|
||||
+ tnl->nsp = nsh->b.b2 << 8;
|
||||
+ tnl->nsi = nsh->b.svc_idx;
|
||||
+ tnl->nshc1 = nsh->c.nshc1;
|
||||
+ tnl->nshc2 = nsh->c.nshc2;
|
||||
+ tnl->nshc3 = nsh->c.nshc3;
|
||||
+ tnl->nshc4 = nsh->c.nshc4;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSP;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSI;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSH_C1 | FLOW_TNL_F_NSH_C2 | \
|
||||
+ FLOW_TNL_F_NSH_C3 | FLOW_TNL_F_NSH_C4;
|
||||
+
|
||||
+ tnl->nsh_flags = NSH_TNL_F_ETHERNET_PARSED | NSH_TNL_F_ETHERNET_PRST| NSH_TNL_F_NODECAP;
|
||||
+ tnl->tun_len = ETH_NSH_HLEN;
|
||||
+
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ return EINVAL;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
netdev_nsh_build_header(const struct netdev *netdev,
|
||||
struct ovs_action_push_tnl *data,
|
||||
const struct flow *tnl_flow)
|
||||
@@ -2144,7 +2185,7 @@ netdev_vport_tunnel_register(void)
|
||||
TUNNEL_CLASS("eth_nsh", "nsh_sys", netdev_nsh_build_header,
|
||||
netdev_nsh_push_header,
|
||||
netdev_nsh_pop_header,
|
||||
- NULL),
|
||||
+ netdev_nsh_pop_header_spec),
|
||||
};
|
||||
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
|
||||
|
||||
diff --git a/lib/odp-util.c b/lib/odp-util.c
|
||||
index c2af063..a87b3be 100644
|
||||
--- a/lib/odp-util.c
|
||||
+++ b/lib/odp-util.c
|
||||
@@ -4837,7 +4837,8 @@ commit_odp_tunnel_set_action(const struct flow_tnl *tunnel, struct flow_tnl *bas
|
||||
struct ofpbuf *odp_actions)
|
||||
{
|
||||
/* A valid IPV4_TUNNEL must have non-zero ip_dst. */
|
||||
- if (tunnel->ip_dst) {
|
||||
+ if (tunnel->ip_dst ||
|
||||
+ tunnel->nsh_flags & NSH_TNL_F_ETHERNET_PARSED) {
|
||||
|
||||
if (!memcmp(tunnel, base, sizeof *tunnel)) {
|
||||
return;
|
||||
diff --git a/lib/packets.c b/lib/packets.c
|
||||
index 7dab4b5..14a19b1 100644
|
||||
--- a/lib/packets.c
|
||||
+++ b/lib/packets.c
|
||||
@@ -934,7 +934,15 @@ packet_set_nsh(struct dp_packet *packet, struct flow_tnl *tun_key)
|
||||
|
||||
eth = (struct eth_header *) dp_packet_data(packet);
|
||||
|
||||
- if (tun_key->nsh_flags & NSH_TNL_F_VXLAN_PRST) {
|
||||
+ if (tun_key->nsh_flags & NSH_TNL_F_ETHERNET_PRST) {
|
||||
+ nsh = (struct nshhdr *) (eth + 1);
|
||||
+ nsh->b.b2 = tun_key->nsp >> 8;
|
||||
+ nsh->b.svc_idx = tun_key->nsi;
|
||||
+ nsh->c.nshc1 = tun_key->nshc1;
|
||||
+ nsh->c.nshc2 = tun_key->nshc2;
|
||||
+ nsh->c.nshc3 = tun_key->nshc3;
|
||||
+ nsh->c.nshc4 = tun_key->nshc4;
|
||||
+ } else if (tun_key->nsh_flags & NSH_TNL_F_VXLAN_PRST) {
|
||||
struct ip_header *ip = (struct ip_header *) (eth + 1);
|
||||
struct udp_header *udp = (struct udp_header *) (ip + 1);
|
||||
struct vxgpehdr *vxg = (struct vxgpehdr *) (udp + 1);
|
||||
diff --git a/tests/tunnel.at b/tests/tunnel.at
|
||||
index 19221fb..1bbf5e2 100644
|
||||
--- a/tests/tunnel.at
|
||||
+++ b/tests/tunnel.at
|
||||
@@ -765,6 +765,27 @@ AT_CHECK([tail -1 stdout], [0],
|
||||
OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
AT_CLEANUP
|
||||
|
||||
+AT_SETUP([tunnel - ETHERNET NSH tun_nodecap - user space])
|
||||
+OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
|
||||
+AT_CHECK([ovs-vsctl add-port br0 p1 -- set interface p1 type=eth_nsh options:tun_nodecap=true options:remote_mac=00:00:00:11:11:22 \
|
||||
+options:out_nsp=flow options:out_nsi=flow options:in_nshc1=flow options:in_nshc2=flow options:in_nshc3=flow options:in_nshc4=flow ofport_request=2], [0])
|
||||
+
|
||||
+AT_CHECK([ovs-ofctl add-flow br0 "priority=16, in_port=1, action=local"])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
|
||||
+ br0 65534/100: (dummy)
|
||||
+ p0 1/1: (dummy)
|
||||
+ p1 2/2: (eth_nsh: in_nshc1=flow, in_nshc2=flow, in_nshc3=flow, in_nshc4=flow, out_nsi=flow, out_nsp=flow, remote_mac=00:00:00:11:11:22, tun_nodecap=true)
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=00:00:00:11:11:22,dst=50:54:00:00:00:07),eth_type(0x894f)'], [0], [stdout])
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_pop_spec(tnl_port(2),pop_type=2)
|
||||
+])
|
||||
+
|
||||
+OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
AT_SETUP([tunnel - Geneve metadata])
|
||||
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \
|
||||
options:remote_ip=1.1.1.1 ofport_request=1 \
|
||||
--
|
||||
1.9.3
|
||||
|
|
@ -1,675 +0,0 @@
|
|||
VxLAN-GPE NSH packet.
|
||||
|
||||
With this feature (options:nsh-convert=true),when Ethernet-NSH packet (Outer
|
||||
MAC header + original packet) are received by Ethernet-NSH port, the vport
|
||||
will remove Outer MAC header, and then modify and push the
|
||||
outer MAC header + Outer IP header + UDP header + VxLAN-GPE. Then the packet
|
||||
with Ethernet+NSH format is converted to VxLAN-GPE NSH packet.
|
||||
|
||||
Signed-off-by: Ricky Li <<A HREF="http://openvswitch.org/mailman/listinfo/dev">ricky.li at intel.com</A>>
|
||||
Signed-off-by: Mengke Liu <<A HREF="http://openvswitch.org/mailman/listinfo/dev">mengke.liu at intel.com</A>>
|
||||
---
|
||||
datapath/linux/compat/include/linux/openvswitch.h | 3 +-
|
||||
lib/netdev-vport.c | 128 +++++++++++++++++-----
|
||||
lib/odp-util.c | 121 +++++++++++++++++++-
|
||||
ofproto/ofproto-dpif-xlate.c | 113 ++++++++++++++++++-
|
||||
ofproto/tunnel.c | 75 +++++++++++++
|
||||
ofproto/tunnel.h | 7 ++
|
||||
tests/tunnel.at | 29 +++++
|
||||
7 files changed, 440 insertions(+), 36 deletions(-)
|
||||
|
||||
diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h
|
||||
index 045a1f4..916aeae 100644
|
||||
--- a/datapath/linux/compat/include/linux/openvswitch.h
|
||||
+++ b/datapath/linux/compat/include/linux/openvswitch.h
|
||||
@@ -651,7 +651,8 @@ struct ovs_action_push_tnl {
|
||||
|
||||
enum ovs_pop_spec_action_type {
|
||||
OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH,
|
||||
- OVS_POP_SPEC_ACTION_NO_DECAP = 2,
|
||||
+ OVS_POP_SPEC_ACTION_CONVERT_TO_VXLAN_GPE_NSH,
|
||||
+ OVS_POP_SPEC_ACTION_NO_DECAP,
|
||||
};
|
||||
|
||||
/*
|
||||
diff --git a/lib/netdev-vport.c b/lib/netdev-vport.c
|
||||
index 038f1e1..6142935 100644
|
||||
--- a/lib/netdev-vport.c
|
||||
+++ b/lib/netdev-vport.c
|
||||
@@ -167,7 +167,8 @@ netdev_vport_needs_dst_port(const struct netdev *dev)
|
||||
|
||||
return (class->get_config == get_tunnel_config &&
|
||||
(!strcmp("geneve", type) || !strcmp("vxlan", type) ||
|
||||
- !strcmp("lisp", type) || !strcmp("stt", type)) );
|
||||
+ !strcmp("lisp", type) || !strcmp("stt", type) ||
|
||||
+ !strcmp("eth_nsh", type)) );
|
||||
}
|
||||
|
||||
const char *
|
||||
@@ -890,7 +891,8 @@ get_tunnel_config(const struct netdev *dev, struct smap *args)
|
||||
if ((!strcmp("geneve", type) && dst_port != GENEVE_DST_PORT) ||
|
||||
(!strcmp("vxlan", type) && dst_port != VXLAN_DST_PORT) ||
|
||||
(!strcmp("lisp", type) && dst_port != LISP_DST_PORT) ||
|
||||
- (!strcmp("stt", type) && dst_port != STT_DST_PORT)) {
|
||||
+ (!strcmp("stt", type) && dst_port != STT_DST_PORT) ||
|
||||
+ (!strcmp("eth_nsh", type) && tnl_cfg.nsh_convert)) {
|
||||
smap_add_format(args, "dst_port", "%d", dst_port);
|
||||
}
|
||||
}
|
||||
@@ -1864,42 +1866,116 @@ netdev_nsh_pop_header(struct dp_packet *packet)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+
|
||||
static int
|
||||
-netdev_nsh_pop_header_spec(struct dp_packet *packet,
|
||||
- const struct ovs_action_pop_tnl *data)
|
||||
+eth_nsh_extract_md_no_decap(struct dp_packet *packet)
|
||||
{
|
||||
struct pkt_metadata *md = &packet->md;
|
||||
struct flow_tnl *tnl = &md->tunnel;
|
||||
struct eth_header *eth;
|
||||
struct nshhdr *nsh;
|
||||
|
||||
- if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
+ pkt_metadata_init_tnl(md);
|
||||
+ if (ETH_NSH_HLEN > dp_packet_size(packet)) {
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
|
||||
- pkt_metadata_init_tnl(md);
|
||||
- if (ETH_NSH_HLEN > dp_packet_size(packet)) {
|
||||
- return EINVAL;
|
||||
- }
|
||||
+ eth = (struct eth_header *) dp_packet_data(packet);
|
||||
+ memcpy(tnl->eth_src.ea, eth->eth_src.ea, ETH_ADDR_LEN);
|
||||
+ memcpy(tnl->eth_dst.ea, eth->eth_dst.ea, ETH_ADDR_LEN);
|
||||
+
|
||||
+ nsh = (struct nshhdr *) (eth + 1);
|
||||
+ tnl->nsp = nsh->b.b2 << 8;
|
||||
+ tnl->nsi = nsh->b.svc_idx;
|
||||
+ tnl->nshc1 = nsh->c.nshc1;
|
||||
+ tnl->nshc2 = nsh->c.nshc2;
|
||||
+ tnl->nshc3 = nsh->c.nshc3;
|
||||
+ tnl->nshc4 = nsh->c.nshc4;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSP;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSI;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSH_C1 | FLOW_TNL_F_NSH_C2 | \
|
||||
+ FLOW_TNL_F_NSH_C3 | FLOW_TNL_F_NSH_C4;
|
||||
+ tnl->nsh_flags = NSH_TNL_F_ETHERNET_PARSED | NSH_TNL_F_ETHERNET_PRST| NSH_TNL_F_NODECAP;
|
||||
+ tnl->tun_len = ETH_NSH_HLEN;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+eth_nsh_extract_md_convert_to_vxlan_gpe_nsh(struct dp_packet *packet,
|
||||
+ const struct ovs_action_pop_tnl *data)
|
||||
+{
|
||||
+ struct pkt_metadata *md = &packet->md;
|
||||
+ struct flow_tnl *tnl = &md->tunnel;
|
||||
+ struct eth_header *eth;
|
||||
+ struct ip_header *ip;
|
||||
+ struct udp_header *udp;
|
||||
+ struct nshhdr *nsh;
|
||||
+
|
||||
+ pkt_metadata_init_tnl(md);
|
||||
+ if (ETH_NSH_HLEN > dp_packet_size(packet)) {
|
||||
+ return EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ eth = (struct eth_header *) dp_packet_data(packet);
|
||||
+ memcpy(tnl->eth_src.ea, eth->eth_src.ea, ETH_ADDR_LEN);
|
||||
+ memcpy(tnl->eth_dst.ea, eth->eth_dst.ea, ETH_ADDR_LEN);
|
||||
|
||||
- eth = (struct eth_header *) dp_packet_data(packet);
|
||||
- memcpy(tnl->eth_dst.ea, eth->eth_dst.ea, ETH_ADDR_LEN);
|
||||
- memcpy(tnl->eth_src.ea, eth->eth_src.ea, ETH_ADDR_LEN);
|
||||
-
|
||||
- nsh = (struct nshhdr *) (eth + 1);
|
||||
- tnl->nsp = nsh->b.b2 << 8;
|
||||
- tnl->nsi = nsh->b.svc_idx;
|
||||
- tnl->nshc1 = nsh->c.nshc1;
|
||||
- tnl->nshc2 = nsh->c.nshc2;
|
||||
- tnl->nshc3 = nsh->c.nshc3;
|
||||
- tnl->nshc4 = nsh->c.nshc4;
|
||||
- tnl->flags |= FLOW_TNL_F_NSP;
|
||||
- tnl->flags |= FLOW_TNL_F_NSI;
|
||||
- tnl->flags |= FLOW_TNL_F_NSH_C1 | FLOW_TNL_F_NSH_C2 | \
|
||||
+ nsh = (struct nshhdr *) (eth + 1);
|
||||
+ tnl->nsp = nsh->b.b2 << 8;
|
||||
+ tnl->nsi = nsh->b.svc_idx;
|
||||
+ tnl->nshc1 = nsh->c.nshc1;
|
||||
+ tnl->nshc2 = nsh->c.nshc2;
|
||||
+ tnl->nshc3 = nsh->c.nshc3;
|
||||
+ tnl->nshc4 = nsh->c.nshc4;
|
||||
+
|
||||
+ tnl->flags |= FLOW_TNL_F_NSP;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSI;
|
||||
+ tnl->flags |= FLOW_TNL_F_NSH_C1 | FLOW_TNL_F_NSH_C2 | \
|
||||
FLOW_TNL_F_NSH_C3 | FLOW_TNL_F_NSH_C4;
|
||||
|
||||
- tnl->nsh_flags = NSH_TNL_F_ETHERNET_PARSED | NSH_TNL_F_ETHERNET_PRST| NSH_TNL_F_NODECAP;
|
||||
- tnl->tun_len = ETH_NSH_HLEN;
|
||||
+ tnl->nsh_flags = NSH_TNL_F_ETHERNET_PARSED | NSH_TNL_F_VXLAN_PRST;
|
||||
|
||||
- return 0;
|
||||
+ dp_packet_reset_packet(packet, ETH_NSH_HLEN - sizeof (struct nshhdr));
|
||||
+ eth = (struct eth_header *) dp_packet_push_uninit(packet, data->header_len);
|
||||
+ memcpy(eth, data->header, data->header_len);
|
||||
+
|
||||
+
|
||||
+ /* set IP length, csum */
|
||||
+ int ip_tot_size = dp_packet_size(packet) - sizeof (struct eth_header);
|
||||
+ ip = ip_hdr(eth);
|
||||
+ ip->ip_tot_len = htons(ip_tot_size);
|
||||
+ ip->ip_csum = recalc_csum16(ip->ip_csum, 0, ip->ip_tot_len);
|
||||
+
|
||||
+ /* set udp src port */
|
||||
+ udp = (struct udp_header *) (ip + 1);
|
||||
+ udp->udp_src = get_src_port(packet);
|
||||
+ udp->udp_len = htons(ip_tot_size - sizeof (struct ip_header));
|
||||
+
|
||||
+ /* udp_csum is zero */
|
||||
+ if (udp->udp_csum) {
|
||||
+ uint32_t csum = packet_csum_pseudoheader(ip);
|
||||
+
|
||||
+ csum = csum_continue(csum, udp,
|
||||
+ ip_tot_size - sizeof (struct ip_header));
|
||||
+ udp->udp_csum = csum_finish(csum);
|
||||
+
|
||||
+ if (!udp->udp_csum) {
|
||||
+ udp->udp_csum = htons(0xffff);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+netdev_nsh_pop_header_spec(struct dp_packet *packet,
|
||||
+ const struct ovs_action_pop_tnl *data)
|
||||
+{
|
||||
+ if (data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_VXLAN_GPE_NSH) {
|
||||
+ return eth_nsh_extract_md_convert_to_vxlan_gpe_nsh(packet, data);
|
||||
+ } else if (data->pop_type == OVS_POP_SPEC_ACTION_NO_DECAP) {
|
||||
+ return eth_nsh_extract_md_no_decap(packet);
|
||||
}
|
||||
|
||||
return EINVAL;
|
||||
diff --git a/lib/odp-util.c b/lib/odp-util.c
|
||||
index a87b3be..183844f 100644
|
||||
--- a/lib/odp-util.c
|
||||
+++ b/lib/odp-util.c
|
||||
@@ -515,7 +515,7 @@ format_odp_tnl_push_header(struct ds *ds, struct ovs_action_push_tnl *data)
|
||||
gnh->oam ? "oam," : "",
|
||||
gnh->critical ? "crit," : "",
|
||||
ntohl(get_16aligned_be32(&gnh->vni)) >> 8);
|
||||
-
|
||||
+
|
||||
if (gnh->opt_len) {
|
||||
ds_put_cstr(ds, ",options(");
|
||||
format_geneve_opts(gnh->options, NULL, gnh->opt_len * 4,
|
||||
@@ -579,10 +579,11 @@ static void
|
||||
format_odp_tnl_pop_header(struct ds *ds, struct ovs_action_pop_tnl *data)
|
||||
{
|
||||
const struct eth_header *eth;
|
||||
+ const struct ip_header *ip;
|
||||
+ const void *l3;
|
||||
|
||||
eth = (const struct eth_header *)data->header;
|
||||
if (data->tnl_type == OVS_VPORT_TYPE_NSH) {
|
||||
- const struct nshhdr *nsh = (const struct nshhdr *) (eth + 1);
|
||||
|
||||
/* Ethernet */
|
||||
ds_put_format(ds, "header(size=%"PRIu8",type=%"PRIu8",eth(dst=",
|
||||
@@ -591,7 +592,37 @@ format_odp_tnl_pop_header(struct ds *ds, struct ovs_action_pop_tnl *data)
|
||||
ds_put_format(ds, ",src=");
|
||||
ds_put_format(ds, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_src));
|
||||
ds_put_format(ds, ",dl_type=0x%04"PRIx16")", ntohs(eth->eth_type));
|
||||
- ds_put_format(ds, "),");
|
||||
+ ds_put_format(ds, "),");
|
||||
+ } else if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) {
|
||||
+ l3 = eth + 1;
|
||||
+ ip = (const struct ip_header *)l3;
|
||||
+
|
||||
+ /* Ethernet */
|
||||
+ ds_put_format(ds, "header(size=%"PRIu8",type=%"PRIu8",eth(dst=",
|
||||
+ data->header_len, data->tnl_type);
|
||||
+ ds_put_format(ds, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_dst));
|
||||
+ ds_put_format(ds, ",src=");
|
||||
+ ds_put_format(ds, ETH_ADDR_FMT, ETH_ADDR_ARGS(eth->eth_src));
|
||||
+ ds_put_format(ds, ",dl_type=0x%04"PRIx16"),", ntohs(eth->eth_type));
|
||||
+
|
||||
+ /* IPv4 */
|
||||
+ ds_put_format(ds, "ipv4(src="IP_FMT",dst="IP_FMT",proto=%"PRIu8
|
||||
+ ",tos=%#"PRIx8",ttl=%"PRIu8",frag=0x%"PRIx16"),",
|
||||
+ IP_ARGS(get_16aligned_be32(&ip->ip_src)),
|
||||
+ IP_ARGS(get_16aligned_be32(&ip->ip_dst)),
|
||||
+ ip->ip_proto, ip->ip_tos,
|
||||
+ ip->ip_ttl,
|
||||
+ ip->ip_frag_off);
|
||||
+ if (data->tnl_type == OVS_VPORT_TYPE_VXLAN) {
|
||||
+ const struct vxlanhdr *vxh;
|
||||
+
|
||||
+ vxh = format_udp_tnl_push_header(ds, ip);
|
||||
+
|
||||
+ ds_put_format(ds, "vxlan(flags=0x%"PRIx32",vni=0x%"PRIx32")",
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_flags)),
|
||||
+ ntohl(get_16aligned_be32(&vxh->vx_vni)) >> 8);
|
||||
+ }
|
||||
+ ds_put_format(ds, "),");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,9 +646,10 @@ format_odp_tnl_pop_spec_action(struct ds *ds, const struct nlattr *attr)
|
||||
data = (struct ovs_action_pop_tnl *) nl_attr_get(attr);
|
||||
|
||||
ds_put_format(ds, "tnl_pop_spec(tnl_port(%"PRIu32"),", data->tnl_port);
|
||||
- if (data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH) {
|
||||
+ if (data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH ||
|
||||
+ data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_VXLAN_GPE_NSH) {
|
||||
ds_put_format(ds, "pop_type=%"PRIu16",",
|
||||
- OVS_POP_SPEC_ACTION_CONVERT_TO_ETH_NSH);
|
||||
+ data->pop_type);
|
||||
format_odp_tnl_pop_header(ds, data);
|
||||
ds_put_format(ds, "out_port(%"PRIu32"))", data->out_port);
|
||||
|
||||
@@ -1174,6 +1206,85 @@ ovs_parse_tnl_pop_spec(const char *s, struct ovs_action_pop_tnl *data)
|
||||
if (!ovs_scan_len(s, &n, ",out_port(%"SCNi32"))", &data->out_port)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
+ } else if (data->pop_type == OVS_POP_SPEC_ACTION_CONVERT_TO_VXLAN_GPE_NSH) {
|
||||
+ struct eth_header *eth;
|
||||
+ struct ip_header *ip;
|
||||
+ struct udp_header *udp;
|
||||
+ uint16_t dl_type, udp_src, udp_dst, csum;
|
||||
+ ovs_be32 sip, dip;
|
||||
+ uint32_t tnl_type = 0, header_len = 0;
|
||||
+ void *l3, *l4;
|
||||
+ int n = 0;
|
||||
+
|
||||
+ eth = (struct eth_header *) data->header;
|
||||
+ l3 = (data->header + sizeof *eth);
|
||||
+ l4 = ((uint8_t *) l3 + sizeof (struct ip_header));
|
||||
+ ip = (struct ip_header *) l3;
|
||||
+ if (!ovs_scan_len(s, &n, "header(size=%"SCNi32",type=%"SCNi32","
|
||||
+ "eth(dst="ETH_ADDR_SCAN_FMT",",
|
||||
+ &data->header_len,
|
||||
+ &data->tnl_type,
|
||||
+ ETH_ADDR_SCAN_ARGS(eth->eth_dst))) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ if (!ovs_scan_len(s, &n, "src="ETH_ADDR_SCAN_FMT",",
|
||||
+ ETH_ADDR_SCAN_ARGS(eth->eth_src))) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (!ovs_scan_len(s, &n, "dl_type=0x%"SCNx16"),", &dl_type)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ eth->eth_type = htons(dl_type);
|
||||
+
|
||||
+ /* IPv4 */
|
||||
+ if (!ovs_scan_len(s, &n, "ipv4(src="IP_SCAN_FMT",dst="IP_SCAN_FMT",proto=%"SCNi8
|
||||
+ ",tos=%"SCNi8",ttl=%"SCNi8",frag=0x%"SCNx16"),",
|
||||
+ IP_SCAN_ARGS(&sip),
|
||||
+ IP_SCAN_ARGS(&dip),
|
||||
+ &ip->ip_proto, &ip->ip_tos,
|
||||
+ &ip->ip_ttl, &ip->ip_frag_off)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ put_16aligned_be32(&ip->ip_src, sip);
|
||||
+ put_16aligned_be32(&ip->ip_dst, dip);
|
||||
+
|
||||
+ /* Tunnel header */
|
||||
+ udp = (struct udp_header *) l4;
|
||||
+ if (ovs_scan_len(s, &n, "udp(src=%"SCNi16",dst=%"SCNi16",csum=0x%"SCNx16"),",
|
||||
+ &udp_src, &udp_dst, &csum)) {
|
||||
+ uint32_t vx_flags, vni;
|
||||
+
|
||||
+ udp->udp_src = htons(udp_src);
|
||||
+ udp->udp_dst = htons(udp_dst);
|
||||
+ udp->udp_len = 0;
|
||||
+ udp->udp_csum = htons(csum);
|
||||
+
|
||||
+ if (ovs_scan_len(s, &n, "vxlan(flags=0x%"SCNx32",vni=0x%"SCNx32"))",
|
||||
+ &vx_flags, &vni)) {
|
||||
+ struct vxlanhdr *vxh = (struct vxlanhdr *) (udp + 1);
|
||||
+
|
||||
+ put_16aligned_be32(&vxh->vx_flags, htonl(vx_flags));
|
||||
+ put_16aligned_be32(&vxh->vx_vni, htonl(vni << 8));
|
||||
+ tnl_type = OVS_VPORT_TYPE_VXLAN;
|
||||
+ header_len = sizeof *eth + sizeof *ip +
|
||||
+ sizeof *udp + sizeof *vxh;
|
||||
+ } else {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ /* check tunnel meta data. */
|
||||
+ if (data->tnl_type != tnl_type) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ if (data->header_len != header_len) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ /* Out port */
|
||||
+ if (!ovs_scan_len(s, &n, ",out_port(%"SCNi32"))", &data->out_port)) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c
|
||||
index 90b5a95..1578a0c 100644
|
||||
--- a/ofproto/ofproto-dpif-xlate.c
|
||||
+++ b/ofproto/ofproto-dpif-xlate.c
|
||||
@@ -2653,7 +2653,7 @@ process_special(struct xlate_ctx *ctx, const struct xport *xport)
|
||||
}
|
||||
|
||||
static int
|
||||
-tnl_route_lookup_flow(const struct flow *oflow,
|
||||
+tnl_route_lookup_flow__(ovs_be32 ip_dst,
|
||||
ovs_be32 *ip, struct xport **out_port)
|
||||
{
|
||||
char out_dev[IFNAMSIZ];
|
||||
@@ -2661,14 +2661,14 @@ tnl_route_lookup_flow(const struct flow *oflow,
|
||||
struct xlate_cfg *xcfg;
|
||||
ovs_be32 gw;
|
||||
|
||||
- if (!ovs_router_lookup(oflow->tunnel.ip_dst, out_dev, &gw)) {
|
||||
+ if (!ovs_router_lookup(ip_dst, out_dev, &gw)) {
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
if (gw) {
|
||||
*ip = gw;
|
||||
} else {
|
||||
- *ip = oflow->tunnel.ip_dst;
|
||||
+ *ip = ip_dst;
|
||||
}
|
||||
|
||||
xcfg = ovsrcu_get(struct xlate_cfg *, &xcfgp);
|
||||
@@ -2690,6 +2690,12 @@ tnl_route_lookup_flow(const struct flow *oflow,
|
||||
}
|
||||
|
||||
static int
|
||||
+tnl_route_lookup_flow(const struct flow *oflow,
|
||||
+ ovs_be32 *ip, struct xport **out_port){
|
||||
+ return tnl_route_lookup_flow__(oflow->tunnel.ip_dst, ip, out_port);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
tnl_outdev_lookup_mac(const struct eth_addr *mac,
|
||||
struct xport **out_port)
|
||||
{
|
||||
@@ -2818,6 +2824,100 @@ build_tunnel_send(struct xlate_ctx *ctx, const struct xport *xport,
|
||||
}
|
||||
|
||||
static int
|
||||
+build_eth_nsh_tunnel_pop(struct xlate_ctx *ctx, odp_port_t tunnel_odp_port, struct flow *flow)
|
||||
+{
|
||||
+ const struct netdev_tunnel_config * cfg;
|
||||
+
|
||||
+ cfg = tnl_port_cfg(tunnel_odp_port, flow);
|
||||
+
|
||||
+ if (cfg) {
|
||||
+ if (cfg->nsh_convert && (ntohs(cfg->dst_port) == VXGPE_DST_PORT)) {
|
||||
+
|
||||
+ struct ovs_action_pop_tnl tnl_pop_data;
|
||||
+ struct xport *out_dev = NULL;
|
||||
+ ovs_be32 s_ip, d_ip = 0;
|
||||
+ struct eth_addr smac;
|
||||
+ struct eth_addr dmac;
|
||||
+ int err;
|
||||
+
|
||||
+ err = tnl_route_lookup_flow__(cfg->ip_dst, &d_ip, &out_dev);
|
||||
+ if (err) {
|
||||
+ xlate_report(ctx, "native tunnel routing failed");
|
||||
+ return err;
|
||||
+ }
|
||||
+ xlate_report(ctx, "tunneling to "IP_FMT" via %s",
|
||||
+ IP_ARGS(d_ip), netdev_get_name(out_dev->netdev));
|
||||
+
|
||||
+ /* Use mac addr of bridge port of the peer. */
|
||||
+ err = netdev_get_etheraddr(out_dev->netdev, &smac);
|
||||
+ if (err) {
|
||||
+ xlate_report(ctx, "tunnel output device lacks Ethernet address");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = netdev_get_in4(out_dev->netdev, (struct in_addr *) &s_ip, NULL);
|
||||
+ if (err) {
|
||||
+ xlate_report(ctx, "tunnel output device lacks IPv4 address");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = tnl_arp_lookup(out_dev->xbridge->name, d_ip, &dmac);
|
||||
+ if (err) {
|
||||
+ xlate_report(ctx, "ARP cache miss for "IP_FMT" on bridge %s, "
|
||||
+ "sending ARP request",
|
||||
+ IP_ARGS(d_ip), out_dev->xbridge->name);
|
||||
+ tnl_send_arp_request(ctx, out_dev, smac, s_ip, d_ip);
|
||||
+ return err;
|
||||
+ }
|
||||
+ if (ctx->xin->xcache) {
|
||||
+ struct xc_entry *entry;
|
||||
+
|
||||
+ entry = xlate_cache_add_entry(ctx->xin->xcache, XC_TNL_ARP);
|
||||
+ ovs_strlcpy(entry->u.tnl_arp_cache.br_name, out_dev->xbridge->name,
|
||||
+ sizeof entry->u.tnl_arp_cache.br_name);
|
||||
+ entry->u.tnl_arp_cache.d_ip = d_ip;
|
||||
+ }
|
||||
+
|
||||
+ xlate_report(ctx, "tunneling from "ETH_ADDR_FMT" "IP_FMT
|
||||
+ " to "ETH_ADDR_FMT" "IP_FMT,
|
||||
+ ETH_ADDR_ARGS(smac), IP_ARGS(s_ip),
|
||||
+ ETH_ADDR_ARGS(dmac), IP_ARGS(d_ip));
|
||||
+ err = tnl_port_build_header_odport_popspec(tunnel_odp_port, cfg,
|
||||
+ dmac, smac, s_ip, &tnl_pop_data);
|
||||
+ if (err) {
|
||||
+ return err;
|
||||
+ }
|
||||
+ tnl_pop_data.tnl_port = odp_to_u32(tunnel_odp_port);
|
||||
+ tnl_pop_data.out_port = odp_to_u32(out_dev->odp_port);
|
||||
+ tnl_pop_data.tnl_type = OVS_VPORT_TYPE_VXLAN;
|
||||
+ tnl_pop_data.pop_type = OVS_POP_SPEC_ACTION_CONVERT_TO_VXLAN_GPE_NSH;
|
||||
+ odp_put_tnl_pop_spec_action(ctx->odp_actions, &tnl_pop_data);
|
||||
+
|
||||
+ } else if (cfg->tun_nodecap) {
|
||||
+ struct ovs_action_pop_tnl tnl_pop_data;
|
||||
+ memset(&tnl_pop_data, 0, sizeof tnl_pop_data);
|
||||
+
|
||||
+ tnl_pop_data.tnl_port = odp_to_u32(tunnel_odp_port);
|
||||
+ tnl_pop_data.pop_type = OVS_POP_SPEC_ACTION_NO_DECAP;
|
||||
+ odp_put_tnl_pop_spec_action(ctx->odp_actions, &tnl_pop_data);
|
||||
+
|
||||
+ } else {
|
||||
+ nl_msg_put_odp_port(ctx->odp_actions,
|
||||
+ OVS_ACTION_ATTR_TUNNEL_POP,
|
||||
+ tunnel_odp_port);
|
||||
+ }
|
||||
+
|
||||
+ } else {
|
||||
+ nl_msg_put_odp_port(ctx->odp_actions,
|
||||
+ OVS_ACTION_ATTR_TUNNEL_POP,
|
||||
+ tunnel_odp_port);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int
|
||||
build_tunnel_pop(const struct xlate_ctx *ctx, odp_port_t tunnel_odp_port, struct flow *flow)
|
||||
{
|
||||
const struct netdev_tunnel_config * cfg;
|
||||
@@ -3185,7 +3285,12 @@ compose_output_action__(struct xlate_ctx *ctx, ofp_port_t ofp_port,
|
||||
if (odp_tnl_port != ODPP_NONE &&
|
||||
!(flow->tunnel.nsh_flags & NSH_TNL_F_NODECAP)) {
|
||||
flow_tnl = flow->tunnel;
|
||||
- build_tunnel_pop(ctx, odp_tnl_port, flow);
|
||||
+ if(flow->dl_type == htons(ETH_TYPE_NSH)) {
|
||||
+ build_eth_nsh_tunnel_pop(ctx, odp_tnl_port, flow);
|
||||
+ }
|
||||
+ else {
|
||||
+ build_tunnel_pop(ctx, odp_tnl_port, flow);
|
||||
+ }
|
||||
flow->tunnel = flow_tnl;
|
||||
} else {
|
||||
/* Tunnel push-pop action is not compatible with
|
||||
diff --git a/ofproto/tunnel.c b/ofproto/tunnel.c
|
||||
index cc0c91a..e279e92 100644
|
||||
--- a/ofproto/tunnel.c
|
||||
+++ b/ofproto/tunnel.c
|
||||
@@ -47,6 +47,13 @@ VLOG_DEFINE_THIS_MODULE(tunnel);
|
||||
|
||||
#define ETH_NSH_HLEN (sizeof(struct eth_header) + \
|
||||
sizeof(struct nshhdr))
|
||||
+
|
||||
+#define VXNSH_HLEN (sizeof(struct eth_header) + \
|
||||
+ sizeof(struct ip_header) + \
|
||||
+ sizeof(struct udp_header) + \
|
||||
+ sizeof(struct vxgpehdr) + \
|
||||
+ sizeof(struct nshhdr))
|
||||
+
|
||||
struct tnl_match {
|
||||
ovs_be64 in_key;
|
||||
ovs_be32 in_nsp;
|
||||
@@ -1044,6 +1051,74 @@ tnl_port_get_name(const struct tnl_port *tnl_port) OVS_REQ_RDLOCK(rwlock)
|
||||
}
|
||||
|
||||
int
|
||||
+tnl_port_build_header_odport_popspec(const odp_port_t odp_port,
|
||||
+ const struct netdev_tunnel_config *cfg,
|
||||
+ const struct eth_addr dmac,
|
||||
+ const struct eth_addr smac,
|
||||
+ ovs_be32 ip_src, struct ovs_action_pop_tnl *data)
|
||||
+{
|
||||
+ struct tnl_port *tnl_port;
|
||||
+ struct eth_header *eth;
|
||||
+ struct ip_header *ip;
|
||||
+ struct udp_header *udp;
|
||||
+ void *l3;
|
||||
+
|
||||
+ fat_rwlock_rdlock(&rwlock);
|
||||
+ tnl_port = tnl_find_odp_port(odp_port);
|
||||
+ ovs_assert(tnl_port);
|
||||
+
|
||||
+ /* Build Ethernet headers. */
|
||||
+ memset(data->header, 0, sizeof data->header);
|
||||
+
|
||||
+ eth = (struct eth_header *)data->header;
|
||||
+ eth->eth_dst = dmac;
|
||||
+ eth->eth_src = smac;
|
||||
+ eth->eth_type = htons(ETH_TYPE_IP);
|
||||
+
|
||||
+ l3 = (eth + 1);
|
||||
+ ip = (struct ip_header *) l3;
|
||||
+
|
||||
+ /* Build IP header */
|
||||
+ ip->ip_ihl_ver = IP_IHL_VER(5, 4);
|
||||
+ ip->ip_tos = cfg->tos;
|
||||
+ ip->ip_ttl = cfg->ttl;
|
||||
+ ip->ip_frag_off = cfg->dont_fragment ? htons(IP_DF) : 0;
|
||||
+ put_16aligned_be32(&ip->ip_src, ip_src);
|
||||
+ put_16aligned_be32(&ip->ip_dst, cfg->ip_dst);
|
||||
+ ip->ip_proto = IPPROTO_UDP;
|
||||
+ ip->ip_csum = csum(ip, sizeof *ip);
|
||||
+
|
||||
+ /* Build UDP header */
|
||||
+ udp = (struct udp_header *) (ip + 1);
|
||||
+ udp->udp_dst = cfg->dst_port;
|
||||
+
|
||||
+ if (cfg->csum) {
|
||||
+ /* Write a value in now to mark that we should compute the checksum
|
||||
+ * later. 0xffff is handy because it is transparent to the
|
||||
+ * calculation. */
|
||||
+ udp->udp_csum = htons(0xffff);
|
||||
+ }
|
||||
+ /* Build VxLAN-GPE header */
|
||||
+ if (ntohs(udp->udp_dst) == VXGPE_DST_PORT){
|
||||
+ struct vxgpehdr *vxg = (struct vxgpehdr *) (udp + 1);
|
||||
+
|
||||
+ memset(vxg, 0, sizeof *vxg);
|
||||
+ vxg->i = 0x01;
|
||||
+ vxg->p = 0x01;
|
||||
+ vxg->ver = 0x01;
|
||||
+ vxg->proto = VXG_P_NSH;
|
||||
+ put_16aligned_be32(&vxg->vx_vni, htonl(ntohll(cfg->out_key) << 8));
|
||||
+
|
||||
+ }
|
||||
+
|
||||
+ data->header_len = VXNSH_HLEN - sizeof (struct nshhdr);
|
||||
+ data->tnl_type = OVS_VPORT_TYPE_VXLAN;
|
||||
+
|
||||
+ fat_rwlock_unlock(&rwlock);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int
|
||||
tnl_port_build_header(const struct ofport_dpif *ofport,
|
||||
const struct flow *tnl_flow,
|
||||
const struct eth_addr dmac,
|
||||
diff --git a/ofproto/tunnel.h b/ofproto/tunnel.h
|
||||
index d771476..9f2f11d 100644
|
||||
--- a/ofproto/tunnel.h
|
||||
+++ b/ofproto/tunnel.h
|
||||
@@ -55,6 +55,13 @@ tnl_port_should_receive(const struct flow *flow)
|
||||
memcmp(flow->tunnel.eth_dst.ea, ð_addr_zero, ETH_ADDR_LEN));
|
||||
}
|
||||
|
||||
+int
|
||||
+tnl_port_build_header_odport_popspec(const odp_port_t odp_port,
|
||||
+ const struct netdev_tunnel_config *cfg,
|
||||
+ const struct eth_addr dmac,
|
||||
+ const struct eth_addr smac,
|
||||
+ ovs_be32 ip_src, struct ovs_action_pop_tnl *data);
|
||||
+
|
||||
int tnl_port_build_header(const struct ofport_dpif *ofport,
|
||||
const struct flow *tnl_flow,
|
||||
const struct eth_addr dmac,
|
||||
diff --git a/tests/tunnel.at b/tests/tunnel.at
|
||||
index 1bbf5e2..c740966 100644
|
||||
--- a/tests/tunnel.at
|
||||
+++ b/tests/tunnel.at
|
||||
@@ -786,6 +786,35 @@ AT_CHECK([tail -1 stdout], [0],
|
||||
OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
AT_CLEANUP
|
||||
|
||||
+AT_SETUP([tunnel - ETHERNET - nsh_convert from Ethernet NSH to VXLAN-GPE NSH - user space])
|
||||
+OVS_VSWITCHD_START([add-port br0 p0 -- set Interface p0 type=dummy ofport_request=1 other-config:hwaddr=aa:55:aa:55:00:00])
|
||||
+AT_CHECK([ovs-vsctl add-port br0 p1 -- set interface p1 type=eth_nsh options:remote_mac=00:00:00:11:11:22 options:nsh_convert=true \
|
||||
+options:nsi=flow options:nsp=flow options:nshc1=flow options:in_key=flow options:remote_ip=1.1.1.1 options:dst_port=4790 ofport_request=2], [0])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl netdev-dummy/ip4addr br0 2.2.2.22/24], [0], [OK
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([
|
||||
+ovs-appctl ovs/route/add 1.1.1.1/24 br0
|
||||
+ovs-appctl tnl/arp/set br0 1.1.1.1 68:05:ca:30:6b:d1
|
||||
+],[0],[stdout])
|
||||
+
|
||||
+AT_CHECK([ovs-ofctl add-flow br0 "priority=16, in_port=1, action=local"])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl dpif/show | tail -n +3], [0], [dnl
|
||||
+ br0 65534/100: (dummy)
|
||||
+ p0 1/1: (dummy)
|
||||
+ p1 2/4790: (eth_nsh: dst_port=4790, in_key=flow, nsh_convert=true, nshc1=flow, nsi=flow, nsp=flow, remote_ip=1.1.1.1, remote_mac=00:00:00:11:11:22)
|
||||
+])
|
||||
+
|
||||
+AT_CHECK([ovs-appctl ofproto/trace ovs-dummy 'in_port(1),eth(src=00:00:00:11:11:22,dst=50:54:00:00:00:07),eth_type(0x894f)'], [0], [stdout])
|
||||
+AT_CHECK([tail -1 stdout], [0],
|
||||
+ [Datapath actions: tnl_pop_spec(tnl_port(4790),pop_type=1,header(size=50,type=4,eth(dst=68:05:ca:30:6b:d1,src=aa:55:aa:55:00:00,dl_type=0x0800),ipv4(src=2.2.2.22,dst=1.1.1.1,proto=17,tos=0,ttl=64,frag=0x40),udp(src=0,dst=4790,csum=0x0),vxlan(flags=0xc400004,vni=0x0)),out_port(100))
|
||||
+])
|
||||
+
|
||||
+OVS_VSWITCHD_STOP(["/The Open vSwitch kernel module is probably not loaded/d"])
|
||||
+AT_CLEANUP
|
||||
+
|
||||
AT_SETUP([tunnel - Geneve metadata])
|
||||
OVS_VSWITCHD_START([add-port br0 p1 -- set Interface p1 type=geneve \
|
||||
options:remote_ip=1.1.1.1 ofport_request=1 \
|
||||
--
|
||||
1.9.3
|
||||
|
|
@ -0,0 +1 @@
|
|||
The patches were copied from https://github.com/yyang13/ovs_nsh_patches
|
|
@ -5,26 +5,23 @@ set -eux
|
|||
BUILD_FOR=${BUILD_FOR:-ubuntu}
|
||||
DIR="$(dirname `readlink -f $0`)"
|
||||
|
||||
INCLUDE_DEPENDENCIES=${INCLUDE_DEPENDENCIES:-true}
|
||||
|
||||
function download_dependencies {
|
||||
if [ "$INCLUDE_DEPENDENCIES" = true ]
|
||||
then
|
||||
wget --content-disposition -N -i "${DIR}/ovs_package/${1}/dependencies.txt"
|
||||
fi
|
||||
}
|
||||
|
||||
function build_pkg {
|
||||
case $1 in
|
||||
ubuntu)
|
||||
pushd "${DIR}/repositories/${1}/"
|
||||
download_dependencies ${1}
|
||||
popd
|
||||
cd ${DIR}/ovs_build
|
||||
sudo docker build -t ovs_build .
|
||||
sudo docker run -v ${DIR}/repositories/ubuntu/:/deb -t ovs_build /ovs_build/build-ovs-nsh.sh
|
||||
sudo docker run -v ${DIR}/repositories/ubuntu/:/deb -t ovs_build /ovs_build/build-ovs-dpdk.sh
|
||||
sudo docker run -v ${DIR}/repositories/ubuntu/:/deb -t ovs_build /ovs_build/build-ovs-nsh-dpdk.sh
|
||||
|
||||
rm -rf ${DIR}/repositories/ubuntu; mkdir -p ${DIR}/repositories/ubuntu
|
||||
rm -rf ${DIR}/tmp/; mkdir -p ${DIR}/tmp/; chmod 777 ${DIR}/tmp
|
||||
sudo docker run -v ${DIR}/tmp:/deb -t ovs_build /ovs_build/build-ovs-dpdk.sh
|
||||
cp -r ${DIR}/tmp/*.deb ${DIR}/repositories/ubuntu
|
||||
|
||||
rm -rf ${DIR}/ovs_package/ubuntu; mkdir -p ${DIR}/ovs_package/ubuntu
|
||||
rm -rf ${DIR}/tmp/; mkdir -p ${DIR}/tmp/; chmod 777 ${DIR}/tmp
|
||||
sudo docker run -v ${DIR}/tmp:/deb -t ovs_build /ovs_build/build-ovs-nsh-dpdk.sh
|
||||
cp -r ${DIR}/tmp/*.deb ${DIR}/ovs_package/ubuntu
|
||||
|
||||
rm -rf ${DIR}/tmp/;
|
||||
;;
|
||||
*) echo "Not supported system"; exit 1;;
|
||||
esac
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -eux
|
||||
|
||||
INSTALL_HOME=/tmp/ovs-nshdpdk
|
||||
rm -rf $INSTALL_HOME; mkdir -p $INSTALL_HOME
|
||||
cd $INSTALL_HOME
|
||||
|
||||
wget -r -nd -np http://10.20.0.2:8080/plugins/fuel-plugin-ovs-0.9/repositories/ubuntu
|
||||
|
||||
if [ $1 = 'nshdpdk' ]
|
||||
then
|
||||
dpkg -i openvswitch-datapath-dkms_2.4.90.nshdpdk-1_all.deb
|
||||
dpkg -i openvswitch-common_2.4.90.nshdpdk-1_amd64.deb
|
||||
dpkg -i openvswitch-switch_2.4.90.nshdpdk-1_amd64.deb
|
||||
elif [ $1 = 'nsh' ]
|
||||
then
|
||||
dpkg -i openvswitch-datapath-dkms_2.4.90.nsh-1_all.deb
|
||||
dpkg -i openvswitch-common_2.4.90.nsh-1_amd64.deb
|
||||
dpkg -i openvswitch-switch_2.4.90.nsh-1_amd64.deb
|
||||
elif [ $1 = 'dpdk' ]
|
||||
then
|
||||
dpkg -i openvswitch-datapath-dkms_2.4.90.dpdk-1_all.deb
|
||||
dpkg -i openvswitch-common_2.4.90.dpdk-1_amd64.deb
|
||||
dpkg -i openvswitch-switch_2.4.90.dpdk-1_amd64.deb
|
||||
fi
|
|
@ -1,8 +1 @@
|
|||
- id: ovs_install_compute
|
||||
role: ['compute']
|
||||
stage: pre_deployment
|
||||
type: puppet
|
||||
parameters:
|
||||
puppet_manifest: puppet/manifests/ovs-install-compute.pp
|
||||
puppet_modules: puppet/modules:/etc/puppet/modules
|
||||
timeout: 720
|
||||
[]
|
||||
|
|
Loading…
Reference in New Issue