./PaxHeaders.69223/openvswitch-2.5.00000644000000000000000000000013212664357344013727 xustar0030 mtime=1456594660.345295209 30 atime=1456594661.701352216 30 ctime=1456594660.345295209 openvswitch-2.5.0/0000775000175000017500000000000012664357344015337 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/PaxHeaders.69223/appveyor.yml0000644000000000000000000000013212664352753016236 xustar0030 mtime=1456592363.422620179 30 atime=1456592368.170815194 30 ctime=1456594659.685267463 openvswitch-2.5.0/appveyor.yml0000664000175000017500000000271312664352753017731 0ustar00jpettitjpettit00000000000000version: 1.0.{build} branches: only: - master clone_folder: C:\openvswitch init: - ps: >- mkdir C:\pthreads-win32 mkdir C:\ovs-build-downloads $source = "ftp://sourceware.org/pub/pthreads-win32/pthreads-w32-2-9-1-release.zip" $destination = "C:\pthreads-win32\pthreads-win32.zip" Invoke-WebRequest $source -OutFile $destination $source = "https://slproweb.com/download/Win32OpenSSL-1_0_2d.exe" $destination = "C:\ovs-build-downloads\Win32OpenSSL-1_0_2d.exe" Invoke-WebRequest $source -OutFile $destination cd C:\pthreads-win32 7z x C:\pthreads-win32\pthreads-win32.zip cd C:\ovs-build-downloads .\Win32OpenSSL-1_0_2d.exe /silent /verysilent /sp- /suppressmsgboxes Start-Sleep -s 30 cd C:\openvswitch build_script: - '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\VsDevCmd"' - C:\MinGW\msys\1.0\bin\bash -lc "echo \"C:/MinGW /mingw\" > /etc/fstab" - C:\MinGW\msys\1.0\bin\bash -lc "cp /c/pthreads-win32/Pre-built.2/dll/x86/*.dll /c/openvswitch/." - C:\MinGW\msys\1.0\bin\bash -lc "mv /bin/link.exe /bin/link_copy.exe" - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./boot.sh" - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && ./configure CC=build-aux/cccl LD=\"`which link`\" LIBS=\"-lws2_32 -liphlpapi\" --with-pthread=C:/pthreads-win32/Pre-built.2 --with-openssl=C:/OpenSSL-Win32 --with-vstudiotarget=\"Debug\"" - C:\MinGW\msys\1.0\bin\bash -lc "cd /c/openvswitch && make" openvswitch-2.5.0/PaxHeaders.69223/include0000644000000000000000000000013212664357343015214 xustar0030 mtime=1456594659.573262755 30 atime=1456594661.701352216 30 ctime=1456594659.573262755 openvswitch-2.5.0/include/0000775000175000017500000000000012664357343016761 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/PaxHeaders.69223/windows0000644000000000000000000000012612664357344016712 xustar0028 mtime=1456594660.3212942 30 atime=1456594661.701352216 28 ctime=1456594660.3212942 openvswitch-2.5.0/include/windows/0000775000175000017500000000000012664357344020454 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/PaxHeaders.69223/windefs.h0000644000000000000000000000013012631676263020570 xustar0030 mtime=1449622707.158445935 30 atime=1456592667.343091717 28 ctime=1456594660.3212942 openvswitch-2.5.0/include/windows/windefs.h0000664000175000017500000000225312631676263022264 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef WINDEFS_H #define WINDEFS_H 1 #include #include #include #include #include #include #include #pragma comment(lib, "advapi32") #undef INET6_ADDRSTRLEN #define INET6_ADDRSTRLEN 46 #define inline __inline #define __func__ __FUNCTION__ #define ssize_t SSIZE_T #define u_int8_t uint8_t #define u_int16_t uint16_t #define u_int32_t uint32_t #define u_int64_t uint64_t typedef int pid_t; char *strsep(char **stringp, const char *delim); #define srandom srand #define random rand #endif /* windefs.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/dirent.h0000644000000000000000000000013112631676263020417 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.293293024 openvswitch-2.5.0/include/windows/dirent.h0000664000175000017500000000000012631676263022076 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/PaxHeaders.69223/poll.h0000644000000000000000000000013112631676263020100 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.309293697 openvswitch-2.5.0/include/windows/poll.h0000664000175000017500000000000012631676263021557 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/PaxHeaders.69223/sys0000644000000000000000000000012612664357344017530 xustar0028 mtime=1456594660.3212942 30 atime=1456594661.701352216 28 ctime=1456594660.3212942 openvswitch-2.5.0/include/windows/sys/0000775000175000017500000000000012664357344021272 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/epoll.h0000644000000000000000000000013212631676263021064 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 30 ctime=1456594660.313293864 openvswitch-2.5.0/include/windows/sys/epoll.h0000664000175000017500000000146212631676263022557 0ustar00jpettitjpettit00000000000000/* * Copyright 2014 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __SYS_EPOLL_H #define __SYS_EPOLL_H 1 #define EPOLLIN 0x00001 typedef union data { uint32_t u32; } data_t; struct epoll_event { uint32_t events; data_t data; }; #endif /* sys/epoll.h */ openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/wait.h0000644000000000000000000000012712631676263020721 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 28 ctime=1456594660.3212942 openvswitch-2.5.0/include/windows/sys/wait.h0000664000175000017500000000000012631676263022373 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/resource.h0000644000000000000000000000013212631676263021600 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 30 ctime=1456594660.313293864 openvswitch-2.5.0/include/windows/sys/resource.h0000664000175000017500000000341212631676263023270 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef SYS_RESOURCE_H #define SYS_RESOURCE_H 1 struct rusage { struct timeval ru_utime; /* user CPU time used */ struct timeval ru_stime; /* system CPU time used */ long ru_maxrss; /* maximum resident set size */ long ru_ixrss; /* integral shared memory size */ long ru_idrss; /* integral unshared data size */ long ru_isrss; /* integral unshared stack size */ long ru_minflt; /* page reclaims (soft page faults) */ long ru_majflt; /* page faults (hard page faults) */ long ru_nswap; /* swaps */ long ru_inblock; /* block input operations */ long ru_oublock; /* block output operations */ long ru_msgsnd; /* IPC messages sent */ long ru_msgrcv; /* IPC messages received */ long ru_nsignals; /* signals received */ long ru_nvcsw; /* voluntary context switches */ long ru_nivcsw; /* involuntary context switches */ }; #ifndef RUSAGE_SELF #define RUSAGE_SELF 1 #endif #ifndef RUSAGE_CHILDREN #define RUSAGE_CHILDREN 2 #endif #ifndef RUSAGE_THREAD #define RUSAGE_THREAD 3 #endif #endif /* sys/resource.h */ openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/socket.h0000644000000000000000000000013212631676263021241 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 30 ctime=1456594660.317294032 openvswitch-2.5.0/include/windows/sys/socket.h0000664000175000017500000000131612631676263022732 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __SYS_SOCKET_H #define __SYS_SOCKET_H 1 typedef unsigned short int sa_family_t; #endif /* sys/socket.h */ openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/un.h0000644000000000000000000000013112631676263020372 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.317294032 openvswitch-2.5.0/include/windows/sys/un.h0000664000175000017500000000000012631676263022051 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/ioctl.h0000644000000000000000000000013112631676263021062 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.313293864 openvswitch-2.5.0/include/windows/sys/ioctl.h0000664000175000017500000000000012631676263022541 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/time.h0000644000000000000000000000013112631676263020706 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.317294032 openvswitch-2.5.0/include/windows/sys/time.h0000664000175000017500000000000012631676263022365 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/sys/PaxHeaders.69223/uio.h0000644000000000000000000000013212631676263020545 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.347091881 30 ctime=1456594660.317294032 openvswitch-2.5.0/include/windows/sys/uio.h0000664000175000017500000000130112631676263022230 0ustar00jpettitjpettit00000000000000/* * Copyright 2014 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __SYS_UIO_H #define __SYS_UIO_H 1 #include #endif /* sys/uio.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/syslog.h0000644000000000000000000000013212631676263020453 xustar0030 mtime=1449622707.158445935 30 atime=1456592667.343091717 30 ctime=1456594660.313293864 openvswitch-2.5.0/include/windows/syslog.h0000664000175000017500000000474112631676263022151 0ustar00jpettitjpettit00000000000000/* * Copyright 2013, 2015 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License.You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the * License for the specific language governing permissions and limitations * under the License. */ #ifndef SYSLOG_H #define SYSLOG_H 1 #define LOG_EMERG 0 /* system is unusable */ #define LOG_ALERT 1 /* action must be taken immediately */ #define LOG_CRIT 2 /* critical conditions */ #define LOG_ERR 3 /* error conditions */ #define LOG_WARNING 4 /* warning conditions */ #define LOG_NOTICE 5 /* normal but significant condition */ #define LOG_INFO 6 /* informational */ #define LOG_DEBUG 7 /* debug-level messages */ #define LOG_NDELAY 8 /* don't delay open */ #define LOG_KERN (0<<3) /* kernel messages */ #define LOG_USER (1<<3) /* user-level messages */ #define LOG_MAIL (2<<3) /* mail system */ #define LOG_DAEMON (3<<3) /* system daemons */ #define LOG_AUTH (4<<3) /* security/authorization messages */ #define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */ #define LOG_LPR (6<<3) /* line printer subsystem */ #define LOG_NEWS (7<<3) /* network news subsystem */ #define LOG_UUCP (8<<3) /* UUCP subsystem */ #define LOG_CRON (9<<3) /* clock daemon */ #define LOG_AUTHPRIV (10<<3) /* security/authorization messages */ #define LOG_FTP (11<<3) /* FTP daemon */ #define LOG_LOCAL0 (16<<3) /* reserved for local use */ #define LOG_LOCAL1 (17<<3) /* reserved for local use */ #define LOG_LOCAL2 (18<<3) /* reserved for local use */ #define LOG_LOCAL3 (19<<3) /* reserved for local use */ #define LOG_LOCAL4 (20<<3) /* reserved for local use */ #define LOG_LOCAL5 (21<<3) /* reserved for local use */ #define LOG_LOCAL6 (22<<3) /* reserved for local use */ #define LOG_LOCAL7 (23<<3) /* reserved for local use */ static inline void openlog(const char *ident, int option, int facility) { } static inline void syslog(int priority, const char *format, ...) { } #endif /* syslog.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/arpa0000644000000000000000000000013212664357344017632 xustar0030 mtime=1456594660.293293024 30 atime=1456594661.701352216 30 ctime=1456594660.293293024 openvswitch-2.5.0/include/windows/arpa/0000775000175000017500000000000012664357344021377 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/arpa/PaxHeaders.69223/inet.h0000644000000000000000000000013112631676263021014 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.293293024 openvswitch-2.5.0/include/windows/arpa/inet.h0000664000175000017500000000000012631676263022473 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/PaxHeaders.69223/unistd.h0000644000000000000000000000013012631676263020437 xustar0030 mtime=1449622707.158445935 30 atime=1456592667.343091717 28 ctime=1456594660.3212942 openvswitch-2.5.0/include/windows/unistd.h0000664000175000017500000000371412631676263022136 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef _UNISTD_H #define _UNISTD_H 1 #define WIN32_LEAN_AND_MEAN #include #define fsync _commit /* Standard file descriptors. */ #define STDIN_FILENO 0 /* Standard input. */ #define STDOUT_FILENO 1 /* Standard output. */ #define STDERR_FILENO 2 /* Standard error output. */ #define _SC_UIO_MAXIOV 2 #define _XOPEN_IOV_MAX 16 #define _SC_PAGESIZE 0x1 #define _SC_NPROCESSORS_ONLN 0x2 #define _SC_PHYS_PAGES 0x4 __inline int GetNumLogicalProcessors(void) { SYSTEM_INFO info_temp; GetSystemInfo(&info_temp); long int n_cores = info_temp.dwNumberOfProcessors; return n_cores; } __inline long sysconf(int type) { long value = -1; long page_size = -1; SYSTEM_INFO sys_info; MEMORYSTATUSEX status; switch (type) { case _SC_NPROCESSORS_ONLN: value = GetNumLogicalProcessors(); break; case _SC_PAGESIZE: GetSystemInfo(&sys_info); value = sys_info.dwPageSize; break; case _SC_PHYS_PAGES: status.dwLength = sizeof(status); page_size = sysconf(_SC_PAGESIZE); if (GlobalMemoryStatusEx(&status) && page_size != -1) { value = status.ullTotalPhys / page_size; } break; default: break; } return value; } #endif /* unistd.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/getopt.h0000644000000000000000000000013212631676263020435 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.331091225 30 ctime=1456594660.297293191 openvswitch-2.5.0/include/windows/getopt.h0000664000175000017500000000425512631676263022133 0ustar00jpettitjpettit00000000000000/*- * Copyright (c) 2000 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Dieter Baron and Thomas Klausner. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef _GETOPT_H_ #define _GETOPT_H_ #include extern char *optarg; extern int optind; /* * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions */ #define no_argument 0 #define required_argument 1 #define optional_argument 2 struct option { /* name of long option */ const char *name; /* * one of no_argument, required_argument, and optional_argument: * whether option takes an argument */ int has_arg; /* if not NULL, set *flag to val when option found */ int *flag; /* if flag not NULL, value to set *flag to; else return value */ int val; }; int getopt_long(int, char * const *, const char *, const struct option *, int *); #endif /* !_GETOPT_H_ */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/netpacket0000644000000000000000000000013012664357344020663 xustar0029 mtime=1456594660.30129336 30 atime=1456594661.701352216 29 ctime=1456594660.30129336 openvswitch-2.5.0/include/windows/netpacket/0000775000175000017500000000000012664357344022432 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/netpacket/PaxHeaders.69223/packet.h0000644000000000000000000000013112631676263022357 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 29 ctime=1456594660.30129336 openvswitch-2.5.0/include/windows/netpacket/packet.h0000664000175000017500000000167712631676263024063 0ustar00jpettitjpettit00000000000000/* * Copyright 2014 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NETPACKET_PACKET_H #define __NETPACKET_PACKET_H 1 struct iovec { void *iov_base; unsigned int iov_len; }; struct msghdr { void *msg_name; socklen_t msg_namelen; struct iovec *msg_iov; size_t msg_iovlen; void *msg_control; size_t msg_controllen; int msg_flags; }; #endif /* netpacket/packet.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/netdb.h0000644000000000000000000000013012631676263020225 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 29 ctime=1456594660.30129336 openvswitch-2.5.0/include/windows/netdb.h0000664000175000017500000000000012631676263021705 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/PaxHeaders.69223/strings.h0000644000000000000000000000013112631676263020623 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.309293697 openvswitch-2.5.0/include/windows/strings.h0000664000175000017500000000000012631676263022302 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/PaxHeaders.69223/netinet0000644000000000000000000000013212664357344020355 xustar0030 mtime=1456594660.309293697 30 atime=1456594661.701352216 30 ctime=1456594660.309293697 openvswitch-2.5.0/include/windows/netinet/0000775000175000017500000000000012664357344022122 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/netinet/PaxHeaders.69223/ip.h0000644000000000000000000000013212631676263021211 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 30 ctime=1456594660.305293529 openvswitch-2.5.0/include/windows/netinet/ip.h0000664000175000017500000000153412631676263022704 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NETINET_IP_H #define __NETINET_IP_H 1 #define IPTOS_PREC_INTERNETCONTROL 0xc0 #define MAXTTL 255 #define IPTOS_LOWDELAY 0x10 #define IPTOS_THROUGHPUT 0x08 #define IP_DF 0x4000 /* dont fragment flag */ #endif /* netinet/ip.h */ openvswitch-2.5.0/include/windows/netinet/PaxHeaders.69223/in_systm.h0000644000000000000000000000013112631676263022445 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.305293529 openvswitch-2.5.0/include/windows/netinet/in_systm.h0000664000175000017500000000000012631676263024124 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/netinet/PaxHeaders.69223/icmp6.h0000644000000000000000000000013112631676263021616 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 29 ctime=1456594660.30129336 openvswitch-2.5.0/include/windows/netinet/icmp6.h0000664000175000017500000005201612631676263023313 0ustar00jpettitjpettit00000000000000/* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip_icmp.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_ICMP6_H_ #define _NETINET_ICMP6_H_ #include "byte-order.h" #define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr) - sizeof(struct icmp6_hdr) */ struct icmp6_hdr { u_int8_t icmp6_type; /* type field */ u_int8_t icmp6_code; /* code field */ u_int16_t icmp6_cksum; /* checksum field */ union { u_int32_t icmp6_un_data32[1]; /* type-specific field */ u_int16_t icmp6_un_data16[2]; /* type-specific field */ u_int8_t icmp6_un_data8[4]; /* type-specific field */ } icmp6_dataun; }; #define icmp6_data32 icmp6_dataun.icmp6_un_data32 #define icmp6_data16 icmp6_dataun.icmp6_un_data16 #define icmp6_data8 icmp6_dataun.icmp6_un_data8 #define icmp6_pptr icmp6_data32[0] /* parameter prob */ #define icmp6_mtu icmp6_data32[0] /* packet too big */ #define icmp6_id icmp6_data16[0] /* echo request/reply */ #define icmp6_seq icmp6_data16[1] /* echo request/reply */ #define icmp6_maxdelay icmp6_data16[0] /* mcast group membership */ #define ICMP6_DST_UNREACH 1 /* dest unreachable, codes: */ #define ICMP6_PACKET_TOO_BIG 2 /* packet too big */ #define ICMP6_TIME_EXCEEDED 3 /* time exceeded, code: */ #define ICMP6_PARAM_PROB 4 /* ip6 header bad */ #define ICMP6_ECHO_REQUEST 128 /* echo service */ #define ICMP6_ECHO_REPLY 129 /* echo reply */ #define MLD_LISTENER_QUERY 130 /* multicast listener query */ #define MLD_LISTENER_REPORT 131 /* multicast listener report */ #define MLD_LISTENER_DONE 132 /* multicast listener done */ #define MLD_LISTENER_REDUCTION MLD_LISTENER_DONE /* RFC3542 definition */ /* RFC2292 decls */ #define ICMP6_MEMBERSHIP_QUERY 130 /* group membership query */ #define ICMP6_MEMBERSHIP_REPORT 131 /* group membership report */ #define ICMP6_MEMBERSHIP_REDUCTION 132 /* group membership termination */ /* the followings are for backward compatibility to old KAME apps. */ #define MLD6_LISTENER_QUERY MLD_LISTENER_QUERY #define MLD6_LISTENER_REPORT MLD_LISTENER_REPORT #define MLD6_LISTENER_DONE MLD_LISTENER_DONE #define ND_ROUTER_SOLICIT 133 /* router solicitation */ #define ND_ROUTER_ADVERT 134 /* router advertisement */ #define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */ #define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisement */ #define ND_REDIRECT 137 /* redirect */ #define ICMP6_ROUTER_RENUMBERING 138 /* router renumbering */ #define ICMP6_WRUREQUEST 139 /* who are you request */ #define ICMP6_WRUREPLY 140 /* who are you reply */ #define ICMP6_FQDN_QUERY 139 /* FQDN query */ #define ICMP6_FQDN_REPLY 140 /* FQDN reply */ #define ICMP6_NI_QUERY 139 /* node information request */ #define ICMP6_NI_REPLY 140 /* node information reply */ #define MLDV2_LISTENER_REPORT 143 /* RFC3810 listener report */ /* The definitions below are experimental. TBA */ #define MLD_MTRACE_RESP 200 /* mtrace response(to sender) */ #define MLD_MTRACE 201 /* mtrace messages */ /* the followings are for backward compatibility to old KAME apps. */ #define MLD6_MTRACE_RESP MLD_MTRACE_RESP #define MLD6_MTRACE MLD_MTRACE #define ICMP6_MAXTYPE 201 #define ICMP6_DST_UNREACH_NOROUTE 0 /* no route to destination */ #define ICMP6_DST_UNREACH_ADMIN 1 /* administratively prohibited */ #define ICMP6_DST_UNREACH_NOTNEIGHBOR 2 /* not a neighbor(obsolete) */ #define ICMP6_DST_UNREACH_BEYONDSCOPE 2 /* beyond scope of source address */ #define ICMP6_DST_UNREACH_ADDR 3 /* address unreachable */ #define ICMP6_DST_UNREACH_NOPORT 4 /* port unreachable */ #define ICMP6_DST_UNREACH_POLICY 5 /* source address failed ingress/egress policy */ #define ICMP6_DST_UNREACH_REJROUTE 6 /* reject route to destination */ #define ICMP6_DST_UNREACH_SOURCERT 7 /* error in source routing header */ #define ICMP6_TIME_EXCEED_TRANSIT 0 /* ttl==0 in transit */ #define ICMP6_TIME_EXCEED_REASSEMBLY 1 /* ttl==0 in reass */ #define ICMP6_PARAMPROB_HEADER 0 /* erroneous header field */ #define ICMP6_PARAMPROB_NEXTHEADER 1 /* unrecognized next header */ #define ICMP6_PARAMPROB_OPTION 2 /* unrecognized option */ #define ICMP6_INFOMSG_MASK 0x80 /* all informational messages */ #define ICMP6_NI_SUBJ_IPV6 0 /* Query Subject is an IPv6 address */ #define ICMP6_NI_SUBJ_FQDN 1 /* Query Subject is a Domain name */ #define ICMP6_NI_SUBJ_IPV4 2 /* Query Subject is an IPv4 address */ #define ICMP6_NI_SUCCESS 0 /* node information successful reply */ #define ICMP6_NI_REFUSED 1 /* node information request is refused */ #define ICMP6_NI_UNKNOWN 2 /* unknown Qtype */ #define ICMP6_ROUTER_RENUMBERING_COMMAND 0 /* rr command */ #define ICMP6_ROUTER_RENUMBERING_RESULT 1 /* rr result */ #define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET 255 /* rr seq num reset */ /* Used in kernel only */ #define ND_REDIRECT_ONLINK 0 /* redirect to an on-link node */ #define ND_REDIRECT_ROUTER 1 /* redirect to a better router */ /* * Multicast Listener Discovery */ struct mld_hdr { struct icmp6_hdr mld_icmp6_hdr; struct in6_addr mld_addr; /* multicast address */ }; /* definitions to provide backward compatibility to old KAME applications */ #define mld6_hdr mld_hdr #define mld6_type mld_type #define mld6_code mld_code #define mld6_cksum mld_cksum #define mld6_maxdelay mld_maxdelay #define mld6_reserved mld_reserved #define mld6_addr mld_addr /* shortcut macro definitions */ #define mld_type mld_icmp6_hdr.icmp6_type #define mld_code mld_icmp6_hdr.icmp6_code #define mld_cksum mld_icmp6_hdr.icmp6_cksum #define mld_maxdelay mld_icmp6_hdr.icmp6_data16[0] #define mld_reserved mld_icmp6_hdr.icmp6_data16[1] #define MLD_MINLEN 24 /* * Neighbor Discovery */ struct nd_router_solicit { /* router solicitation */ struct icmp6_hdr nd_rs_hdr; /* could be followed by options */ }; #define nd_rs_type nd_rs_hdr.icmp6_type #define nd_rs_code nd_rs_hdr.icmp6_code #define nd_rs_cksum nd_rs_hdr.icmp6_cksum #define nd_rs_reserved nd_rs_hdr.icmp6_data32[0] struct nd_router_advert { /* router advertisement */ struct icmp6_hdr nd_ra_hdr; u_int32_t nd_ra_reachable; /* reachable time */ u_int32_t nd_ra_retransmit; /* retransmit timer */ /* could be followed by options */ }; #define nd_ra_type nd_ra_hdr.icmp6_type #define nd_ra_code nd_ra_hdr.icmp6_code #define nd_ra_cksum nd_ra_hdr.icmp6_cksum #define nd_ra_curhoplimit nd_ra_hdr.icmp6_data8[0] #define nd_ra_flags_reserved nd_ra_hdr.icmp6_data8[1] #define ND_RA_FLAG_MANAGED 0x80 #define ND_RA_FLAG_OTHER 0x40 #define ND_RA_FLAG_HOME_AGENT 0x20 /* * Router preference values based on RFC4191. */ #define ND_RA_FLAG_RTPREF_MASK 0x18 /* 00011000 */ #define ND_RA_FLAG_RTPREF_HIGH 0x08 /* 00001000 */ #define ND_RA_FLAG_RTPREF_MEDIUM 0x00 /* 00000000 */ #define ND_RA_FLAG_RTPREF_LOW 0x18 /* 00011000 */ #define ND_RA_FLAG_RTPREF_RSV 0x10 /* 00010000 */ #define nd_ra_router_lifetime nd_ra_hdr.icmp6_data16[1] struct nd_neighbor_solicit { /* neighbor solicitation */ struct icmp6_hdr nd_ns_hdr; struct in6_addr nd_ns_target; /*target address */ /* could be followed by options */ }; #define nd_ns_type nd_ns_hdr.icmp6_type #define nd_ns_code nd_ns_hdr.icmp6_code #define nd_ns_cksum nd_ns_hdr.icmp6_cksum #define nd_ns_reserved nd_ns_hdr.icmp6_data32[0] struct nd_neighbor_advert { /* neighbor advertisement */ struct icmp6_hdr nd_na_hdr; struct in6_addr nd_na_target; /* target address */ /* could be followed by options */ }; #define nd_na_type nd_na_hdr.icmp6_type #define nd_na_code nd_na_hdr.icmp6_code #define nd_na_cksum nd_na_hdr.icmp6_cksum #define nd_na_flags_reserved nd_na_hdr.icmp6_data32[0] #define ND_NA_FLAG_ROUTER CONSTANT_HTONL(0x80000000) #define ND_NA_FLAG_SOLICITED CONSTANT_HTONL(0x40000000) #define ND_NA_FLAG_OVERRIDE CONSTANT_HTONL(0x20000000) struct nd_redirect { /* redirect */ struct icmp6_hdr nd_rd_hdr; struct in6_addr nd_rd_target; /* target address */ struct in6_addr nd_rd_dst; /* destination address */ /* could be followed by options */ }; #define nd_rd_type nd_rd_hdr.icmp6_type #define nd_rd_code nd_rd_hdr.icmp6_code #define nd_rd_cksum nd_rd_hdr.icmp6_cksum #define nd_rd_reserved nd_rd_hdr.icmp6_data32[0] struct nd_opt_hdr { /* Neighbor discovery option header */ u_int8_t nd_opt_type; u_int8_t nd_opt_len; /* followed by option specific data*/ }; #define ND_OPT_SOURCE_LINKADDR 1 #define ND_OPT_TARGET_LINKADDR 2 #define ND_OPT_PREFIX_INFORMATION 3 #define ND_OPT_REDIRECTED_HEADER 4 #define ND_OPT_MTU 5 #define ND_OPT_ADVINTERVAL 7 #define ND_OPT_HOMEAGENT_INFO 8 #define ND_OPT_SOURCE_ADDRLIST 9 #define ND_OPT_TARGET_ADDRLIST 10 #define ND_OPT_MAP 23 /* RFC 5380 */ #define ND_OPT_ROUTE_INFO 24 /* RFC 4191 */ #define ND_OPT_RDNSS 25 /* RFC 6016 */ #define ND_OPT_DNSSL 31 /* RFC 6016 */ struct nd_opt_route_info { /* route info */ u_int8_t nd_opt_rti_type; u_int8_t nd_opt_rti_len; u_int8_t nd_opt_rti_prefixlen; u_int8_t nd_opt_rti_flags; u_int32_t nd_opt_rti_lifetime; /* prefix follows */ }; struct nd_opt_prefix_info { /* prefix information */ u_int8_t nd_opt_pi_type; u_int8_t nd_opt_pi_len; u_int8_t nd_opt_pi_prefix_len; u_int8_t nd_opt_pi_flags_reserved; u_int32_t nd_opt_pi_valid_time; u_int32_t nd_opt_pi_preferred_time; u_int32_t nd_opt_pi_reserved2; struct in6_addr nd_opt_pi_prefix; }; #define ND_OPT_PI_FLAG_ONLINK 0x80 #define ND_OPT_PI_FLAG_AUTO 0x40 struct nd_opt_rd_hdr { /* redirected header */ u_int8_t nd_opt_rh_type; u_int8_t nd_opt_rh_len; u_int16_t nd_opt_rh_reserved1; u_int32_t nd_opt_rh_reserved2; /* followed by IP header and data */ }; struct nd_opt_mtu { /* MTU option */ u_int8_t nd_opt_mtu_type; u_int8_t nd_opt_mtu_len; u_int16_t nd_opt_mtu_reserved; u_int32_t nd_opt_mtu_mtu; }; struct nd_opt_rdnss { /* RDNSS option RFC 6106 */ u_int8_t nd_opt_rdnss_type; u_int8_t nd_opt_rdnss_len; u_int16_t nd_opt_rdnss_reserved; u_int32_t nd_opt_rdnss_lifetime; /* followed by list of IP prefixes */ }; struct nd_opt_dnssl { /* DNSSL option RFC 6106 */ u_int8_t nd_opt_dnssl_type; u_int8_t nd_opt_dnssl_len; u_int16_t nd_opt_dnssl_reserved; u_int32_t nd_opt_dnssl_lifetime; /* followed by list of IP prefixes */ }; /* * icmp6 namelookup */ struct icmp6_namelookup { struct icmp6_hdr icmp6_nl_hdr; u_int8_t icmp6_nl_nonce[8]; int32_t icmp6_nl_ttl; #if 0 u_int8_t icmp6_nl_len; u_int8_t icmp6_nl_name[3]; #endif /* could be followed by options */ }; /* * icmp6 node information */ struct icmp6_nodeinfo { struct icmp6_hdr icmp6_ni_hdr; u_int8_t icmp6_ni_nonce[8]; /* could be followed by reply data */ }; #define ni_type icmp6_ni_hdr.icmp6_type #define ni_code icmp6_ni_hdr.icmp6_code #define ni_cksum icmp6_ni_hdr.icmp6_cksum #define ni_qtype icmp6_ni_hdr.icmp6_data16[0] #define ni_flags icmp6_ni_hdr.icmp6_data16[1] #define NI_QTYPE_NOOP 0 /* NOOP */ #define NI_QTYPE_SUPTYPES 1 /* Supported Qtypes */ #define NI_QTYPE_FQDN 2 /* FQDN (draft 04) */ #define NI_QTYPE_DNSNAME 2 /* DNS Name */ #define NI_QTYPE_NODEADDR 3 /* Node Addresses */ #define NI_QTYPE_IPV4ADDR 4 /* IPv4 Addresses */ #define NI_SUPTYPE_FLAG_COMPRESS CONSTANT_HTONS(0x1) #define NI_FQDN_FLAG_VALIDTTL CONSTANT_HTONS(0x1) #ifdef NAME_LOOKUPS_04 #define NI_NODEADDR_FLAG_LINKLOCAL CONSTANT_HTONS(0x1) #define NI_NODEADDR_FLAG_SITELOCAL CONSTANT_HTONS(0x2) #define NI_NODEADDR_FLAG_GLOBAL CONSTANT_HTONS(0x4) #define NI_NODEADDR_FLAG_ALL CONSTANT_HTONS(0x8) #define NI_NODEADDR_FLAG_TRUNCATE CONSTANT_HTONS(0x10) #define NI_NODEADDR_FLAG_ANYCAST CONSTANT_HTONS(0x20) /* just experimental. not in spec */ #else /* draft-ietf-ipngwg-icmp-name-lookups-05 (and later?) */ #define NI_NODEADDR_FLAG_TRUNCATE CONSTANT_HTONS(0x1) #define NI_NODEADDR_FLAG_ALL CONSTANT_HTONS(0x2) #define NI_NODEADDR_FLAG_COMPAT CONSTANT_HTONS(0x4) #define NI_NODEADDR_FLAG_LINKLOCAL CONSTANT_HTONS(0x8) #define NI_NODEADDR_FLAG_SITELOCAL CONSTANT_HTONS(0x10) #define NI_NODEADDR_FLAG_GLOBAL CONSTANT_HTONS(0x20) #define NI_NODEADDR_FLAG_ANYCAST CONSTANT_HTONS(0x40) /* just experimental. not in spec */ #endif struct ni_reply_fqdn { u_int32_t ni_fqdn_ttl; /* TTL */ u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */ u_int8_t ni_fqdn_name[3]; /* XXX: alignment */ }; /* * Router Renumbering. as router-renum-08.txt */ struct icmp6_router_renum { /* router renumbering header */ struct icmp6_hdr rr_hdr; u_int8_t rr_segnum; u_int8_t rr_flags; u_int16_t rr_maxdelay; u_int32_t rr_reserved; }; #define ICMP6_RR_FLAGS_TEST 0x80 #define ICMP6_RR_FLAGS_REQRESULT 0x40 #define ICMP6_RR_FLAGS_FORCEAPPLY 0x20 #define ICMP6_RR_FLAGS_SPECSITE 0x10 #define ICMP6_RR_FLAGS_PREVDONE 0x08 #define rr_type rr_hdr.icmp6_type #define rr_code rr_hdr.icmp6_code #define rr_cksum rr_hdr.icmp6_cksum #define rr_seqnum rr_hdr.icmp6_data32[0] struct rr_pco_match { /* match prefix part */ u_int8_t rpm_code; u_int8_t rpm_len; u_int8_t rpm_ordinal; u_int8_t rpm_matchlen; u_int8_t rpm_minlen; u_int8_t rpm_maxlen; u_int16_t rpm_reserved; struct in6_addr rpm_prefix; }; #define RPM_PCO_ADD 1 #define RPM_PCO_CHANGE 2 #define RPM_PCO_SETGLOBAL 3 #define RPM_PCO_MAX 4 struct rr_pco_use { /* use prefix part */ u_int8_t rpu_uselen; u_int8_t rpu_keeplen; u_int8_t rpu_ramask; u_int8_t rpu_raflags; u_int32_t rpu_vltime; u_int32_t rpu_pltime; u_int32_t rpu_flags; struct in6_addr rpu_prefix; }; #define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK 0x80 #define ICMP6_RR_PCOUSE_RAFLAGS_AUTO 0x40 #define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME CONSTANT_HTONL(0x80000000) #define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME CONSTANT_HTONL(0x40000000) struct rr_result { /* router renumbering result message */ u_int16_t rrr_flags; u_int8_t rrr_ordinal; u_int8_t rrr_matchedlen; u_int32_t rrr_ifid; struct in6_addr rrr_prefix; }; #define ICMP6_RR_RESULT_FLAGS_OOB CONSTANT_HTONS(0x0002) #define ICMP6_RR_RESULT_FLAGS_FORBIDDEN CONSTANT_HTONS(0x0001) /* * icmp6 filter structures. */ struct icmp6_filter { u_int32_t icmp6_filt[8]; }; #define ICMP6_FILTER_SETPASSALL(filterp) \ (void)memset(filterp, 0xff, sizeof(struct icmp6_filter)) #define ICMP6_FILTER_SETBLOCKALL(filterp) \ (void)memset(filterp, 0x00, sizeof(struct icmp6_filter)) #define ICMP6_FILTER_SETPASS(type, filterp) \ (((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31))) #define ICMP6_FILTER_SETBLOCK(type, filterp) \ (((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31))) #define ICMP6_FILTER_WILLPASS(type, filterp) \ ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0) #define ICMP6_FILTER_WILLBLOCK(type, filterp) \ ((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0) /* * Variables related to this implementation * of the internet control message protocol version 6. */ /* * IPv6 ICMP statistics. * Each counter is an unsigned 64-bit value. */ #define ICMP6_STAT_ERROR 0 /* # of calls to icmp6_error */ #define ICMP6_STAT_CANTERROR 1 /* no error (old was icmp) */ #define ICMP6_STAT_TOOFREQ 2 /* no error (rate limitation) */ #define ICMP6_STAT_OUTHIST 3 /* # of output messages */ /* space for 256 counters */ #define ICMP6_STAT_BADCODE 259 /* icmp6_code out of range */ #define ICMP6_STAT_TOOSHORT 260 /* packet < sizeof(struct icmp6_hdr) */ #define ICMP6_STAT_CHECKSUM 261 /* bad checksum */ #define ICMP6_STAT_BADLEN 262 /* calculated bound mismatch */ /* * number of responses; this member is inherited from the netinet code, * but for netinet6 code, it is already available in outhist[]. */ #define ICMP6_STAT_REFLECT 263 #define ICMP6_STAT_INHIST 264 /* # of input messages */ /* space for 256 counters */ #define ICMP6_STAT_ND_TOOMANYOPT 520 /* too many ND options */ #define ICMP6_STAT_OUTERRHIST 521 /* space for 13 counters */ #define ICMP6_STAT_PMTUCHG 534 /* path MTU changes */ #define ICMP6_STAT_ND_BADOPT 535 /* bad ND options */ #define ICMP6_STAT_BADNS 536 /* bad neighbor solicititation */ #define ICMP6_STAT_BADNA 537 /* bad neighbor advertisement */ #define ICMP6_STAT_BADRS 538 /* bad router solicitiation */ #define ICMP6_STAT_BADRA 539 /* bad router advertisement */ #define ICMP6_STAT_BADREDIRECT 540 /* bad redirect message */ #define ICMP6_STAT_DROPPED_RAROUTE 541 /* discarded routes from router advertisement */ #define ICMP6_NSTATS 542 #define ICMP6_ERRSTAT_DST_UNREACH_NOROUTE 0 #define ICMP6_ERRSTAT_DST_UNREACH_ADMIN 1 #define ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE 2 #define ICMP6_ERRSTAT_DST_UNREACH_ADDR 3 #define ICMP6_ERRSTAT_DST_UNREACH_NOPORT 4 #define ICMP6_ERRSTAT_PACKET_TOO_BIG 5 #define ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT 6 #define ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY 7 #define ICMP6_ERRSTAT_PARAMPROB_HEADER 8 #define ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER 9 #define ICMP6_ERRSTAT_PARAMPROB_OPTION 10 #define ICMP6_ERRSTAT_REDIRECT 11 #define ICMP6_ERRSTAT_UNKNOWN 12 /* * Names for ICMP sysctl objects */ #define ICMPV6CTL_STATS 1 #define ICMPV6CTL_REDIRACCEPT 2 /* accept/process redirects */ #define ICMPV6CTL_REDIRTIMEOUT 3 /* redirect cache time */ #if 0 /*obsoleted*/ #define ICMPV6CTL_ERRRATELIMIT 5 /* ICMPv6 error rate limitation */ #endif #define ICMPV6CTL_ND6_PRUNE 6 #define ICMPV6CTL_ND6_DELAY 8 #define ICMPV6CTL_ND6_UMAXTRIES 9 #define ICMPV6CTL_ND6_MMAXTRIES 10 #define ICMPV6CTL_ND6_USELOOPBACK 11 /*#define ICMPV6CTL_ND6_PROXYALL 12 obsoleted, do not reuse here */ #define ICMPV6CTL_NODEINFO 13 #define ICMPV6CTL_ERRPPSLIMIT 14 /* ICMPv6 error pps limitation */ #define ICMPV6CTL_ND6_MAXNUDHINT 15 #define ICMPV6CTL_MTUDISC_HIWAT 16 #define ICMPV6CTL_MTUDISC_LOWAT 17 #define ICMPV6CTL_ND6_DEBUG 18 #define ICMPV6CTL_ND6_DRLIST 19 #define ICMPV6CTL_ND6_PRLIST 20 #define ICMPV6CTL_ND6_MAXQLEN 24 #define ICMPV6CTL_MAXID 25 #define ICMPV6CTL_NAMES { \ { 0, 0 }, \ { 0, 0 }, \ { "rediraccept", CTLTYPE_INT }, \ { "redirtimeout", CTLTYPE_INT }, \ { 0, 0 }, \ { 0, 0 }, \ { "nd6_prune", CTLTYPE_INT }, \ { 0, 0 }, \ { "nd6_delay", CTLTYPE_INT }, \ { "nd6_umaxtries", CTLTYPE_INT }, \ { "nd6_mmaxtries", CTLTYPE_INT }, \ { "nd6_useloopback", CTLTYPE_INT }, \ { 0, 0 }, \ { "nodeinfo", CTLTYPE_INT }, \ { "errppslimit", CTLTYPE_INT }, \ { "nd6_maxnudhint", CTLTYPE_INT }, \ { "mtudisc_hiwat", CTLTYPE_INT }, \ { "mtudisc_lowat", CTLTYPE_INT }, \ { "nd6_debug", CTLTYPE_INT }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { 0, 0 }, \ { "nd6_maxqueuelen", CTLTYPE_INT }, \ } #endif /* !_NETINET_ICMP6_H_ */ openvswitch-2.5.0/include/windows/netinet/PaxHeaders.69223/ip6.h0000644000000000000000000000013212631676263021277 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 30 ctime=1456594660.305293529 openvswitch-2.5.0/include/windows/netinet/ip6.h0000664000175000017500000002015312631676263022770 0ustar00jpettitjpettit00000000000000/* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)ip.h 8.1 (Berkeley) 6/10/93 */ #ifndef _NETINET_IP6_H_ #define _NETINET_IP6_H_ #include #include #include "byte-order.h" /* * Definition for internet protocol version 6. * RFC 2460 */ struct ip6_hdr { union { struct ip6_hdrctl { u_int32_t ip6_un1_flow; /* 20 bits of flow-ID */ u_int16_t ip6_un1_plen; /* payload length */ u_int8_t ip6_un1_nxt; /* next header */ u_int8_t ip6_un1_hlim; /* hop limit */ } ip6_un1; u_int8_t ip6_un2_vfc; /* 4 bits version, top 4 bits class */ } ip6_ctlun; struct in6_addr ip6_src; /* source address */ struct in6_addr ip6_dst; /* destination address */ }; #define ip6_vfc ip6_ctlun.ip6_un2_vfc #define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt #define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim #define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim #define IPV6_VERSION 0x60 #define IPV6_VERSION_MASK 0xf0 #define IPV6_FLOWINFO_MASK CONSTANT_HTONL(0x0fffffff) /* flow info (28 bits) */ #define IPV6_FLOWLABEL_MASK CONSTANT_HTONL(0x000fffff) /* flow label (20 bits) */ #if 1 /* ECN bits proposed by Sally Floyd */ #define IP6TOS_CE 0x01 /* congestion experienced */ #define IP6TOS_ECT 0x02 /* ECN-capable transport */ #endif /* * Extension Headers */ struct ip6_ext { u_int8_t ip6e_nxt; u_int8_t ip6e_len; }; /* Hop-by-Hop options header */ /* XXX should we pad it to force alignment on an 8-byte boundary? */ struct ip6_hbh { u_int8_t ip6h_nxt; /* next header */ u_int8_t ip6h_len; /* length in units of 8 octets */ /* followed by options */ }; /* Destination options header */ /* XXX should we pad it to force alignment on an 8-byte boundary? */ struct ip6_dest { u_int8_t ip6d_nxt; /* next header */ u_int8_t ip6d_len; /* length in units of 8 octets */ /* followed by options */ }; /* Option types and related macros */ #define IP6OPT_PAD1 0x00 /* 00 0 00000 */ #define IP6OPT_PADN 0x01 /* 00 0 00001 */ #define IP6OPT_JUMBO 0xC2 /* 11 0 00010 = 194 */ #define IP6OPT_NSAP_ADDR 0xC3 /* 11 0 00011 */ #define IP6OPT_TUNNEL_LIMIT 0x04 /* 00 0 00100 */ #define IP6OPT_RTALERT 0x05 /* 00 0 00101 (KAME definition) */ #define IP6OPT_ROUTER_ALERT 0x05 /* (RFC3542 def, recommended) */ #define IP6OPT_RTALERT_LEN 4 #define IP6OPT_RTALERT_MLD 0 /* Datagram contains an MLD message */ #define IP6OPT_RTALERT_RSVP 1 /* Datagram contains an RSVP message */ #define IP6OPT_RTALERT_ACTNET 2 /* contains an Active Networks msg */ #define IP6OPT_MINLEN 2 #define IP6OPT_TYPE(o) ((o) & 0xC0) #define IP6OPT_TYPE_SKIP 0x00 #define IP6OPT_TYPE_DISCARD 0x40 #define IP6OPT_TYPE_FORCEICMP 0x80 #define IP6OPT_TYPE_ICMP 0xC0 #define IP6OPT_MUTABLE 0x20 /* IPv6 options: common part */ struct ip6_opt { u_int8_t ip6o_type; u_int8_t ip6o_len; }; /* Jumbo Payload Option */ struct ip6_opt_jumbo { u_int8_t ip6oj_type; u_int8_t ip6oj_len; u_int8_t ip6oj_jumbo_len[4]; }; #define IP6OPT_JUMBO_LEN 6 /* NSAP Address Option */ struct ip6_opt_nsap { u_int8_t ip6on_type; u_int8_t ip6on_len; u_int8_t ip6on_src_nsap_len; u_int8_t ip6on_dst_nsap_len; /* followed by source NSAP */ /* followed by destination NSAP */ }; /* Tunnel Limit Option */ struct ip6_opt_tunnel { u_int8_t ip6ot_type; u_int8_t ip6ot_len; u_int8_t ip6ot_encap_limit; }; /* Router Alert Option */ struct ip6_opt_router { u_int8_t ip6or_type; u_int8_t ip6or_len; u_int8_t ip6or_value[2]; }; /* Router alert values (in network byte order) */ #define IP6_ALERT_MLD CONSTANT_HTONS(0x0000) #define IP6_ALERT_RSVP CONSTANT_HTONS(0x0001) #define IP6_ALERT_AN CONSTANT_HTONS(0x0002) /* Routing header */ struct ip6_rthdr { u_int8_t ip6r_nxt; /* next header */ u_int8_t ip6r_len; /* length in units of 8 octets */ u_int8_t ip6r_type; /* routing type */ u_int8_t ip6r_segleft; /* segments left */ /* followed by routing type specific data */ }; /* Type 0 Routing header */ struct ip6_rthdr0 { u_int8_t ip6r0_nxt; /* next header */ u_int8_t ip6r0_len; /* length in units of 8 octets */ u_int8_t ip6r0_type; /* always zero */ u_int8_t ip6r0_segleft; /* segments left */ u_int32_t ip6r0_reserved; /* reserved field */ }; /* Fragment header */ struct ip6_frag { u_int8_t ip6f_nxt; /* next header */ u_int8_t ip6f_reserved; /* reserved field */ u_int16_t ip6f_offlg; /* offset, reserved, and flag */ u_int32_t ip6f_ident; /* identification */ }; #define IP6F_OFF_MASK CONSTANT_HTONS(0xfff8) /* mask out offset from _offlg */ #define IP6F_RESERVED_MASK CONSTANT_HTONS(0x0006) /* reserved bits in ip6f_offlg */ #define IP6F_MORE_FRAG CONSTANT_HTONS(0x0001) /* more-fragments flag */ /* * Internet implementation parameters. */ #define IPV6_MAXHLIM 255 /* maximum hoplimit */ #define IPV6_DEFHLIM 64 /* default hlim */ #define IPV6_FRAGTTL 120 /* ttl for fragment packets, in slowtimo tick */ #define IPV6_HLIMDEC 1 /* subtracted when forwarding */ #define IPV6_MMTU 1280 /* minimal MTU and reassembly. 1024 + 256 */ #define IPV6_MAXPACKET 65535 /* ip6 max packet size without Jumbo payload*/ #endif /* !_NETINET_IP6_H_ */ openvswitch-2.5.0/include/windows/netinet/PaxHeaders.69223/tcp.h0000644000000000000000000000013112631676263021366 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.309293697 openvswitch-2.5.0/include/windows/netinet/tcp.h0000664000175000017500000000000012631676263023045 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/netinet/PaxHeaders.69223/in.h0000644000000000000000000000013212631676263021207 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.339091552 30 ctime=1456594660.305293529 openvswitch-2.5.0/include/windows/netinet/in.h0000664000175000017500000000132312631676263022676 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NETINET_IN_H #define __NETINET_IN_H 1 #define IPPROTO_GRE 47 #define IPPORT_FTP 21 #endif /* netinet/in.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/linux0000644000000000000000000000013212664357344020046 xustar0030 mtime=1456594660.297293191 30 atime=1456594661.701352216 30 ctime=1456594660.297293191 openvswitch-2.5.0/include/windows/linux/0000775000175000017500000000000012664357344021613 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/linux/PaxHeaders.69223/types.h0000644000000000000000000000013112631676263021435 xustar0030 mtime=1449622707.154445794 29 atime=1456592667.59510205 30 ctime=1456594660.297293191 openvswitch-2.5.0/include/windows/linux/types.h0000664000175000017500000000000012631676263023114 0ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/linux/PaxHeaders.69223/pkt_sched.h0000644000000000000000000000013212631676263022236 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.331091225 30 ctime=1456594660.297293191 openvswitch-2.5.0/include/windows/linux/pkt_sched.h0000664000175000017500000000151612631676263023731 0ustar00jpettitjpettit00000000000000/* * Copyright 2014 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __LINUX_PKT_SCHED_H #define __LINUX_PKT_SCHED_H 1 #define TC_H_MAJ_MASK (0xFFFF0000U) #define TC_H_MIN_MASK (0x0000FFFFU) #define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK)) #endif /* linux/pkt_sched.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/net0000644000000000000000000000013212664357344017475 xustar0030 mtime=1456594660.297293191 30 atime=1456594661.701352216 30 ctime=1456594660.297293191 openvswitch-2.5.0/include/windows/net/0000775000175000017500000000000012664357344021242 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/windows/net/PaxHeaders.69223/if.h0000644000000000000000000000013212631676263020317 xustar0030 mtime=1449622707.154445794 30 atime=1456592667.331091225 30 ctime=1456594660.297293191 openvswitch-2.5.0/include/windows/net/if.h0000664000175000017500000000334112631676263022010 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NET_IF_H #define __NET_IF_H 1 #include #define IFNAMSIZ IF_NAMESIZE enum { IFLA_UNSPEC, IFLA_ADDRESS, IFLA_BROADCAST, IFLA_IFNAME, IFLA_MTU, IFLA_LINK, IFLA_QDISC, IFLA_STATS, IFLA_COST, #define IFLA_COST IFLA_COST IFLA_PRIORITY, #define IFLA_PRIORITY IFLA_PRIORITY IFLA_MASTER, #define IFLA_MASTER IFLA_MASTER IFLA_WIRELESS, #define IFLA_WIRELESS IFLA_WIRELESS IFLA_PROTINFO, #define IFLA_PROTINFO IFLA_PROTINFO IFLA_TXQLEN, #define IFLA_TXQLEN IFLA_TXQLEN IFLA_MAP, #define IFLA_MAP IFLA_MAP IFLA_WEIGHT, #define IFLA_WEIGHT IFLA_WEIGHT IFLA_OPERSTATE, IFLA_LINKMODE, IFLA_LINKINFO, #define IFLA_LINKINFO IFLA_LINKINFO IFLA_NET_NS_PID, IFLA_IFALIAS, IFLA_NUM_VF, IFLA_VFINFO_LIST, IFLA_STATS64, IFLA_VF_PORTS, IFLA_PORT_SELF, IFLA_AF_SPEC, IFLA_GROUP, IFLA_NET_NS_FD, IFLA_EXT_MASK, IFLA_PROMISCUITY, #define IFLA_PROMISCUITY IFLA_PROMISCUITY IFLA_NUM_TX_QUEUES, IFLA_NUM_RX_QUEUES, IFLA_CARRIER, IFLA_PHYS_PORT_ID, __IFLA_MAX }; #define IFLA_MAX (__IFLA_MAX - 1) #endif /* net/if.h */ openvswitch-2.5.0/include/windows/PaxHeaders.69223/automake.mk0000644000000000000000000000013212631676263021121 xustar0030 mtime=1449622707.154445794 30 atime=1456592426.457208646 30 ctime=1456594659.577262924 openvswitch-2.5.0/include/windows/automake.mk0000664000175000017500000000215512631676263022614 0ustar00jpettitjpettit00000000000000# Copyright (C) 2013 Nicira, Inc. # # Copying and distribution of this file, with or without modification # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. noinst_HEADERS += \ include/windows/arpa/inet.h \ include/windows/dirent.h \ include/windows/getopt.h \ include/windows/linux/pkt_sched.h \ include/windows/linux/types.h \ include/windows/net/if.h \ include/windows/netdb.h \ include/windows/netpacket/packet.h \ include/windows/netinet/icmp6.h \ include/windows/netinet/in.h \ include/windows/netinet/in_systm.h \ include/windows/netinet/ip.h \ include/windows/netinet/ip6.h \ include/windows/netinet/tcp.h \ include/windows/poll.h \ include/windows/strings.h \ include/windows/syslog.h \ include/windows/sys/epoll.h \ include/windows/sys/ioctl.h \ include/windows/sys/resource.h \ include/windows/sys/socket.h \ include/windows/sys/time.h \ include/windows/sys/uio.h \ include/windows/sys/un.h \ include/windows/sys/wait.h \ include/windows/unistd.h \ include/windows/windefs.h openvswitch-2.5.0/include/PaxHeaders.69223/openvswitch0000644000000000000000000000013212664357344017566 xustar0030 mtime=1456594660.341295041 30 atime=1456594661.701352216 30 ctime=1456594660.341295041 openvswitch-2.5.0/include/openvswitch/0000775000175000017500000000000012664357344021333 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/types.h0000644000000000000000000000013212663320001021133 xustar0030 mtime=1456316417.506932771 30 atime=1456592608.528679928 30 ctime=1456594660.337294874 openvswitch-2.5.0/include/openvswitch/types.h0000664000175000017500000001065712663320001022634 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2010, 2011, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_TYPES_H #define OPENVSWITCH_TYPES_H 1 #include #include #include "openvswitch/compiler.h" #ifdef __CHECKER__ #define OVS_BITWISE __attribute__((bitwise)) #define OVS_FORCE __attribute__((force)) #else #define OVS_BITWISE #define OVS_FORCE #endif /* The ovs_be types indicate that an object is in big-endian, not * native-endian, byte order. They are otherwise equivalent to uint_t. */ typedef uint16_t OVS_BITWISE ovs_be16; typedef uint32_t OVS_BITWISE ovs_be32; typedef uint64_t OVS_BITWISE ovs_be64; #define OVS_BE16_MAX ((OVS_FORCE ovs_be16) 0xffff) #define OVS_BE32_MAX ((OVS_FORCE ovs_be32) 0xffffffff) #define OVS_BE64_MAX ((OVS_FORCE ovs_be64) 0xffffffffffffffffULL) /* These types help with a few funny situations: * * - The Ethernet header is 14 bytes long, which misaligns everything after * that. One can put 2 "shim" bytes before the Ethernet header, but this * helps only if there is exactly one Ethernet header. If there are two, * as with GRE and VXLAN (and if the inner header doesn't use this * trick--GRE and VXLAN don't) then you have the choice of aligning the * inner data or the outer data. So it seems better to treat 32-bit fields * in protocol headers as aligned only on 16-bit boundaries. * * - ARP headers contain misaligned 32-bit fields. * * - Netlink and OpenFlow contain 64-bit values that are only guaranteed to * be aligned on 32-bit boundaries. * * lib/unaligned.h has helper functions for accessing these. */ /* A 32-bit value, in host byte order, that is only aligned on a 16-bit * boundary. */ typedef struct { #ifdef WORDS_BIGENDIAN uint16_t hi, lo; #else uint16_t lo, hi; #endif } ovs_16aligned_u32; /* A 32-bit value, in network byte order, that is only aligned on a 16-bit * boundary. */ typedef struct { ovs_be16 hi, lo; } ovs_16aligned_be32; /* A 64-bit value, in host byte order, that is only aligned on a 32-bit * boundary. */ typedef struct { #ifdef WORDS_BIGENDIAN uint32_t hi, lo; #else uint32_t lo, hi; #endif } ovs_32aligned_u64; typedef union { uint32_t u32[4]; struct { #ifdef WORDS_BIGENDIAN uint64_t hi, lo; #else uint64_t lo, hi; #endif } u64; } ovs_u128; typedef union { ovs_be32 be32[4]; struct { ovs_be64 hi, lo; } be64; } ovs_be128; /* MSVC2015 doesn't support designated initializers when compiling C++, * and doesn't support ternary operators with non-designated initializers. * So we use these static definitions rather than using initializer macros. */ static const ovs_u128 OVS_U128_MAX = { { UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX } }; static const ovs_be128 OVS_BE128_MAX OVS_UNUSED = { { OVS_BE32_MAX, OVS_BE32_MAX, OVS_BE32_MAX, OVS_BE32_MAX } }; /* A 64-bit value, in network byte order, that is only aligned on a 32-bit * boundary. */ typedef struct { ovs_be32 hi, lo; } ovs_32aligned_be64; /* ofp_port_t represents the port number of a OpenFlow switch. * odp_port_t represents the port number on the datapath. * ofp11_port_t represents the OpenFlow-1.1 port number. */ typedef uint16_t OVS_BITWISE ofp_port_t; typedef uint32_t OVS_BITWISE odp_port_t; typedef uint32_t OVS_BITWISE ofp11_port_t; /* Macro functions that cast int types to ofp/odp/ofp11 types. */ #define OFP_PORT_C(X) ((OVS_FORCE ofp_port_t) (X)) #define ODP_PORT_C(X) ((OVS_FORCE odp_port_t) (X)) #define OFP11_PORT_C(X) ((OVS_FORCE ofp11_port_t) (X)) /* Using this struct instead of a bare array makes an ethernet address field * assignable. The size of the array is also part of the type, so it is easier * to deal with. */ struct eth_addr { union { uint8_t ea[6]; ovs_be16 be16[3]; }; }; #endif /* openvswitch/types.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/vconn.h0000644000000000000000000000013212631676263021135 xustar0030 mtime=1449622707.134445091 30 atime=1456592608.672685834 30 ctime=1456594660.341295041 openvswitch-2.5.0/include/openvswitch/vconn.h0000664000175000017500000000644112631676263022632 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_VCONN_H #define OPENVSWITCH_VCONN_H 1 #include #include #include #include #ifdef __cplusplus extern "C" { #endif struct ofpbuf; struct pvconn; struct pvconn_class; struct vconn; struct vconn_class; void vconn_usage(bool active, bool passive, bool bootstrap); /* Active vconns: virtual connections to OpenFlow devices. */ int vconn_verify_name(const char *name); int vconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp, struct vconn **vconnp); void vconn_close(struct vconn *); const char *vconn_get_name(const struct vconn *); uint32_t vconn_get_allowed_versions(const struct vconn *vconn); void vconn_set_allowed_versions(struct vconn *vconn, uint32_t allowed_versions); int vconn_get_version(const struct vconn *); void vconn_set_recv_any_version(struct vconn *); int vconn_connect(struct vconn *); int vconn_recv(struct vconn *, struct ofpbuf **); int vconn_send(struct vconn *, struct ofpbuf *); int vconn_recv_xid(struct vconn *, ovs_be32 xid, struct ofpbuf **); int vconn_transact(struct vconn *, struct ofpbuf *, struct ofpbuf **); int vconn_transact_noreply(struct vconn *, struct ofpbuf *, struct ofpbuf **); int vconn_transact_multiple_noreply(struct vconn *, struct ovs_list *requests, struct ofpbuf **replyp); int vconn_bundle_transact(struct vconn *, struct ovs_list *requests, uint16_t bundle_flags, void (*error_reporter)(const struct ofp_header *)); void vconn_run(struct vconn *); void vconn_run_wait(struct vconn *); int vconn_get_status(const struct vconn *); int vconn_open_block(const char *name, uint32_t allowed_versions, uint8_t dscp, struct vconn **); int vconn_connect_block(struct vconn *); int vconn_send_block(struct vconn *, struct ofpbuf *); int vconn_recv_block(struct vconn *, struct ofpbuf **); enum vconn_wait_type { WAIT_CONNECT, WAIT_RECV, WAIT_SEND }; void vconn_wait(struct vconn *, enum vconn_wait_type); void vconn_connect_wait(struct vconn *); void vconn_recv_wait(struct vconn *); void vconn_send_wait(struct vconn *); /* Passive vconns: virtual listeners for incoming OpenFlow connections. */ int pvconn_verify_name(const char *name); int pvconn_open(const char *name, uint32_t allowed_versions, uint8_t dscp, struct pvconn **pvconnp); const char *pvconn_get_name(const struct pvconn *); void pvconn_close(struct pvconn *); int pvconn_accept(struct pvconn *, struct vconn **); void pvconn_wait(struct pvconn *); #ifdef __cplusplus } #endif #endif /* vconn.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/compiler.h0000644000000000000000000000013212664352753021625 xustar0030 mtime=1456592363.442621001 30 atime=1456592368.182815687 30 ctime=1456594660.333294706 openvswitch-2.5.0/include/openvswitch/compiler.h0000664000175000017500000002064012664352753023317 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_COMPILER_H #define OPENVSWITCH_COMPILER_H 1 #ifndef __has_feature #define __has_feature(x) 0 #endif #ifndef __has_extension #define __has_extension(x) 0 #endif /* To make OVS_NO_RETURN portable across gcc/clang and MSVC, it should be * added at the beginning of the function declaration. */ #if __GNUC__ && !__CHECKER__ #define OVS_NO_RETURN __attribute__((__noreturn__)) #elif _MSC_VER #define OVS_NO_RETURN __declspec(noreturn) #else #define OVS_NO_RETURN #endif #if __GNUC__ && !__CHECKER__ #define OVS_UNUSED __attribute__((__unused__)) #define OVS_PRINTF_FORMAT(FMT, ARG1) __attribute__((__format__(printf, FMT, ARG1))) #define OVS_SCANF_FORMAT(FMT, ARG1) __attribute__((__format__(scanf, FMT, ARG1))) #define OVS_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) #define OVS_LIKELY(CONDITION) __builtin_expect(!!(CONDITION), 1) #define OVS_UNLIKELY(CONDITION) __builtin_expect(!!(CONDITION), 0) #else #define OVS_UNUSED #define OVS_PRINTF_FORMAT(FMT, ARG1) #define OVS_SCANF_FORMAT(FMT, ARG1) #define OVS_WARN_UNUSED_RESULT #define OVS_LIKELY(CONDITION) (!!(CONDITION)) #define OVS_UNLIKELY(CONDITION) (!!(CONDITION)) #endif #if __has_feature(c_thread_safety_attributes) /* "clang" annotations for thread safety check. * * OVS_LOCKABLE indicates that the struct contains mutex element * which can be locked by functions like ovs_mutex_lock(). * * Below, the word MUTEX stands for the name of an object with an OVS_LOCKABLE * struct type. It can also be a comma-separated list of multiple structs, * e.g. to require a function to hold multiple locks while invoked. * * * On a variable: * * - OVS_GUARDED indicates that the variable may only be accessed some mutex * is held. * * - OVS_GUARDED_BY(MUTEX) indicates that the variable may only be accessed * while the specific MUTEX is held. * * * On a variable A of mutex type: * * - OVS_ACQ_BEFORE(B), where B is a mutex or a comma-separated list of * mutexes, declare that if both A and B are acquired at the same time, * then A must be acquired before B. That is, B nests inside A. * * - OVS_ACQ_AFTER(B) is the opposite of OVS_ACQ_BEFORE(B), that is, it * declares that A nests inside B. * * * On a function, the following attributes apply to mutexes: * * - OVS_ACQUIRES(MUTEX) indicate that the function must be called without * holding MUTEX and that it returns holding MUTEX. * * - OVS_RELEASES(MUTEX) indicates that the function may only be called with * MUTEX held and that it returns with MUTEX released. It can be used for * all types of MUTEX. * * - OVS_TRY_LOCK(RETVAL, MUTEX) indicate that the function will try to * acquire MUTEX. RETVAL is an integer or boolean value specifying the * return value of a successful lock acquisition. * * - OVS_REQUIRES(MUTEX) indicate that the function may only be called with * MUTEX held and that the function does not release MUTEX. * * - OVS_EXCLUDED(MUTEX) indicates that the function may only be called when * MUTEX is not held. * * * The following variants, with the same syntax, apply to reader-writer locks: * * mutex rwlock, for reading rwlock, for writing * ------------------- ------------------- ------------------- * OVS_ACQUIRES OVS_ACQ_RDLOCK OVS_ACQ_WRLOCK * OVS_RELEASES OVS_RELEASES OVS_RELEASES * OVS_TRY_LOCK OVS_TRY_RDLOCK OVS_TRY_WRLOCK * OVS_REQUIRES OVS_REQ_RDLOCK OVS_REQ_WRLOCK * OVS_EXCLUDED OVS_EXCLUDED OVS_EXCLUDED */ #define OVS_LOCKABLE __attribute__((lockable)) #define OVS_REQ_RDLOCK(...) __attribute__((shared_locks_required(__VA_ARGS__))) #define OVS_ACQ_RDLOCK(...) __attribute__((shared_lock_function(__VA_ARGS__))) #define OVS_REQ_WRLOCK(...) \ __attribute__((exclusive_locks_required(__VA_ARGS__))) #define OVS_ACQ_WRLOCK(...) \ __attribute__((exclusive_lock_function(__VA_ARGS__))) #define OVS_REQUIRES(...) \ __attribute__((exclusive_locks_required(__VA_ARGS__))) #define OVS_ACQUIRES(...) \ __attribute__((exclusive_lock_function(__VA_ARGS__))) #define OVS_TRY_WRLOCK(RETVAL, ...) \ __attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__))) #define OVS_TRY_RDLOCK(RETVAL, ...) \ __attribute__((shared_trylock_function(RETVAL, __VA_ARGS__))) #define OVS_TRY_LOCK(RETVAL, ...) \ __attribute__((exclusive_trylock_function(RETVAL, __VA_ARGS__))) #define OVS_GUARDED __attribute__((guarded_var)) #define OVS_GUARDED_BY(...) __attribute__((guarded_by(__VA_ARGS__))) #define OVS_RELEASES(...) __attribute__((unlock_function(__VA_ARGS__))) #define OVS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) #define OVS_ACQ_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) #define OVS_ACQ_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) #define OVS_NO_THREAD_SAFETY_ANALYSIS \ __attribute__((no_thread_safety_analysis)) #else /* not Clang */ #define OVS_LOCKABLE #define OVS_REQ_RDLOCK(...) #define OVS_ACQ_RDLOCK(...) #define OVS_REQ_WRLOCK(...) #define OVS_ACQ_WRLOCK(...) #define OVS_REQUIRES(...) #define OVS_ACQUIRES(...) #define OVS_TRY_WRLOCK(...) #define OVS_TRY_RDLOCK(...) #define OVS_TRY_LOCK(...) #define OVS_GUARDED #define OVS_GUARDED_BY(...) #define OVS_EXCLUDED(...) #define OVS_RELEASES(...) #define OVS_ACQ_BEFORE(...) #define OVS_ACQ_AFTER(...) #define OVS_NO_THREAD_SAFETY_ANALYSIS #endif /* ISO C says that a C implementation may choose any integer type for an enum * that is sufficient to hold all of its values. Common ABIs (such as the * System V ABI used on i386 GNU/Linux) always use a full-sized "int", even * when a smaller type would suffice. * * In GNU C, "enum __attribute__((packed)) name { ... }" defines 'name' as an * enum compatible with a type that is no bigger than necessary. This is the * intended use of OVS_PACKED_ENUM. * * OVS_PACKED_ENUM is intended for use only as a space optimization, since it * only works with GCC. That means that it must not be used in wire protocols * or otherwise exposed outside of a single process. */ #if __GNUC__ && !__CHECKER__ #define OVS_PACKED_ENUM __attribute__((__packed__)) #define HAVE_PACKED_ENUM #else #define OVS_PACKED_ENUM #endif #ifndef _MSC_VER #define OVS_PACKED(DECL) DECL __attribute__((__packed__)) #else #define OVS_PACKED(DECL) __pragma(pack(push, 1)) DECL __pragma(pack(pop)) #endif /* For defining a structure whose instances should aligned on an N-byte * boundary. * * e.g. The following: * OVS_ALIGNED_STRUCT(64, mystruct) { ... }; * is equivalent to the following except that it specifies 64-byte alignment: * struct mystruct { ... }; */ #ifndef _MSC_VER #define OVS_ALIGNED_STRUCT(N, TAG) struct __attribute__((aligned(N))) TAG #else #define OVS_ALIGNED_STRUCT(N, TAG) __declspec(align(N)) struct TAG #endif #ifdef _MSC_VER #define CCALL __cdecl #pragma section(".CRT$XCU",read) #define OVS_CONSTRUCTOR(f) \ static void __cdecl f(void); \ __declspec(allocate(".CRT$XCU")) void (__cdecl*f##_)(void) = f; \ static void __cdecl f(void) #else #define OVS_CONSTRUCTOR(f) \ static void f(void) __attribute__((constructor)); \ static void f(void) #endif /* OVS_PREFETCH() can be used to instruct the CPU to fetch the cache * line containing the given address to a CPU cache. * OVS_PREFETCH_WRITE() should be used when the memory is going to be * written to. Depending on the target CPU, this can generate the same * instruction as OVS_PREFETCH(), or bring the data into the cache in an * exclusive state. */ #if __GNUC__ #define OVS_PREFETCH(addr) __builtin_prefetch((addr)) #define OVS_PREFETCH_WRITE(addr) __builtin_prefetch((addr), 1) #else #define OVS_PREFETCH(addr) #define OVS_PREFETCH_WRITE(addr) #endif #endif /* compiler.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/version.h.in0000644000000000000000000000013212631676263022104 xustar0030 mtime=1449622707.134445091 30 atime=1456592563.978852552 30 ctime=1456594659.637265447 openvswitch-2.5.0/include/openvswitch/version.h.in0000664000175000017500000000167712631676263023607 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * Copyright (c) 2014 Cisco Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_VERSION_H #define OPENVSWITCH_VERSION_H 1 #define OVS_PACKAGE_STRING "@PACKAGE_STRING@" #define OVS_PACKAGE_VERSION "@PACKAGE_VERSION@" #define OVS_LIB_VERSION @LT_CURRENT@ #define OVS_LIB_REVISION @LT_REVISION@ #define OVS_LIB_AGE @LT_AGE@ #endif /* openvswitch/version.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/thread.h0000644000000000000000000000013212664352753021262 xustar0030 mtime=1456592363.442621001 30 atime=1456592368.182815687 30 ctime=1456594660.337294874 openvswitch-2.5.0/include/openvswitch/thread.h0000664000175000017500000001127212664352753022755 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_THREAD_H #define OPENVSWITCH_THREAD_H 1 #include #include #include #include #include "util.h" /* Mutex. */ struct OVS_LOCKABLE ovs_mutex { pthread_mutex_t lock; const char *where; /* NULL if and only if uninitialized. */ }; /* "struct ovs_mutex" initializer. */ #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP #define OVS_MUTEX_INITIALIZER { PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP, \ "" } #else #define OVS_MUTEX_INITIALIZER { PTHREAD_MUTEX_INITIALIZER, "" } #endif #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP #define OVS_ADAPTIVE_MUTEX_INITIALIZER \ { PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, "" } #else #define OVS_ADAPTIVE_MUTEX_INITIALIZER OVS_MUTEX_INITIALIZER #endif /* ovs_mutex functions analogous to pthread_mutex_*() functions. * * Most of these functions abort the process with an error message on any * error. ovs_mutex_trylock() is an exception: it passes through a 0 or EBUSY * return value to the caller and aborts on any other error. */ void ovs_mutex_init(const struct ovs_mutex *); void ovs_mutex_init_recursive(const struct ovs_mutex *); void ovs_mutex_init_adaptive(const struct ovs_mutex *); void ovs_mutex_destroy(const struct ovs_mutex *); void ovs_mutex_unlock(const struct ovs_mutex *mutex) OVS_RELEASES(mutex); void ovs_mutex_lock_at(const struct ovs_mutex *mutex, const char *where) OVS_ACQUIRES(mutex); #define ovs_mutex_lock(mutex) \ ovs_mutex_lock_at(mutex, OVS_SOURCE_LOCATOR) int ovs_mutex_trylock_at(const struct ovs_mutex *mutex, const char *where) OVS_TRY_LOCK(0, mutex); #define ovs_mutex_trylock(mutex) \ ovs_mutex_trylock_at(mutex, OVS_SOURCE_LOCATOR) void ovs_mutex_cond_wait(pthread_cond_t *, const struct ovs_mutex *); /* Convenient once-only execution. * * * Problem * ======= * * POSIX provides pthread_once_t and pthread_once() as primitives for running a * set of code only once per process execution. They are used like this: * * static void run_once(void) { ...initialization... } * static pthread_once_t once = PTHREAD_ONCE_INIT; * ... * pthread_once(&once, run_once); * * pthread_once() does not allow passing any parameters to the initialization * function, which is often inconvenient, because it means that the function * can only access data declared at file scope. * * * Solution * ======== * * Use ovsthread_once, like this, instead: * * static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; * * if (ovsthread_once_start(&once)) { * ...initialization... * ovsthread_once_done(&once); * } */ struct ovsthread_once { bool done; /* Non-atomic, false negatives possible. */ struct ovs_mutex mutex; }; #define OVSTHREAD_ONCE_INITIALIZER \ { \ false, \ OVS_MUTEX_INITIALIZER, \ } static inline bool ovsthread_once_start(struct ovsthread_once *once) OVS_TRY_LOCK(true, once->mutex); void ovsthread_once_done(struct ovsthread_once *once) OVS_RELEASES(once->mutex); bool ovsthread_once_start__(struct ovsthread_once *once) OVS_TRY_LOCK(true, once->mutex); /* Returns true if this is the first call to ovsthread_once_start() for * 'once'. In this case, the caller should perform whatever initialization * actions it needs to do, then call ovsthread_once_done() for 'once'. * * Returns false if this is not the first call to ovsthread_once_start() for * 'once'. In this case, the call will not return until after * ovsthread_once_done() has been called. */ static inline bool ovsthread_once_start(struct ovsthread_once *once) { /* We may be reading 'done' at the same time as the first thread * is writing on it, or we can be using a stale copy of it. The * worst that can happen is that we call ovsthread_once_start__() * once when strictly not necessary. */ return OVS_UNLIKELY(!once->done && ovsthread_once_start__(once)); } #endif /* ovs-thread.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/util.h0000644000000000000000000000013212631676263020767 xustar0030 mtime=1449622707.134445091 30 atime=1456592608.564681405 30 ctime=1456594660.341295041 openvswitch-2.5.0/include/openvswitch/util.h0000664000175000017500000000336412631676263022465 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_UTIL_H #define OPENVSWITCH_UTIL_H 1 #include #ifdef __cplusplus extern "C" { #endif void ovs_set_program_name__(const char *name, const char *version, const char *date, const char *time); #define ovs_set_program_name(name, version) \ ovs_set_program_name__(name, version, __DATE__, __TIME__) const char *ovs_get_program_name(void); const char *ovs_get_program_version(void); /* Expands to a string that looks like ":", e.g. "tmp.c:10". * * See http://c-faq.com/ansi/stringize.html for an explanation of OVS_STRINGIZE * and OVS_STRINGIZE2. */ #define OVS_SOURCE_LOCATOR __FILE__ ":" OVS_STRINGIZE(__LINE__) #define OVS_STRINGIZE(ARG) OVS_STRINGIZE2(ARG) #define OVS_STRINGIZE2(ARG) #ARG /* Saturating multiplication of "unsigned int"s: overflow yields UINT_MAX. */ #define OVS_SAT_MUL(X, Y) \ ((Y) == 0 ? 0 \ : (X) <= UINT_MAX / (Y) ? (unsigned int) (X) * (unsigned int) (Y) \ : UINT_MAX) #ifdef __cplusplus } #endif #endif openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/token-bucket.h0000644000000000000000000000013212631676263022405 xustar0030 mtime=1449622707.134445091 30 atime=1456592608.660685342 30 ctime=1456594660.337294874 openvswitch-2.5.0/include/openvswitch/token-bucket.h0000664000175000017500000000275012631676263024101 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_TOKEN_BUCKET_H #define OPENVSWITCH_TOKEN_BUCKET_H 1 #include #include struct token_bucket { /* Configuration settings. */ unsigned int rate; /* Tokens added per millisecond. */ unsigned int burst; /* Max cumulative tokens credit. */ /* Current status. */ unsigned int tokens; /* Current number of tokens. */ long long int last_fill; /* Last time tokens added. */ }; #define TOKEN_BUCKET_INIT(RATE, BURST) { RATE, BURST, 0, LLONG_MIN } void token_bucket_init(struct token_bucket *, unsigned int rate, unsigned int burst); void token_bucket_set(struct token_bucket *, unsigned int rate, unsigned int burst); bool token_bucket_withdraw(struct token_bucket *, unsigned int n); void token_bucket_wait(struct token_bucket *, unsigned int n); #endif /* token-bucket.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/vlog.h0000644000000000000000000000013212664352753020762 xustar0030 mtime=1456592363.442621001 30 atime=1456592368.182815687 30 ctime=1456594660.341295041 openvswitch-2.5.0/include/openvswitch/vlog.h0000664000175000017500000003200012664352753022445 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_VLOG_H #define OPENVSWITCH_VLOG_H 1 /* Logging. * * * Thread-safety * ============= * * Fully thread safe. */ #include #include #include #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /* Logging severity levels. * * ovs-appctl(8) defines each of the log levels. */ #define VLOG_LEVELS \ VLOG_LEVEL(OFF, LOG_ALERT, 1) \ VLOG_LEVEL(EMER, LOG_ALERT, 1) \ VLOG_LEVEL(ERR, LOG_ERR, 3) \ VLOG_LEVEL(WARN, LOG_WARNING, 4) \ VLOG_LEVEL(INFO, LOG_NOTICE, 5) \ VLOG_LEVEL(DBG, LOG_DEBUG, 7) enum vlog_level { #define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424_LEVEL) VLL_##NAME, VLOG_LEVELS #undef VLOG_LEVEL VLL_N_LEVELS }; const char *vlog_get_level_name(enum vlog_level); enum vlog_level vlog_get_level_val(const char *name); /* Destinations that we can log to. */ #define VLOG_DESTINATIONS \ VLOG_DESTINATION(SYSLOG, "ovs|%05N|%c%T|%p|%m") \ VLOG_DESTINATION(CONSOLE, "%D{%Y-%m-%dT%H:%M:%SZ}|%05N|%c%T|%p|%m") \ VLOG_DESTINATION(FILE, "%D{%Y-%m-%dT%H:%M:%S.###Z}|%05N|%c%T|%p|%m") enum vlog_destination { #define VLOG_DESTINATION(NAME, PATTERN) VLF_##NAME, VLOG_DESTINATIONS #undef VLOG_DESTINATION VLF_N_DESTINATIONS, VLF_ANY_DESTINATION = -1 }; const char *vlog_get_destination_name(enum vlog_destination); enum vlog_destination vlog_get_destination_val(const char *name); /* A log module. */ struct vlog_module { struct ovs_list list; const char *name; /* User-visible name. */ int levels[VLF_N_DESTINATIONS]; /* Minimum log level for each destination. */ int min_level; /* Minimum log level for any destination. */ bool honor_rate_limits; /* Set false to ignore rate limits. */ }; /* Global list of all logging modules */ extern struct ovs_list vlog_modules; void vlog_insert_module(struct ovs_list *); /* Creates and initializes a global instance of a module named MODULE. */ #define VLOG_DEFINE_MODULE(MODULE) \ VLOG_DEFINE_MODULE__(MODULE) \ OVS_CONSTRUCTOR(init_##MODULE) { \ vlog_insert_module(&VLM_##MODULE.list); \ } \ const char *vlog_get_module_name(const struct vlog_module *); struct vlog_module *vlog_module_from_name(const char *name); /* Rate-limiter for log messages. */ struct vlog_rate_limit { struct token_bucket token_bucket; time_t first_dropped; /* Time first message was dropped. */ time_t last_dropped; /* Time of most recent message drop. */ unsigned int n_dropped; /* Number of messages dropped. */ struct ovs_mutex mutex; /* Mutual exclusion for rate limit. */ }; /* Number of tokens to emit a message. We add 'rate' tokens per millisecond, * thus 60,000 tokens are required to emit one message per minute. */ #define VLOG_MSG_TOKENS (60 * 1000) /* Initializer for a struct vlog_rate_limit, to set up a maximum rate of RATE * messages per minute and a maximum burst size of BURST messages. */ #define VLOG_RATE_LIMIT_INIT(RATE, BURST) \ { \ TOKEN_BUCKET_INIT(RATE, OVS_SAT_MUL(BURST, VLOG_MSG_TOKENS)), \ 0, /* first_dropped */ \ 0, /* last_dropped */ \ 0, /* n_dropped */ \ OVS_MUTEX_INITIALIZER /* mutex */ \ } /* Configuring how each module logs messages. */ enum vlog_level vlog_get_level(const struct vlog_module *, enum vlog_destination); void vlog_set_levels(struct vlog_module *, enum vlog_destination, enum vlog_level); char *vlog_set_levels_from_string(const char *) OVS_WARN_UNUSED_RESULT; void vlog_set_levels_from_string_assert(const char *); char *vlog_get_levels(void); char *vlog_get_patterns(void); bool vlog_is_enabled(const struct vlog_module *, enum vlog_level); bool vlog_should_drop(const struct vlog_module *, enum vlog_level, struct vlog_rate_limit *); void vlog_set_verbosity(const char *arg); /* Configuring log destinations. */ void vlog_set_pattern(enum vlog_destination, const char *pattern); int vlog_set_log_file(const char *file_name); int vlog_reopen_log_file(void); #ifndef _WIN32 void vlog_change_owner_unix(uid_t, gid_t); #endif /* Configure method how vlog should send messages to syslog server. */ void vlog_set_syslog_method(const char *method); /* Configure syslog target. */ void vlog_set_syslog_target(const char *target); /* Initialization. */ void vlog_init(void); void vlog_enable_async(void); /* Functions for actual logging. */ void vlog(const struct vlog_module *, enum vlog_level, const char *format, ...) OVS_PRINTF_FORMAT (3, 4); void vlog_valist(const struct vlog_module *, enum vlog_level, const char *, va_list) OVS_PRINTF_FORMAT (3, 0); OVS_NO_RETURN void vlog_fatal(const struct vlog_module *, const char *format, ...) OVS_PRINTF_FORMAT (2, 3); OVS_NO_RETURN void vlog_fatal_valist(const struct vlog_module *, const char *format, va_list) OVS_PRINTF_FORMAT (2, 0); OVS_NO_RETURN void vlog_abort(const struct vlog_module *, const char *format, ...) OVS_PRINTF_FORMAT (2, 3); OVS_NO_RETURN void vlog_abort_valist(const struct vlog_module *, const char *format, va_list) OVS_PRINTF_FORMAT (2, 0); void vlog_rate_limit(const struct vlog_module *, enum vlog_level, struct vlog_rate_limit *, const char *, ...) OVS_PRINTF_FORMAT (4, 5); /* Creates and initializes a global instance of a module named MODULE, and * defines a static variable named THIS_MODULE that points to it, for use with * the convenience macros below. */ #define VLOG_DEFINE_THIS_MODULE(MODULE) \ VLOG_DEFINE_MODULE(MODULE); \ static struct vlog_module *const THIS_MODULE = &VLM_##MODULE /* Convenience macros. These assume that THIS_MODULE points to a "struct * vlog_module" for the current module, as set up by e.g. the * VLOG_DEFINE_MODULE macro above. * * Guaranteed to preserve errno. */ #define VLOG_FATAL(...) vlog_fatal(THIS_MODULE, __VA_ARGS__) #define VLOG_ABORT(...) vlog_abort(THIS_MODULE, __VA_ARGS__) #define VLOG_EMER(...) VLOG(VLL_EMER, __VA_ARGS__) #define VLOG_ERR(...) VLOG(VLL_ERR, __VA_ARGS__) #define VLOG_WARN(...) VLOG(VLL_WARN, __VA_ARGS__) #define VLOG_INFO(...) VLOG(VLL_INFO, __VA_ARGS__) #define VLOG_DBG(...) VLOG(VLL_DBG, __VA_ARGS__) /* More convenience macros, for testing whether a given level is enabled in * THIS_MODULE. When constructing a log message is expensive, this enables it * to be skipped. */ #define VLOG_IS_ERR_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_ERR) #define VLOG_IS_WARN_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_WARN) #define VLOG_IS_INFO_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_INFO) #define VLOG_IS_DBG_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_DBG) /* Convenience macros for rate-limiting. * Guaranteed to preserve errno. */ #define VLOG_ERR_RL(RL, ...) VLOG_RL(RL, VLL_ERR, __VA_ARGS__) #define VLOG_WARN_RL(RL, ...) VLOG_RL(RL, VLL_WARN, __VA_ARGS__) #define VLOG_INFO_RL(RL, ...) VLOG_RL(RL, VLL_INFO, __VA_ARGS__) #define VLOG_DBG_RL(RL, ...) VLOG_RL(RL, VLL_DBG, __VA_ARGS__) /* Convenience macros to additionally store log message in buffer * Caller is responsible for freeing *ERRP afterwards */ #define VLOG_ERR_BUF(ERRP, ...) VLOG_ERRP(ERRP, VLL_ERR, __VA_ARGS__) #define VLOG_WARN_BUF(ERRP, ...) VLOG_ERRP(ERRP, VLL_WARN, __VA_ARGS__) #define VLOG_DROP_ERR(RL) vlog_should_drop(THIS_MODULE, VLL_ERR, RL) #define VLOG_DROP_WARN(RL) vlog_should_drop(THIS_MODULE, VLL_WARN, RL) #define VLOG_DROP_INFO(RL) vlog_should_drop(THIS_MODULE, VLL_INFO, RL) #define VLOG_DROP_DBG(RL) vlog_should_drop(THIS_MODULE, VLL_DBG, RL) /* Macros for logging at most once per execution. */ #define VLOG_ERR_ONCE(...) VLOG_ONCE(VLL_ERR, __VA_ARGS__) #define VLOG_WARN_ONCE(...) VLOG_ONCE(VLL_WARN, __VA_ARGS__) #define VLOG_INFO_ONCE(...) VLOG_ONCE(VLL_INFO, __VA_ARGS__) #define VLOG_DBG_ONCE(...) VLOG_ONCE(VLL_DBG, __VA_ARGS__) /* Command line processing. */ #define VLOG_OPTION_ENUMS \ OPT_LOG_FILE, \ OPT_SYSLOG_IMPL, \ OPT_SYSLOG_TARGET #define VLOG_LONG_OPTIONS \ {"verbose", optional_argument, NULL, 'v'}, \ {"log-file", optional_argument, NULL, OPT_LOG_FILE}, \ {"syslog-method", optional_argument, NULL, OPT_SYSLOG_IMPL}, \ {"syslog-target", required_argument, NULL, OPT_SYSLOG_TARGET} #define VLOG_OPTION_HANDLERS \ case 'v': \ vlog_set_verbosity(optarg); \ break; \ case OPT_LOG_FILE: \ vlog_set_log_file(optarg); \ break; \ case OPT_SYSLOG_IMPL: \ vlog_set_syslog_method(optarg); \ break; \ case OPT_SYSLOG_TARGET: \ vlog_set_syslog_target(optarg); \ break; void vlog_usage(void); /* Implementation details. */ #define VLOG(LEVEL, ...) \ do { \ enum vlog_level level__ = LEVEL; \ if (THIS_MODULE->min_level >= level__) { \ vlog(THIS_MODULE, level__, __VA_ARGS__); \ } \ } while (0) #define VLOG_RL(RL, LEVEL, ...) \ do { \ enum vlog_level level__ = LEVEL; \ if (THIS_MODULE->min_level >= level__) { \ vlog_rate_limit(THIS_MODULE, level__, RL, __VA_ARGS__); \ } \ } while (0) #define VLOG_ONCE(LEVEL, ...) \ do { \ static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; \ if (ovsthread_once_start(&once)) { \ vlog(THIS_MODULE, LEVEL, __VA_ARGS__); \ ovsthread_once_done(&once); \ } \ } while (0) #define VLOG_ERRP(ERRP, LEVEL, ...) \ do { \ VLOG(LEVEL, __VA_ARGS__); \ if (ERRP) { \ *(ERRP) = xasprintf(__VA_ARGS__); \ } \ } while (0) #define VLOG_DEFINE_MODULE__(MODULE) \ extern struct vlog_module VLM_##MODULE; \ struct vlog_module VLM_##MODULE = \ { \ OVS_LIST_INITIALIZER(&VLM_##MODULE.list), \ #MODULE, /* name */ \ { VLL_INFO, VLL_INFO, VLL_INFO }, /* levels */ \ VLL_INFO, /* min_level */ \ true /* honor_rate_limits */ \ }; #ifdef __cplusplus } #endif #endif /* vlog.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/version.h0000644000000000000000000000013212664357165021502 xustar0030 mtime=1456594549.608638155 30 atime=1456594549.772645055 30 ctime=1456594660.341295041 openvswitch-2.5.0/include/openvswitch/version.h0000664000175000017500000000162612664357165023177 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * Copyright (c) 2014 Cisco Systems, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_VERSION_H #define OPENVSWITCH_VERSION_H 1 #define OVS_PACKAGE_STRING "openvswitch 2.5.0" #define OVS_PACKAGE_VERSION "2.5.0" #define OVS_LIB_VERSION 1 #define OVS_LIB_REVISION 0 #define OVS_LIB_AGE 0 #endif /* openvswitch/version.h */ openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/automake.mk0000644000000000000000000000013112631676263021777 xustar0029 mtime=1449622707.12644481 30 atime=1456592426.453208481 30 ctime=1456594659.573262755 openvswitch-2.5.0/include/openvswitch/automake.mk0000664000175000017500000000056112631676263023472 0ustar00jpettitjpettit00000000000000openvswitchincludedir = $(includedir)/openvswitch openvswitchinclude_HEADERS = \ include/openvswitch/compiler.h \ include/openvswitch/list.h \ include/openvswitch/thread.h \ include/openvswitch/token-bucket.h \ include/openvswitch/types.h \ include/openvswitch/util.h \ include/openvswitch/version.h \ include/openvswitch/vconn.h \ include/openvswitch/vlog.h openvswitch-2.5.0/include/openvswitch/PaxHeaders.69223/list.h0000644000000000000000000000013212631676263020765 xustar0030 mtime=1449622707.130444951 30 atime=1456592608.592682553 30 ctime=1456594660.333294706 openvswitch-2.5.0/include/openvswitch/list.h0000664000175000017500000000164512631676263022463 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENVSWITCH_LIST_H #define OPENVSWITCH_LIST_H 1 /* Doubly linked list head or element. */ struct ovs_list { struct ovs_list *prev; /* Previous list element. */ struct ovs_list *next; /* Next list element. */ }; #define OVS_LIST_INITIALIZER(LIST) { LIST, LIST } #endif /* list.h */ openvswitch-2.5.0/include/PaxHeaders.69223/openflow0000644000000000000000000000013212664357344017046 xustar0030 mtime=1456594660.333294706 30 atime=1456594661.701352216 30 ctime=1456594660.333294706 openvswitch-2.5.0/include/openflow/0000775000175000017500000000000012664357344020613 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow-1.5.h0000644000000000000000000000013212664352753021425 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.182815687 30 ctime=1456594660.329294538 openvswitch-2.5.0/include/openflow/openflow-1.5.h0000664000175000017500000001726212664352753023125 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2014 The Board of Trustees of The Leland Stanford * Junior University * Copyright (c) 2011, 2014 Open Networking Foundation * * We are making the OpenFlow specification and associated documentation * (Software) available for public use and benefit with the expectation * that others will use, modify and enhance the Software and contribute * those enhancements back to the community. However, since we would * like to make the Software available for broadest use, with as few * restrictions as possible permission is hereby granted, free of * charge, to any person obtaining a copy of this Software to deal in * the Software under the copyrights without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * The name and trademarks of copyright holder(s) may NOT be used in * advertising or publicity pertaining to the Software or any * derivatives without specific, written prior permission. */ /* OpenFlow: protocol between controller and datapath. */ #ifndef OPENFLOW_15_H #define OPENFLOW_15_H 1 #include /* Body for ofp15_multipart_request of type OFPMP_PORT_DESC. */ struct ofp15_port_desc_request { ovs_be32 port_no; /* All ports if OFPP_ANY. */ uint8_t pad[4]; /* Align to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp15_port_desc_request) == 8); /* Group commands */ enum ofp15_group_mod_command { /* Present since OpenFlow 1.1 - 1.4 */ OFPGC15_ADD = 0, /* New group. */ OFPGC15_MODIFY = 1, /* Modify all matching groups. */ OFPGC15_DELETE = 2, /* Delete all matching groups. */ /* New in OpenFlow 1.5 */ OFPGC15_INSERT_BUCKET = 3,/* Insert action buckets to the already available list of action buckets in a matching group */ /* OFPGCXX_YYY = 4, */ /* Reserved for future use. */ OFPGC15_REMOVE_BUCKET = 5,/* Remove all action buckets or any specific action bucket from matching group */ }; /* Group bucket property types. */ enum ofp15_group_bucket_prop_type { OFPGBPT15_WEIGHT = 0, /* Select groups only. */ OFPGBPT15_WATCH_PORT = 1, /* Fast failover groups only. */ OFPGBPT15_WATCH_GROUP = 2, /* Fast failover groups only. */ OFPGBPT15_EXPERIMENTER = 0xFFFF, /* Experimenter defined. */ }; /* Group bucket weight property, for select groups only. */ struct ofp15_group_bucket_prop_weight { ovs_be16 type; /* OFPGBPT15_WEIGHT. */ ovs_be16 length; /* 8. */ ovs_be16 weight; /* Relative weight of bucket. */ uint8_t pad[2]; /* Pad to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp15_group_bucket_prop_weight) == 8); /* Group bucket watch port or watch group property, for fast failover groups * only. */ struct ofp15_group_bucket_prop_watch { ovs_be16 type; /* OFPGBPT15_WATCH_PORT or OFPGBPT15_WATCH_GROUP. */ ovs_be16 length; /* 8. */ ovs_be32 watch; /* The port or the group. */ }; OFP_ASSERT(sizeof(struct ofp15_group_bucket_prop_watch) == 8); /* Bucket for use in groups. */ struct ofp15_bucket { ovs_be16 len; /* Length the bucket in bytes, including this header and any padding to make it 64-bit aligned. */ ovs_be16 action_array_len; /* Length of all actions in bytes. */ ovs_be32 bucket_id; /* Bucket Id used to identify bucket*/ /* Followed by exactly len - 8 bytes of group bucket properties. */ /* Followed by: * - Exactly 'action_array_len' bytes containing an array of * struct ofp_action_*. * - Zero or more bytes of group bucket properties to fill out the * overall length in header.length. */ }; OFP_ASSERT(sizeof(struct ofp15_bucket) == 8); /* Bucket Id can be any value between 0 and OFPG_BUCKET_MAX */ enum ofp15_group_bucket { OFPG15_BUCKET_MAX = 0xffffff00, /* Last usable bucket ID */ OFPG15_BUCKET_FIRST = 0xfffffffd, /* First bucket ID in the list of action buckets of a group. This is applicable for OFPGC15_INSERT_BUCKET and OFPGC15_REMOVE_BUCKET commands */ OFPG15_BUCKET_LAST = 0xfffffffe, /* Last bucket ID in the list of action buckets of a group. This is applicable for OFPGC15_INSERT_BUCKET and OFPGC15_REMOVE_BUCKET commands */ OFPG15_BUCKET_ALL = 0xffffffff /* All action buckets in a group, This is applicable for only OFPGC15_REMOVE_BUCKET command */ }; /* Group property types. */ enum ofp_group_prop_type { OFPGPT15_EXPERIMENTER = 0xFFFF, /* Experimenter defined. */ }; /* Group setup and teardown (controller -> datapath). */ struct ofp15_group_mod { ovs_be16 command; /* One of OFPGC15_*. */ uint8_t type; /* One of OFPGT11_*. */ uint8_t pad; /* Pad to 64 bits. */ ovs_be32 group_id; /* Group identifier. */ ovs_be16 bucket_array_len; /* Length of action buckets data. */ uint8_t pad1[2]; /* Pad to 64 bits. */ ovs_be32 command_bucket_id; /* Bucket Id used as part of * OFPGC15_INSERT_BUCKET and * OFPGC15_REMOVE_BUCKET commands * execution.*/ /* Followed by: * - Exactly 'bucket_array_len' bytes containing an array of * struct ofp15_bucket. * - Zero or more bytes of group properties to fill out the overall * length in header.length. */ }; OFP_ASSERT(sizeof(struct ofp15_group_mod) == 16); /* Body for ofp15_multipart_request of type OFPMP_GROUP_DESC. */ struct ofp15_group_desc_request { ovs_be32 group_id; /* All groups if OFPG_ALL. */ uint8_t pad[4]; /* Align to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp15_group_desc_request) == 8); /* Body of reply to OFPMP_GROUP_DESC request. */ struct ofp15_group_desc_stats { ovs_be16 length; /* Length of this entry. */ uint8_t type; /* One of OFPGT11_*. */ uint8_t pad; /* Pad to 64 bits. */ ovs_be32 group_id; /* Group identifier. */ ovs_be16 bucket_list_len; /* Length of action buckets data. */ uint8_t pad2[6]; /* Pad to 64 bits. */ /* Followed by: * - Exactly 'bucket_list_len' bytes containing an array of * struct ofp_bucket. * - Zero or more bytes of group properties to fill out the overall * length in header.length. */ }; OFP_ASSERT(sizeof(struct ofp15_group_desc_stats) == 16); #endif /* openflow/openflow-1.5.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow-1.3.h0000644000000000000000000000013212664352753021423 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.182815687 30 ctime=1456594660.329294538 openvswitch-2.5.0/include/openflow/openflow-1.3.h0000664000175000017500000004672412664352753023130 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford * Junior University * Copyright (c) 2011, 2012 Open Networking Foundation * * We are making the OpenFlow specification and associated documentation * (Software) available for public use and benefit with the expectation * that others will use, modify and enhance the Software and contribute * those enhancements back to the community. However, since we would * like to make the Software available for broadest use, with as few * restrictions as possible permission is hereby granted, free of * charge, to any person obtaining a copy of this Software to deal in * the Software under the copyrights without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * The name and trademarks of copyright holder(s) may NOT be used in * advertising or publicity pertaining to the Software or any * derivatives without specific, written prior permission. */ /* OpenFlow: protocol between controller and datapath. */ #ifndef OPENFLOW_13_H #define OPENFLOW_13_H 1 #include /* * OpenFlow 1.3 modifies the syntax of the following message types: * * OFPT_FEATURES_REPLY = 6 (opf13_switch_features) * - new field: auxiliary_id * - removed: ofp_ports at the end * * OFPT_PACKET_IN = 10 (ofp13_packet_in) new field: cookie * * OpenFlow 1.3 adds following new message types: * * * Asynchronous message configuration. * * OFPT13_GET_ASYNC_REQUEST = 26 (void) * OFPT13_GET_ASYNC_REPLY = 27 (ofp13_async_config) * OFPT13_SET_ASYNC = 28 (ofp13_async_config) * * * Meters and rate limiters configuration messages. * * OFPT13_METER_MOD = 29 (ofp13_meter_mod) * * OpenFlow 1.3 modifies the syntax of the following statistics message types * (now called multipart message types): * * OFPMP13_FLOW_REPLY = 1 (struct ofp13_flow_stats[]) * OFPMP13_TABLE_REPLY = 3 (struct ofp13_table_stats[]) * OFPMP13_PORT_REPLY = 4 (struct ofp13_port_stats[]) * OFPMP13_QUEUE_REPLY = 5, (struct ofp13_queue_stats[]) * OFPMP13_GROUP_REPLY = 6, (struct ofp13_group_stats[]) * * OpenFlow 1.3 adds the following multipart message types * * Meter statistics: * OFPMP13_METER_REQUEST = 9, (struct ofp13_meter_multipart_request) * OFPMP13_METER_REPLY = 9, (struct ofp13_meter_stats[]) * * Meter configuration: * OFPMP13_METER_CONFIG_REQUEST = 10, (struct ofp13_meter_multipart_request) * OFPMP13_METER_CONFIG_REPLY = 10, (struct ofp13_meter_config[]) * * Meter features: * OFPMP13_METER_FEATURES_REQUEST = 11 (void) * OFPMP13_METER_FEATURES_REPLY = 11 (struct ofp13_meter_features) * * Table features: * OFPMP13_TABLE_FEATURES_REQUEST = 12, (struct ofp13_table_features[]) * OFPMP13_TABLE_FEATURES_REPLY = 12, (struct ofp13_table_features[]) * */ enum ofp13_instruction_type { OFPIT13_METER = 6 /* Apply meter (rate limiter) */ }; /* Instruction structure for OFPIT_METER */ struct ofp13_instruction_meter { ovs_be16 type; /* OFPIT13_METER */ ovs_be16 len; /* Length is 8. */ ovs_be32 meter_id; /* Meter instance. */ }; OFP_ASSERT(sizeof(struct ofp13_instruction_meter) == 8); /* enum ofp_config_flags value OFPC_INVALID_TTL_TO_CONTROLLER * is deprecated in OpenFlow 1.3 */ /* Flags to configure the table. Reserved for future use. */ enum ofp13_table_config { OFPTC13_DEPRECATED_MASK = 3 /* Deprecated bits */ }; /* OpenFlow 1.3 specific flags for flow_mod messages. */ enum ofp13_flow_mod_flags { OFPFF13_NO_PKT_COUNTS = 1 << 3, /* Don't keep track of packet count. */ OFPFF13_NO_BYT_COUNTS = 1 << 4 /* Don't keep track of byte count. */ }; /* Common header for all meter bands */ struct ofp13_meter_band_header { ovs_be16 type; /* One of OFPMBT_*. */ ovs_be16 len; /* Length in bytes of this band. */ ovs_be32 rate; /* Rate for this band. */ ovs_be32 burst_size; /* Size of bursts. */ }; OFP_ASSERT(sizeof(struct ofp13_meter_band_header) == 12); /* Meter configuration. OFPT_METER_MOD. */ struct ofp13_meter_mod { ovs_be16 command; /* One of OFPMC_*. */ ovs_be16 flags; /* Set of OFPMF_*. */ ovs_be32 meter_id; /* Meter instance. */ /* struct ofp13_meter_band_header bands[0]; The bands length is inferred from the length field in the header. */ }; OFP_ASSERT(sizeof(struct ofp13_meter_mod) == 8); /* Meter numbering. Flow meters can use any number up to OFPM_MAX. */ enum ofp13_meter { /* Last usable meter. */ OFPM13_MAX = 0xffff0000, /* Virtual meters. */ OFPM13_SLOWPATH = 0xfffffffd, /* Meter for slow datapath. */ OFPM13_CONTROLLER = 0xfffffffe, /* Meter for controller connection. */ OFPM13_ALL = 0xffffffff, /* Represents all meters for stat requests commands. */ }; /* Meter commands */ enum ofp13_meter_mod_command { OFPMC13_ADD, /* New meter. */ OFPMC13_MODIFY, /* Modify specified meter. */ OFPMC13_DELETE /* Delete specified meter. */ }; /* Meter configuration flags */ enum ofp13_meter_flags { OFPMF13_KBPS = 1 << 0, /* Rate value in kb/s (kilo-bit per second). */ OFPMF13_PKTPS = 1 << 1, /* Rate value in packet/sec. */ OFPMF13_BURST = 1 << 2, /* Do burst size. */ OFPMF13_STATS = 1 << 3 /* Collect statistics. */ }; /* Meter band types */ enum ofp13_meter_band_type { OFPMBT13_DROP = 1, /* Drop packet. */ OFPMBT13_DSCP_REMARK = 2, /* Remark DSCP in the IP header. */ OFPMBT13_EXPERIMENTER = 0xFFFF /* Experimenter meter band. */ }; /* OFPMBT_DROP band - drop packets */ struct ofp13_meter_band_drop { ovs_be16 type; /* OFPMBT_DROP. */ ovs_be16 len; /* Length in bytes of this band. */ ovs_be32 rate; /* Rate for dropping packets. */ ovs_be32 burst_size; /* Size of bursts. */ uint8_t pad[4]; }; OFP_ASSERT(sizeof(struct ofp13_meter_band_drop) == 16); /* OFPMBT_DSCP_REMARK band - Remark DSCP in the IP header */ struct ofp13_meter_band_dscp_remark { ovs_be16 type; /* OFPMBT_DSCP_REMARK. */ ovs_be16 len; /* Length in bytes of this band. */ ovs_be32 rate; /* Rate for remarking packets. */ ovs_be32 burst_size; /* Size of bursts. */ uint8_t prec_level; /* Number of drop precedence level to add. */ uint8_t pad[3]; }; OFP_ASSERT(sizeof(struct ofp13_meter_band_dscp_remark) == 16); /* OFPMBT_EXPERIMENTER band - Write actions in action set */ struct ofp13_meter_band_experimenter { ovs_be16 type; /* OFPMBT_EXPERIMENTER. */ ovs_be16 len; /* Length in bytes of this band. */ ovs_be32 rate; /* Rate for dropping packets. */ ovs_be32 burst_size; /* Size of bursts. */ ovs_be32 experimenter; /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ }; OFP_ASSERT(sizeof(struct ofp13_meter_band_experimenter) == 16); /* OF 1.3 adds MORE flag also for requests */ enum ofp13_multipart_request_flags { OFPMPF13_REQ_MORE = 1 << 0 /* More requests to follow. */ }; /* OF 1.3 splits table features off the ofp_table_stats */ /* Body of reply to OFPMP13_TABLE request. */ struct ofp13_table_stats { uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */ uint8_t pad[3]; /* Align to 32-bits. */ ovs_be32 active_count; /* Number of active entries. */ ovs_be64 lookup_count; /* Number of packets looked up in table. */ ovs_be64 matched_count; /* Number of packets that hit table. */ }; OFP_ASSERT(sizeof(struct ofp13_table_stats) == 24); /* Common header for all Table Feature Properties */ struct ofp13_table_feature_prop_header { ovs_be16 type; /* One of OFPTFPT_*. */ ovs_be16 length; /* Length in bytes of this property. */ }; OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_header) == 4); /* Body for ofp_multipart_request of type OFPMP_TABLE_FEATURES./ * Body of reply to OFPMP_TABLE_FEATURES request. */ struct ofp13_table_features { ovs_be16 length; /* Length is padded to 64 bits. */ uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */ uint8_t pad[5]; /* Align to 64-bits. */ char name[OFP_MAX_TABLE_NAME_LEN]; ovs_be64 metadata_match; /* Bits of metadata table can match. */ ovs_be64 metadata_write; /* Bits of metadata table can write. */ /* In OF1.3 this field was named 'config' and it was useless because OF1.3 * did not define any OFPTC_* bits. * * OF1.4 renamed this field to 'capabilities' and added OFPTC14_EVICTION * and OFPTC14_VACANCY_EVENTS. */ ovs_be32 capabilities; /* Bitmap of OFPTC_* values */ ovs_be32 max_entries; /* Max number of entries supported. */ /* Table Feature Property list */ /* struct ofp13_table_feature_prop_header properties[0]; */ }; OFP_ASSERT(sizeof(struct ofp13_table_features) == 64); /* Table Feature property types. * Low order bit cleared indicates a property for a regular Flow Entry. * Low order bit set indicates a property for the Table-Miss Flow Entry. */ enum ofp13_table_feature_prop_type { OFPTFPT13_INSTRUCTIONS = 0, /* Instructions property. */ OFPTFPT13_INSTRUCTIONS_MISS = 1, /* Instructions for table-miss. */ OFPTFPT13_NEXT_TABLES = 2, /* Next Table property. */ OFPTFPT13_NEXT_TABLES_MISS = 3, /* Next Table for table-miss. */ OFPTFPT13_WRITE_ACTIONS = 4, /* Write Actions property. */ OFPTFPT13_WRITE_ACTIONS_MISS = 5, /* Write Actions for table-miss. */ OFPTFPT13_APPLY_ACTIONS = 6, /* Apply Actions property. */ OFPTFPT13_APPLY_ACTIONS_MISS = 7, /* Apply Actions for table-miss. */ OFPTFPT13_MATCH = 8, /* Match property. */ OFPTFPT13_WILDCARDS = 10, /* Wildcards property. */ OFPTFPT13_WRITE_SETFIELD = 12, /* Write Set-Field property. */ OFPTFPT13_WRITE_SETFIELD_MISS = 13, /* Write Set-Field for table-miss. */ OFPTFPT13_APPLY_SETFIELD = 14, /* Apply Set-Field property. */ OFPTFPT13_APPLY_SETFIELD_MISS = 15, /* Apply Set-Field for table-miss. */ OFPTFPT13_EXPERIMENTER = 0xFFFE, /* Experimenter property. */ OFPTFPT13_EXPERIMENTER_MISS = 0xFFFF, /* Experimenter for table-miss. */ }; /* Instructions property */ struct ofp13_table_feature_prop_instructions { ovs_be16 type; /* One of OFPTFPT13_INSTRUCTIONS, OFPTFPT13_INSTRUCTIONS_MISS. */ ovs_be16 length; /* Length in bytes of this property. */ /* Followed by: * - Exactly (length - 4) bytes containing the instruction ids, then * - Exactly (length + 7)/8*8 - (length) (between 0 and 7) * bytes of all-zero bytes */ /* struct ofp11_instruction instruction_ids[0]; List of instructions without any data */ }; OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_instructions) == 4); /* Next Tables property */ struct ofp13_table_feature_prop_next_tables { ovs_be16 type; /* One of OFPTFPT13_NEXT_TABLES, OFPTFPT13_NEXT_TABLES_MISS. */ ovs_be16 length; /* Length in bytes of this property. */ /* Followed by: * - Exactly (length - 4) bytes containing the table_ids, then * - Exactly (length + 7)/8*8 - (length) (between 0 and 7) * bytes of all-zero bytes */ /* uint8_t next_table_ids[0]; */ }; OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_next_tables) == 4); /* Actions property */ struct ofp13_table_feature_prop_actions { ovs_be16 type; /* One of OFPTFPT13_WRITE_ACTIONS, OFPTFPT13_WRITE_ACTIONS_MISS, OFPTFPT13_APPLY_ACTIONS, OFPTFPT13_APPLY_ACTIONS_MISS. */ ovs_be16 length; /* Length in bytes of this property. */ /* Followed by: * - Exactly (length - 4) bytes containing the action_ids, then * - Exactly (length + 7)/8*8 - (length) (between 0 and 7) * bytes of all-zero bytes */ /* struct ofp_action_header action_ids[0]; List of actions without any data */ }; OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_actions) == 4); /* Match, Wildcard or Set-Field property */ struct ofp13_table_feature_prop_oxm { ovs_be16 type; /* One of OFPTFPT13_MATCH, OFPTFPT13_WILDCARDS, OFPTFPT13_WRITE_SETFIELD, OFPTFPT13_WRITE_SETFIELD_MISS, OFPTFPT13_APPLY_SETFIELD, OFPTFPT13_APPLY_SETFIELD_MISS. */ ovs_be16 length; /* Length in bytes of this property. */ /* Followed by: * - Exactly (length - 4) bytes containing the oxm_ids, then * - Exactly (length + 7)/8*8 - (length) (between 0 and 7) * bytes of all-zero bytes */ /* ovs_be32 oxm_ids[0]; Array of OXM headers */ }; OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_oxm) == 4); /* Experimenter table feature property */ struct ofp13_table_feature_prop_experimenter { ovs_be16 type; /* One of OFPTFPT13_EXPERIMENTER, OFPTFPT13_EXPERIMENTER_MISS. */ ovs_be16 length; /* Length in bytes of this property. */ ovs_be32 experimenter; /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ ovs_be32 exp_type; /* Experimenter defined. */ /* Followed by: * - Exactly (length - 12) bytes containing the experimenter data, then * - Exactly (length + 7)/8*8 - (length) (between 0 and 7) * bytes of all-zero bytes */ /* ovs_be32 experimenter_data[0]; */ }; OFP_ASSERT(sizeof(struct ofp13_table_feature_prop_experimenter) == 12); /* Body of reply to OFPMP13_PORT request. If a counter is unsupported, set * the field to all ones. */ struct ofp13_port_stats { struct ofp11_port_stats ps; ovs_be32 duration_sec; /* Time port has been alive in seconds. */ ovs_be32 duration_nsec; /* Time port has been alive in nanoseconds beyond duration_sec. */ }; OFP_ASSERT(sizeof(struct ofp13_port_stats) == 112); /* Body of reply to OFPMP13_QUEUE request */ struct ofp13_queue_stats { struct ofp11_queue_stats qs; ovs_be32 duration_sec; /* Time queue has been alive in seconds. */ ovs_be32 duration_nsec; /* Time queue has been alive in nanoseconds beyond duration_sec. */ }; OFP_ASSERT(sizeof(struct ofp13_queue_stats) == 40); /* Body of reply to OFPMP13_GROUP request */ struct ofp13_group_stats { struct ofp11_group_stats gs; ovs_be32 duration_sec; /* Time group has been alive in seconds. */ ovs_be32 duration_nsec; /* Time group has been alive in nanoseconds beyond duration_sec. */ /* struct ofp11_bucket_counter bucket_stats[]; */ }; OFP_ASSERT(sizeof(struct ofp13_group_stats) == 40); /* Body of OFPMP13_METER and OFPMP13_METER_CONFIG requests. */ struct ofp13_meter_multipart_request { ovs_be32 meter_id; /* Meter instance, or OFPM_ALL. */ uint8_t pad[4]; /* Align to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp13_meter_multipart_request) == 8); /* Statistics for each meter band */ struct ofp13_meter_band_stats { ovs_be64 packet_band_count; /* Number of packets in band. */ ovs_be64 byte_band_count; /* Number of bytes in band. */ }; OFP_ASSERT(sizeof(struct ofp13_meter_band_stats) == 16); /* Body of reply to OFPMP13_METER request. Meter statistics. */ struct ofp13_meter_stats { ovs_be32 meter_id; /* Meter instance. */ ovs_be16 len; /* Length in bytes of this stats. */ uint8_t pad[6]; ovs_be32 flow_count; /* Number of flows bound to meter. */ ovs_be64 packet_in_count; /* Number of packets in input. */ ovs_be64 byte_in_count; /* Number of bytes in input. */ ovs_be32 duration_sec; /* Time meter has been alive in seconds. */ ovs_be32 duration_nsec; /* Time meter has been alive in nanoseconds beyond duration_sec. */ struct ofp13_meter_band_stats band_stats[0]; /* The band_stats length is inferred from the length field. */ }; OFP_ASSERT(sizeof(struct ofp13_meter_stats) == 40); /* Body of reply to OFPMP13_METER_CONFIG request. Meter configuration. */ struct ofp13_meter_config { ovs_be16 length; /* Length of this entry. */ ovs_be16 flags; /* Set of OFPMC_* that apply. */ ovs_be32 meter_id; /* Meter instance. */ /* struct ofp13_meter_band_header bands[0]; The bands length is inferred from the length field. */ }; OFP_ASSERT(sizeof(struct ofp13_meter_config) == 8); /* Body of reply to OFPMP13_METER_FEATURES request. Meter features. */ struct ofp13_meter_features { ovs_be32 max_meter; /* Maximum number of meters. */ ovs_be32 band_types; /* Bitmaps of OFPMBT13_* values supported. */ ovs_be32 capabilities; /* Bitmaps of "ofp13_meter_flags". */ uint8_t max_bands; /* Maximum bands per meters */ uint8_t max_color; /* Maximum color value */ uint8_t pad[2]; }; OFP_ASSERT(sizeof(struct ofp13_meter_features) == 16); /* Asynchronous message configuration. */ /* The body of this is the same as nx_async_config */ /* OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC. */ struct ofp13_async_config { ovs_be32 packet_in_mask[2]; /* Bitmasks of OFPR_* values. */ ovs_be32 port_status_mask[2]; /* Bitmasks of OFPPR_* values. */ ovs_be32 flow_removed_mask[2];/* Bitmasks of OFPRR_* values. */ }; OFP_ASSERT(sizeof(struct ofp13_async_config) == 24); /* Packet received on port (datapath -> controller). */ struct ofp13_packet_in { struct ofp12_packet_in pi; ovs_be64 cookie; /* Cookie of the flow entry that was looked up */ /* Followed by: * - Match * - Exactly 2 all-zero padding bytes, then * - An Ethernet frame whose length is inferred from header.length. * The padding bytes preceding the Ethernet frame ensure that the IP * header (if any) following the Ethernet header is 32-bit aligned. */ /* struct ofp12_match match; */ /* uint8_t pad[2]; Align to 64 bit + 16 bit */ /* uint8_t data[0]; Ethernet frame */ }; OFP_ASSERT(sizeof(struct ofp13_packet_in) == 16); #endif /* openflow/openflow-1.3.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow-1.0.h0000644000000000000000000000013212664352753021420 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.182815687 30 ctime=1456594660.325294369 openvswitch-2.5.0/include/openflow/openflow-1.0.h0000664000175000017500000004615212664352753023120 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* OpenFlow: protocol between controller and datapath. */ #ifndef OPENFLOW_OPENFLOW10_H #define OPENFLOW_OPENFLOW10_H 1 #include /* Port number(s) meaning * --------------- -------------------------------------- * 0x0000 not assigned a meaning by OpenFlow 1.0 * 0x0001...0xfeff "physical" ports * 0xff00...0xfff6 "reserved" but not assigned a meaning by OpenFlow 1.x * 0xfff7...0xffff "reserved" OFPP_* ports with assigned meanings */ /* Ranges. */ #define OFPP_MAX OFP_PORT_C(0xff00) /* Max # of switch ports. */ #define OFPP_FIRST_RESV OFP_PORT_C(0xfff7) /* First assigned reserved port. */ #define OFPP_LAST_RESV OFP_PORT_C(0xffff) /* Last assigned reserved port. */ /* Reserved output "ports". */ #define OFPP_UNSET OFP_PORT_C(0xfff7) /* For OXM_OF_ACTSET_OUTPUT only. */ #define OFPP_IN_PORT OFP_PORT_C(0xfff8) /* Where the packet came in. */ #define OFPP_TABLE OFP_PORT_C(0xfff9) /* Perform actions in flow table. */ #define OFPP_NORMAL OFP_PORT_C(0xfffa) /* Process with normal L2/L3. */ #define OFPP_FLOOD OFP_PORT_C(0xfffb) /* All ports except input port and * ports disabled by STP. */ #define OFPP_ALL OFP_PORT_C(0xfffc) /* All ports except input port. */ #define OFPP_CONTROLLER OFP_PORT_C(0xfffd) /* Send to controller. */ #define OFPP_LOCAL OFP_PORT_C(0xfffe) /* Local openflow "port". */ #define OFPP_NONE OFP_PORT_C(0xffff) /* Not associated with any port. */ /* OpenFlow 1.0 specific capabilities supported by the datapath (struct * ofp_switch_features, member capabilities). */ enum ofp10_capabilities { OFPC10_STP = 1 << 3, /* 802.1d spanning tree. */ OFPC10_RESERVED = 1 << 4, /* Reserved, must not be set. */ }; /* OpenFlow 1.0 specific flags to indicate behavior of the physical port. * These flags are used in ofp10_phy_port to describe the current * configuration. They are used in the ofp10_port_mod message to configure the * port's behavior. */ enum ofp10_port_config { OFPPC10_NO_STP = 1 << 1, /* Disable 802.1D spanning tree on port. */ OFPPC10_NO_RECV_STP = 1 << 3, /* Drop received 802.1D STP packets. */ OFPPC10_NO_FLOOD = 1 << 4, /* Do not include port when flooding. */ #define OFPPC10_ALL (OFPPC_PORT_DOWN | OFPPC10_NO_STP | OFPPC_NO_RECV | \ OFPPC10_NO_RECV_STP | OFPPC10_NO_FLOOD | OFPPC_NO_FWD | \ OFPPC_NO_PACKET_IN) }; /* OpenFlow 1.0 specific current state of the physical port. These are not * configurable from the controller. */ enum ofp10_port_state { /* The OFPPS10_STP_* bits have no effect on switch operation. The * controller must adjust OFPPC_NO_RECV, OFPPC_NO_FWD, and * OFPPC_NO_PACKET_IN appropriately to fully implement an 802.1D spanning * tree. */ OFPPS10_STP_LISTEN = 0 << 8, /* Not learning or relaying frames. */ OFPPS10_STP_LEARN = 1 << 8, /* Learning but not relaying frames. */ OFPPS10_STP_FORWARD = 2 << 8, /* Learning and relaying frames. */ OFPPS10_STP_BLOCK = 3 << 8, /* Not part of spanning tree. */ OFPPS10_STP_MASK = 3 << 8 /* Bit mask for OFPPS10_STP_* values. */ #define OFPPS10_ALL (OFPPS_LINK_DOWN | OFPPS10_STP_MASK) }; /* OpenFlow 1.0 specific features of physical ports available in a datapath. */ enum ofp10_port_features { OFPPF10_COPPER = 1 << 7, /* Copper medium. */ OFPPF10_FIBER = 1 << 8, /* Fiber medium. */ OFPPF10_AUTONEG = 1 << 9, /* Auto-negotiation. */ OFPPF10_PAUSE = 1 << 10, /* Pause. */ OFPPF10_PAUSE_ASYM = 1 << 11 /* Asymmetric pause. */ }; /* Description of a physical port */ struct ofp10_phy_port { ovs_be16 port_no; struct eth_addr hw_addr; char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */ ovs_be32 config; /* Bitmap of OFPPC_* and OFPPC10_* flags. */ ovs_be32 state; /* Bitmap of OFPPS_* and OFPPS10_* flags. */ /* Bitmaps of OFPPF_* and OFPPF10_* that describe features. All bits * zeroed if unsupported or unavailable. */ ovs_be32 curr; /* Current features. */ ovs_be32 advertised; /* Features being advertised by the port. */ ovs_be32 supported; /* Features supported by the port. */ ovs_be32 peer; /* Features advertised by peer. */ }; OFP_ASSERT(sizeof(struct ofp10_phy_port) == 48); /* Modify behavior of the physical port */ struct ofp10_port_mod { ovs_be16 port_no; struct eth_addr hw_addr; /* The hardware address is not configurable. This is used to sanity-check the request, so it must be the same as returned in an ofp10_phy_port struct. */ ovs_be32 config; /* Bitmap of OFPPC_* flags. */ ovs_be32 mask; /* Bitmap of OFPPC_* flags to be changed. */ ovs_be32 advertise; /* Bitmap of "ofp_port_features"s. Zero all bits to prevent any action taking place. */ uint8_t pad[4]; /* Pad to 64-bits. */ }; OFP_ASSERT(sizeof(struct ofp10_port_mod) == 24); struct ofp10_packet_queue { ovs_be32 queue_id; /* id for the specific queue. */ ovs_be16 len; /* Length in bytes of this queue desc. */ uint8_t pad[2]; /* 64-bit alignment. */ /* Followed by any number of queue properties expressed using * ofp_queue_prop_header, to fill out a total of 'len' bytes. */ }; OFP_ASSERT(sizeof(struct ofp10_packet_queue) == 8); /* Query for port queue configuration. */ struct ofp10_queue_get_config_request { ovs_be16 port; /* Port to be queried. Should refer to a valid physical port (i.e. < OFPP_MAX) */ uint8_t pad[2]; /* 32-bit alignment. */ }; OFP_ASSERT(sizeof(struct ofp10_queue_get_config_request) == 4); /* Queue configuration for a given port. */ struct ofp10_queue_get_config_reply { ovs_be16 port; uint8_t pad[6]; /* struct ofp10_packet_queue queues[0]; List of configured queues. */ }; OFP_ASSERT(sizeof(struct ofp10_queue_get_config_reply) == 8); /* Packet received on port (datapath -> controller). */ struct ofp10_packet_in { ovs_be32 buffer_id; /* ID assigned by datapath. */ ovs_be16 total_len; /* Full length of frame. */ ovs_be16 in_port; /* Port on which frame was received. */ uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */ uint8_t pad; uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word, so the IP header is 32-bit aligned. The amount of data is inferred from the length field in the header. Because of padding, offsetof(struct ofp_packet_in, data) == sizeof(struct ofp_packet_in) - 2. */ }; OFP_ASSERT(sizeof(struct ofp10_packet_in) == 12); /* Send packet (controller -> datapath). */ struct ofp10_packet_out { ovs_be32 buffer_id; /* ID assigned by datapath or UINT32_MAX. */ ovs_be16 in_port; /* Packet's input port (OFPP_NONE if none). */ ovs_be16 actions_len; /* Size of action array in bytes. */ /* Followed by: * - Exactly 'actions_len' bytes (possibly 0 bytes, and always a multiple * of 8) containing actions. * - If 'buffer_id' == UINT32_MAX, packet data to fill out the remainder * of the message length. */ }; OFP_ASSERT(sizeof(struct ofp10_packet_out) == 8); /* Flow wildcards. */ enum ofp10_flow_wildcards { OFPFW10_IN_PORT = 1 << 0, /* Switch input port. */ OFPFW10_DL_VLAN = 1 << 1, /* VLAN vid. */ OFPFW10_DL_SRC = 1 << 2, /* Ethernet source address. */ OFPFW10_DL_DST = 1 << 3, /* Ethernet destination address. */ OFPFW10_DL_TYPE = 1 << 4, /* Ethernet frame type. */ OFPFW10_NW_PROTO = 1 << 5, /* IP protocol. */ OFPFW10_TP_SRC = 1 << 6, /* TCP/UDP source port. */ OFPFW10_TP_DST = 1 << 7, /* TCP/UDP destination port. */ /* IP source address wildcard bit count. 0 is exact match, 1 ignores the * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard * the entire field. This is the *opposite* of the usual convention where * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded. */ OFPFW10_NW_SRC_SHIFT = 8, OFPFW10_NW_SRC_BITS = 6, OFPFW10_NW_SRC_MASK = (((1 << OFPFW10_NW_SRC_BITS) - 1) << OFPFW10_NW_SRC_SHIFT), OFPFW10_NW_SRC_ALL = 32 << OFPFW10_NW_SRC_SHIFT, /* IP destination address wildcard bit count. Same format as source. */ OFPFW10_NW_DST_SHIFT = 14, OFPFW10_NW_DST_BITS = 6, OFPFW10_NW_DST_MASK = (((1 << OFPFW10_NW_DST_BITS) - 1) << OFPFW10_NW_DST_SHIFT), OFPFW10_NW_DST_ALL = 32 << OFPFW10_NW_DST_SHIFT, OFPFW10_DL_VLAN_PCP = 1 << 20, /* VLAN priority. */ OFPFW10_NW_TOS = 1 << 21, /* IP ToS (DSCP field, 6 bits). */ /* Wildcard all fields. */ OFPFW10_ALL = ((1 << 22) - 1) }; /* The wildcards for ICMP type and code fields use the transport source * and destination port fields, respectively. */ #define OFPFW10_ICMP_TYPE OFPFW10_TP_SRC #define OFPFW10_ICMP_CODE OFPFW10_TP_DST /* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate * special conditions. All ones indicates that 802.1Q header is not present. */ #define OFP10_VLAN_NONE 0xffff /* Fields to match against flows */ struct ofp10_match { ovs_be32 wildcards; /* Wildcard fields. */ ovs_be16 in_port; /* Input switch port. */ struct eth_addr dl_src; /* Ethernet source address. */ struct eth_addr dl_dst; /* Ethernet destination address. */ ovs_be16 dl_vlan; /* Input VLAN. */ uint8_t dl_vlan_pcp; /* Input VLAN priority. */ uint8_t pad1[1]; /* Align to 64-bits. */ ovs_be16 dl_type; /* Ethernet frame type. */ uint8_t nw_tos; /* IP ToS (DSCP field, 6 bits). */ uint8_t nw_proto; /* IP protocol or lower 8 bits of ARP opcode. */ uint8_t pad2[2]; /* Align to 64-bits. */ ovs_be32 nw_src; /* IP source address. */ ovs_be32 nw_dst; /* IP destination address. */ ovs_be16 tp_src; /* TCP/UDP source port. */ ovs_be16 tp_dst; /* TCP/UDP destination port. */ }; OFP_ASSERT(sizeof(struct ofp10_match) == 40); enum ofp10_flow_mod_flags { OFPFF10_EMERG = 1 << 2 /* Part of "emergency flow cache". */ }; /* Flow setup and teardown (controller -> datapath). */ struct ofp10_flow_mod { struct ofp10_match match; /* Fields to match */ ovs_be64 cookie; /* Opaque controller-issued identifier. */ /* Flow actions. */ ovs_be16 command; /* One of OFPFC_*. */ ovs_be16 idle_timeout; /* Idle time before discarding (seconds). */ ovs_be16 hard_timeout; /* Max time before discarding (seconds). */ ovs_be16 priority; /* Priority level of flow entry. */ ovs_be32 buffer_id; /* Buffered packet to apply to (or -1). Not meaningful for OFPFC_DELETE*. */ ovs_be16 out_port; /* For OFPFC_DELETE* commands, require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. */ ovs_be16 flags; /* One of OFPFF_*. */ /* Followed by OpenFlow actions whose length is inferred from the length * field in the OpenFlow header. */ }; OFP_ASSERT(sizeof(struct ofp10_flow_mod) == 64); /* Flow removed (datapath -> controller). */ struct ofp10_flow_removed { struct ofp10_match match; /* Description of fields. */ ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be16 priority; /* Priority level of flow entry. */ uint8_t reason; /* One of OFPRR_*. */ uint8_t pad[1]; /* Align to 32-bits. */ ovs_be32 duration_sec; /* Time flow was alive in seconds. */ ovs_be32 duration_nsec; /* Time flow was alive in nanoseconds beyond duration_sec. */ ovs_be16 idle_timeout; /* Idle timeout from original flow mod. */ uint8_t pad2[2]; /* Align to 64-bits. */ ovs_be64 packet_count; ovs_be64 byte_count; }; OFP_ASSERT(sizeof(struct ofp10_flow_removed) == 80); /* Statistics request or reply message. */ struct ofp10_stats_msg { struct ofp_header header; ovs_be16 type; /* One of the OFPST_* constants. */ ovs_be16 flags; /* Requests: always 0. * Replies: 0 or OFPSF_REPLY_MORE. */ }; OFP_ASSERT(sizeof(struct ofp10_stats_msg) == 12); /* Stats request of type OFPST_AGGREGATE or OFPST_FLOW. */ struct ofp10_flow_stats_request { struct ofp10_match match; /* Fields to match. */ uint8_t table_id; /* ID of table to read (from ofp_table_stats) or 0xff for all tables. */ uint8_t pad; /* Align to 32 bits. */ ovs_be16 out_port; /* Require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. */ }; OFP_ASSERT(sizeof(struct ofp10_flow_stats_request) == 44); /* Body of reply to OFPST_FLOW request. */ struct ofp10_flow_stats { ovs_be16 length; /* Length of this entry. */ uint8_t table_id; /* ID of table flow came from. */ uint8_t pad; struct ofp10_match match; /* Description of fields. */ ovs_be32 duration_sec; /* Time flow has been alive in seconds. */ ovs_be32 duration_nsec; /* Time flow has been alive in nanoseconds beyond duration_sec. */ ovs_be16 priority; /* Priority of the entry. Only meaningful when this is not an exact-match entry. */ ovs_be16 idle_timeout; /* Number of seconds idle before expiration. */ ovs_be16 hard_timeout; /* Number of seconds before expiration. */ uint8_t pad2[6]; /* Align to 64 bits. */ ovs_32aligned_be64 cookie; /* Opaque controller-issued identifier. */ ovs_32aligned_be64 packet_count; /* Number of packets in flow. */ ovs_32aligned_be64 byte_count; /* Number of bytes in flow. */ /* Followed by OpenFlow actions whose length is inferred from 'length'. */ }; OFP_ASSERT(sizeof(struct ofp10_flow_stats) == 88); /* Body of reply to OFPST_TABLE request. */ struct ofp10_table_stats { uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */ uint8_t pad[3]; /* Align to 32-bits. */ char name[OFP_MAX_TABLE_NAME_LEN]; ovs_be32 wildcards; /* Bitmap of OFPFW10_* wildcards that are supported by the table. */ ovs_be32 max_entries; /* Max number of entries supported. */ ovs_be32 active_count; /* Number of active entries. */ ovs_32aligned_be64 lookup_count; /* # of packets looked up in table. */ ovs_32aligned_be64 matched_count; /* Number of packets that hit table. */ }; OFP_ASSERT(sizeof(struct ofp10_table_stats) == 64); /* Stats request of type OFPST_PORT. */ struct ofp10_port_stats_request { ovs_be16 port_no; /* OFPST_PORT message may request statistics for a single port (specified with port_no) or for all ports (port_no == OFPP_NONE). */ uint8_t pad[6]; }; OFP_ASSERT(sizeof(struct ofp10_port_stats_request) == 8); /* Body of reply to OFPST_PORT request. If a counter is unsupported, set * the field to all ones. */ struct ofp10_port_stats { ovs_be16 port_no; uint8_t pad[6]; /* Align to 64-bits. */ ovs_32aligned_be64 rx_packets; /* Number of received packets. */ ovs_32aligned_be64 tx_packets; /* Number of transmitted packets. */ ovs_32aligned_be64 rx_bytes; /* Number of received bytes. */ ovs_32aligned_be64 tx_bytes; /* Number of transmitted bytes. */ ovs_32aligned_be64 rx_dropped; /* Number of packets dropped by RX. */ ovs_32aligned_be64 tx_dropped; /* Number of packets dropped by TX. */ ovs_32aligned_be64 rx_errors; /* Number of receive errors. This is a super-set of receive errors and should be great than or equal to the sum of all rx_*_err values. */ ovs_32aligned_be64 tx_errors; /* Number of transmit errors. This is a super-set of transmit errors. */ ovs_32aligned_be64 rx_frame_err; /* Number of frame alignment errors. */ ovs_32aligned_be64 rx_over_err; /* Number of packets with RX overrun. */ ovs_32aligned_be64 rx_crc_err; /* Number of CRC errors. */ ovs_32aligned_be64 collisions; /* Number of collisions. */ }; OFP_ASSERT(sizeof(struct ofp10_port_stats) == 104); /* All ones is used to indicate all queues in a port (for stats retrieval). */ #define OFPQ_ALL 0xffffffff /* Body for stats request of type OFPST_QUEUE. */ struct ofp10_queue_stats_request { ovs_be16 port_no; /* All ports if OFPP_ALL. */ uint8_t pad[2]; /* Align to 32-bits. */ ovs_be32 queue_id; /* All queues if OFPQ_ALL. */ }; OFP_ASSERT(sizeof(struct ofp10_queue_stats_request) == 8); /* Body for stats reply of type OFPST_QUEUE consists of an array of this * structure type. */ struct ofp10_queue_stats { ovs_be16 port_no; uint8_t pad[2]; /* Align to 32-bits. */ ovs_be32 queue_id; /* Queue id. */ ovs_32aligned_be64 tx_bytes; /* Number of transmitted bytes. */ ovs_32aligned_be64 tx_packets; /* Number of transmitted packets. */ ovs_32aligned_be64 tx_errors; /* # of packets dropped due to overrun. */ }; OFP_ASSERT(sizeof(struct ofp10_queue_stats) == 32); /* Vendor extension stats message. */ struct ofp10_vendor_stats_msg { struct ofp10_stats_msg osm; /* Type OFPST_VENDOR. */ ovs_be32 vendor; /* Vendor ID: * - MSB 0: low-order bytes are IEEE OUI. * - MSB != 0: defined by OpenFlow * consortium. */ /* Followed by vendor-defined arbitrary additional data. */ }; OFP_ASSERT(sizeof(struct ofp10_vendor_stats_msg) == 16); #endif /* openflow/openflow-1.0.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/nicira-ext.h0000644000000000000000000000013212664352753021336 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.178815523 30 ctime=1456594660.325294369 openvswitch-2.5.0/include/openflow/nicira-ext.h0000664000175000017500000013014312664352753023030 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENFLOW_NICIRA_EXT_H #define OPENFLOW_NICIRA_EXT_H 1 #include #include /* The following vendor extensions, proposed by Nicira, are not yet * standardized, so they are not included in openflow.h. Some of them may be * suitable for standardization; others we never expect to standardize. */ /* Nicira vendor-specific error messages extension. * * OpenFlow 1.0 has a set of predefined error types (OFPET_*) and codes (which * are specific to each type). It does not have any provision for * vendor-specific error codes, and it does not even provide "generic" error * codes that can apply to problems not anticipated by the OpenFlow * specification authors. * * This extension attempts to address the problem by adding a generic "error * vendor extension". The extension works as follows: use NXET_VENDOR as type * and NXVC_VENDOR_ERROR as code, followed by struct nx_vendor_error with * vendor-specific details, followed by at least 64 bytes of the failed * request. * * It would be better to have a type-specific vendor extension, e.g. so that * OFPET_BAD_ACTION could be used with vendor-specific code values. But * OFPET_BAD_ACTION and most other standardized types already specify that * their 'data' values are (the start of) the OpenFlow message being replied * to, so there is no room to insert a vendor ID. * * Currently this extension is only implemented by Open vSwitch, but it seems * like a reasonable candidate for future standardization. */ /* This is a random number to avoid accidental collision with any other * vendor's extension. */ #define NXET_VENDOR 0xb0c2 /* ofp_error msg 'code' values for NXET_VENDOR. */ enum nx_vendor_code { NXVC_VENDOR_ERROR /* 'data' contains struct nx_vendor_error. */ }; /* 'data' for 'type' == NXET_VENDOR, 'code' == NXVC_VENDOR_ERROR. */ struct nx_vendor_error { ovs_be32 vendor; /* Vendor ID as in struct ofp_vendor_header. */ ovs_be16 type; /* Vendor-defined type. */ ovs_be16 code; /* Vendor-defined subtype. */ /* Followed by at least the first 64 bytes of the failed request. */ }; /* Nicira vendor requests and replies. */ /* Header for Nicira vendor requests and replies. */ struct nicira_header { struct ofp_header header; ovs_be32 vendor; /* NX_VENDOR_ID. */ ovs_be32 subtype; /* See the NXT numbers in ofp-msgs.h. */ }; OFP_ASSERT(sizeof(struct nicira_header) == 16); /* Header for Nicira vendor stats request and reply messages in OpenFlow * 1.0. */ struct nicira10_stats_msg { struct ofp10_vendor_stats_msg vsm; /* Vendor NX_VENDOR_ID. */ ovs_be32 subtype; /* One of NXST_* below. */ uint8_t pad[4]; /* Align to 64-bits. */ }; OFP_ASSERT(sizeof(struct nicira10_stats_msg) == 24); /* Header for Nicira vendor stats request and reply messages in OpenFlow * 1.1. */ struct nicira11_stats_msg { struct ofp11_vendor_stats_msg vsm; /* Vendor NX_VENDOR_ID. */ ovs_be32 subtype; /* One of NXST_* below. */ }; OFP_ASSERT(sizeof(struct nicira11_stats_msg) == 24); /* Fields to use when hashing flows. */ enum nx_hash_fields { /* Ethernet source address (NXM_OF_ETH_SRC) only. */ NX_HASH_FIELDS_ETH_SRC, /* L2 through L4, symmetric across src/dst. Specifically, each of the * following fields, if present, is hashed (slashes separate symmetric * pairs): * * - NXM_OF_ETH_DST / NXM_OF_ETH_SRC * - NXM_OF_ETH_TYPE * - The VID bits from NXM_OF_VLAN_TCI, ignoring PCP and CFI. * - NXM_OF_IP_PROTO * - NXM_OF_IP_SRC / NXM_OF_IP_DST * - NXM_OF_TCP_SRC / NXM_OF_TCP_DST */ NX_HASH_FIELDS_SYMMETRIC_L4, /* L3+L4 only, including the following fields: * * - NXM_OF_IP_PROTO * - NXM_OF_IP_SRC / NXM_OF_IP_DST * - NXM_OF_SCTP_SRC / NXM_OF_SCTP_DST * - NXM_OF_TCP_SRC / NXM_OF_TCP_DST */ NX_HASH_FIELDS_SYMMETRIC_L3L4, /* L3+L4 only with UDP ports, including the following fields: * * - NXM_OF_IP_PROTO * - NXM_OF_IP_SRC / NXM_OF_IP_DST * - NXM_OF_SCTP_SRC / NXM_OF_SCTP_DST * - NXM_OF_TCP_SRC / NXM_OF_TCP_DST * - NXM_OF_UDP_SRC / NXM_OF_UDP_DST */ NX_HASH_FIELDS_SYMMETRIC_L3L4_UDP }; /* This command enables or disables an Open vSwitch extension that allows a * controller to specify the OpenFlow table to which a flow should be added, * instead of having the switch decide which table is most appropriate as * required by OpenFlow 1.0. Because NXM was designed as an extension to * OpenFlow 1.0, the extension applies equally to ofp10_flow_mod and * nx_flow_mod. By default, the extension is disabled. * * When this feature is enabled, Open vSwitch treats struct ofp10_flow_mod's * and struct nx_flow_mod's 16-bit 'command' member as two separate fields. * The upper 8 bits are used as the table ID, the lower 8 bits specify the * command as usual. A table ID of 0xff is treated like a wildcarded table ID. * * The specific treatment of the table ID depends on the type of flow mod: * * - OFPFC_ADD: Given a specific table ID, the flow is always placed in that * table. If an identical flow already exists in that table only, then it * is replaced. If the flow cannot be placed in the specified table, * either because the table is full or because the table cannot support * flows of the given type, the switch replies with an OFPFMFC_TABLE_FULL * error. (A controller can distinguish these cases by comparing the * current and maximum number of entries reported in ofp_table_stats.) * * If the table ID is wildcarded, the switch picks an appropriate table * itself. If an identical flow already exist in the selected flow table, * then it is replaced. The choice of table might depend on the flows * that are already in the switch; for example, if one table fills up then * the switch might fall back to another one. * * - OFPFC_MODIFY, OFPFC_DELETE: Given a specific table ID, only flows * within that table are matched and modified or deleted. If the table ID * is wildcarded, flows within any table may be matched and modified or * deleted. * * - OFPFC_MODIFY_STRICT, OFPFC_DELETE_STRICT: Given a specific table ID, * only a flow within that table may be matched and modified or deleted. * If the table ID is wildcarded and exactly one flow within any table * matches, then it is modified or deleted; if flows in more than one * table match, then none is modified or deleted. */ struct nx_flow_mod_table_id { uint8_t set; /* Nonzero to enable, zero to disable. */ uint8_t pad[7]; }; OFP_ASSERT(sizeof(struct nx_flow_mod_table_id) == 8); enum nx_packet_in_format { NXPIF_OPENFLOW10 = 0, /* Standard OpenFlow 1.0 compatible. */ NXPIF_NXM = 1 /* Nicira Extended. */ }; /* NXT_SET_PACKET_IN_FORMAT request. */ struct nx_set_packet_in_format { ovs_be32 format; /* One of NXPIF_*. */ }; OFP_ASSERT(sizeof(struct nx_set_packet_in_format) == 4); /* NXT_PACKET_IN (analogous to OFPT_PACKET_IN). * * NXT_PACKET_IN is similar to the OpenFlow 1.2 OFPT_PACKET_IN. The * differences are: * * - NXT_PACKET_IN includes the cookie of the rule that triggered the * message. (OpenFlow 1.3 OFPT_PACKET_IN also includes the cookie.) * * - The metadata fields use NXM (instead of OXM) field numbers. * * Open vSwitch 1.9.0 and later omits metadata fields that are zero (as allowed * by OpenFlow 1.2). Earlier versions included all implemented metadata * fields. * * Open vSwitch does not include non-metadata in the nx_match, because by * definition that information can be found in the packet itself. The format * and the standards allow this, however, so controllers should be prepared to * tolerate future changes. * * The NXM format is convenient for reporting metadata values, but it is * important not to interpret the format as matching against a flow, because it * does not. Nothing is being matched; arbitrary metadata masks would not be * meaningful. * * Whereas in most cases a controller can expect to only get back NXM fields * that it set up itself (e.g. flow dumps will ordinarily report only NXM * fields from flows that the controller added), NXT_PACKET_IN messages might * contain fields that the controller does not understand, because the switch * might support fields (new registers, new protocols, etc.) that the * controller does not. The controller must prepared to tolerate these. * * The 'cookie' field has no meaning when 'reason' is OFPR_NO_MATCH. In this * case it should be UINT64_MAX. */ struct nx_packet_in { ovs_be32 buffer_id; /* ID assigned by datapath. */ ovs_be16 total_len; /* Full length of frame. */ uint8_t reason; /* Reason packet is sent (one of OFPR_*). */ uint8_t table_id; /* ID of the table that was looked up. */ ovs_be64 cookie; /* Cookie of the rule that was looked up. */ ovs_be16 match_len; /* Size of nx_match. */ uint8_t pad[6]; /* Align to 64-bits. */ /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes, then * - Exactly 2 all-zero padding bytes, then * - An Ethernet frame whose length is inferred from nxh.header.length. * * The padding bytes preceding the Ethernet frame ensure that the IP * header (if any) following the Ethernet header is 32-bit aligned. */ /* uint8_t nxm_fields[...]; */ /* NXM headers. */ /* uint8_t pad[2]; */ /* Align to 64 bit + 16 bit. */ /* uint8_t data[0]; */ /* Ethernet frame. */ }; OFP_ASSERT(sizeof(struct nx_packet_in) == 24); /* Configures the "role" of the sending controller. The default role is: * * - Other (NX_ROLE_OTHER), which allows the controller access to all * OpenFlow features. * * The other possible roles are a related pair: * * - Master (NX_ROLE_MASTER) is equivalent to Other, except that there may * be at most one Master controller at a time: when a controller * configures itself as Master, any existing Master is demoted to the * Slave role. * * - Slave (NX_ROLE_SLAVE) allows the controller read-only access to * OpenFlow features. In particular attempts to modify the flow table * will be rejected with an OFPBRC_EPERM error. * * Slave controllers do not receive OFPT_PACKET_IN or OFPT_FLOW_REMOVED * messages, but they do receive OFPT_PORT_STATUS messages. */ struct nx_role_request { ovs_be32 role; /* One of NX_ROLE_*. */ }; OFP_ASSERT(sizeof(struct nx_role_request) == 4); enum nx_role { NX_ROLE_OTHER, /* Default role, full access. */ NX_ROLE_MASTER, /* Full access, at most one. */ NX_ROLE_SLAVE /* Read-only access. */ }; /* NXT_SET_ASYNC_CONFIG. * * Sent by a controller, this message configures the asynchronous messages that * the controller wants to receive. Element 0 in each array specifies messages * of interest when the controller has an "other" or "master" role; element 1, * when the controller has a "slave" role. * * Each array element is a bitmask in which a 0-bit disables receiving a * particular message and a 1-bit enables receiving it. Each bit controls the * message whose 'reason' corresponds to the bit index. For example, the bit * with value 1<<2 == 4 in port_status_mask[1] determines whether the * controller will receive OFPT_PORT_STATUS messages with reason OFPPR_MODIFY * (value 2) when the controller has a "slave" role. * * As a side effect, for service controllers, this message changes the * miss_send_len from default of zero to OFP_DEFAULT_MISS_SEND_LEN (128). */ struct nx_async_config { ovs_be32 packet_in_mask[2]; /* Bitmasks of OFPR_* values. */ ovs_be32 port_status_mask[2]; /* Bitmasks of OFPRR_* values. */ ovs_be32 flow_removed_mask[2]; /* Bitmasks of OFPPR_* values. */ }; OFP_ASSERT(sizeof(struct nx_async_config) == 24); /* Flexible flow specifications (aka NXM = Nicira Extended Match). * * OpenFlow 1.0 has "struct ofp10_match" for specifying flow matches. This * structure is fixed-length and hence difficult to extend. This section * describes a more flexible, variable-length flow match, called "nx_match" for * short, that is also supported by Open vSwitch. This section also defines a * replacement for each OpenFlow message that includes struct ofp10_match. * * OpenFlow 1.2+ introduced OpenFlow Extensible Match (OXM), adapting * the design of NXM. The format of NXM and OXM are compatible. * * * Format * ====== * * An nx_match is a sequence of zero or more "nxm_entry"s, which are * type-length-value (TLV) entries, each 5 to 259 (inclusive) bytes long. * "nxm_entry"s are not aligned on or padded to any multibyte boundary. The * first 4 bytes of an nxm_entry are its "header", followed by the entry's * "body". * * An nxm_entry's header is interpreted as a 32-bit word in network byte order: * * |<-------------------- nxm_type ------------------>| * | | * |31 16 15 9| 8 7 0 * +----------------------------------+---------------+--+------------------+ * | nxm_vendor | nxm_field |hm| nxm_length | * +----------------------------------+---------------+--+------------------+ * * The most-significant 23 bits of the header are collectively "nxm_type". * Bits 16...31 are "nxm_vendor", one of OFPXMC12_* values. In case of * NXM, it's either OFPXMC12_NXM_0 or OFPXMC12_NXM_1. * Bits 9...15 are "nxm_field", which is a vendor-specific value. nxm_type * normally designates a protocol header, such as the Ethernet type, but it * can also refer to packet metadata, such as the switch port on which a packet * arrived. * * Bit 8 is "nxm_hasmask" (labeled "hm" above for space reasons). The meaning * of this bit is explained later. * * The least-significant 8 bits are "nxm_length", a positive integer. The * length of the nxm_entry, including the header, is exactly 4 + nxm_length * bytes. * * For a given nxm_vendor, nxm_field, and nxm_hasmask value, nxm_length is a * constant. It is included only to allow software to minimally parse * "nxm_entry"s of unknown types. (Similarly, for a given nxm_vendor, * nxm_field, and nxm_length, nxm_hasmask is a constant.) * * * Semantics * ========= * * A zero-length nx_match (one with no "nxm_entry"s) matches every packet. * * An nxm_entry places a constraint on the packets matched by the nx_match: * * - If nxm_hasmask is 0, the nxm_entry's body contains a value for the * field, called "nxm_value". The nx_match matches only packets in which * the field equals nxm_value. * * - If nxm_hasmask is 1, then the nxm_entry's body contains a value for the * field (nxm_value), followed by a bitmask of the same length as the * value, called "nxm_mask". For each 1-bit in position J in nxm_mask, the * nx_match matches only packets for which bit J in the given field's value * matches bit J in nxm_value. A 0-bit in nxm_mask causes the * corresponding bit in nxm_value is ignored (it should be 0; Open vSwitch * may enforce this someday), as is the corresponding bit in the field's * value. (The sense of the nxm_mask bits is the opposite of that used by * the "wildcards" member of struct ofp10_match.) * * When nxm_hasmask is 1, nxm_length is always even. * * An all-zero-bits nxm_mask is equivalent to omitting the nxm_entry * entirely. An all-one-bits nxm_mask is equivalent to specifying 0 for * nxm_hasmask. * * When there are multiple "nxm_entry"s, all of the constraints must be met. * * * Mask Restrictions * ================= * * Masks may be restricted: * * - Some nxm_types may not support masked wildcards, that is, nxm_hasmask * must always be 0 when these fields are specified. For example, the * field that identifies the port on which a packet was received may not be * masked. * * - Some nxm_types that do support masked wildcards may only support certain * nxm_mask patterns. For example, fields that have IPv4 address values * may be restricted to CIDR masks. * * These restrictions should be noted in specifications for individual fields. * A switch may accept an nxm_hasmask or nxm_mask value that the specification * disallows, if the switch correctly implements support for that nxm_hasmask * or nxm_mask value. A switch must reject an attempt to set up a flow that * contains a nxm_hasmask or nxm_mask value that it does not support. * * * Prerequisite Restrictions * ========================= * * The presence of an nxm_entry with a given nxm_type may be restricted based * on the presence of or values of other "nxm_entry"s. For example: * * - An nxm_entry for nxm_type=NXM_OF_IP_TOS is allowed only if it is * preceded by another entry with nxm_type=NXM_OF_ETH_TYPE, nxm_hasmask=0, * and nxm_value=0x0800. That is, matching on the IP source address is * allowed only if the Ethernet type is explicitly set to IP. * * - An nxm_entry for nxm_type=NXM_OF_TCP_SRC is allowed only if it is * preceded by an entry with nxm_type=NXM_OF_ETH_TYPE, nxm_hasmask=0, and * nxm_value either 0x0800 or 0x86dd, and another with * nxm_type=NXM_OF_IP_PROTO, nxm_hasmask=0, nxm_value=6, in that order. * That is, matching on the TCP source port is allowed only if the Ethernet * type is IP or IPv6 and the IP protocol is TCP. * * These restrictions should be noted in specifications for individual fields. * A switch may implement relaxed versions of these restrictions. A switch * must reject an attempt to set up a flow that violates its restrictions. * * * Ordering Restrictions * ===================== * * An nxm_entry that has prerequisite restrictions must appear after the * "nxm_entry"s for its prerequisites. Ordering of "nxm_entry"s within an * nx_match is not otherwise constrained. * * Any given nxm_type may appear in an nx_match at most once. * * * nxm_entry Examples * ================== * * These examples show the format of a single nxm_entry with particular * nxm_hasmask and nxm_length values. The diagrams are labeled with field * numbers and byte indexes. * * * 8-bit nxm_value, nxm_hasmask=1, nxm_length=2: * * 0 3 4 5 * +------------+---+---+ * | header | v | m | * +------------+---+---+ * * * 16-bit nxm_value, nxm_hasmask=0, nxm_length=2: * * 0 3 4 5 * +------------+------+ * | header | value| * +------------+------+ * * * 32-bit nxm_value, nxm_hasmask=0, nxm_length=4: * * 0 3 4 7 * +------------+-------------+ * | header | nxm_value | * +------------+-------------+ * * * 48-bit nxm_value, nxm_hasmask=0, nxm_length=6: * * 0 3 4 9 * +------------+------------------+ * | header | nxm_value | * +------------+------------------+ * * * 48-bit nxm_value, nxm_hasmask=1, nxm_length=12: * * 0 3 4 9 10 15 * +------------+------------------+------------------+ * | header | nxm_value | nxm_mask | * +------------+------------------+------------------+ * * * Error Reporting * =============== * * A switch should report an error in an nx_match using error type * OFPET_BAD_REQUEST and one of the NXBRC_NXM_* codes. Ideally the switch * should report a specific error code, if one is assigned for the particular * problem, but NXBRC_NXM_INVALID is also available to report a generic * nx_match error. */ /* Number of registers allocated NXM field IDs. */ #define NXM_NX_MAX_REGS 16 /* Bits in the value of NXM_NX_IP_FRAG. */ #define NX_IP_FRAG_ANY (1 << 0) /* Is this a fragment? */ #define NX_IP_FRAG_LATER (1 << 1) /* Is this a fragment with nonzero offset? */ /* Bits in the value of NXM_NX_TUN_FLAGS. */ #define NX_TUN_FLAG_OAM (1 << 0) /* Is this an OAM packet? */ /* ## --------------------- ## */ /* ## Requests and replies. ## */ /* ## --------------------- ## */ enum nx_flow_format { NXFF_OPENFLOW10 = 0, /* Standard OpenFlow 1.0 compatible. */ NXFF_NXM = 2 /* Nicira extended match. */ }; /* NXT_SET_FLOW_FORMAT request. */ struct nx_set_flow_format { ovs_be32 format; /* One of NXFF_*. */ }; OFP_ASSERT(sizeof(struct nx_set_flow_format) == 4); /* NXT_FLOW_MOD (analogous to OFPT_FLOW_MOD). * * It is possible to limit flow deletions and modifications to certain * cookies by using the NXM_NX_COOKIE(_W) matches. The "cookie" field * is used only to add or modify flow cookies. */ struct nx_flow_mod { ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be16 command; /* OFPFC_* + possibly a table ID (see comment * on struct nx_flow_mod_table_id). */ ovs_be16 idle_timeout; /* Idle time before discarding (seconds). */ ovs_be16 hard_timeout; /* Max time before discarding (seconds). */ ovs_be16 priority; /* Priority level of flow entry. */ ovs_be32 buffer_id; /* Buffered packet to apply to (or -1). Not meaningful for OFPFC_DELETE*. */ ovs_be16 out_port; /* For OFPFC_DELETE* commands, require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. */ ovs_be16 flags; /* One of OFPFF_*. */ ovs_be16 match_len; /* Size of nx_match. */ uint8_t pad[6]; /* Align to 64-bits. */ /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes, then * - Actions to fill out the remainder of the message length (always a * multiple of 8). */ }; OFP_ASSERT(sizeof(struct nx_flow_mod) == 32); /* NXT_FLOW_REMOVED (analogous to OFPT_FLOW_REMOVED). * * 'table_id' is present only in Open vSwitch 1.11 and later. In earlier * versions of Open vSwitch, this is a padding byte that is always zeroed. * Therefore, a 'table_id' value of 0 indicates that the table ID is not known, * and other values may be interpreted as one more than the flow's former table * ID. */ struct nx_flow_removed { ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be16 priority; /* Priority level of flow entry. */ uint8_t reason; /* One of OFPRR_*. */ uint8_t table_id; /* Flow's former table ID, plus one. */ ovs_be32 duration_sec; /* Time flow was alive in seconds. */ ovs_be32 duration_nsec; /* Time flow was alive in nanoseconds beyond duration_sec. */ ovs_be16 idle_timeout; /* Idle timeout from original flow mod. */ ovs_be16 match_len; /* Size of nx_match. */ ovs_be64 packet_count; ovs_be64 byte_count; /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes. */ }; OFP_ASSERT(sizeof(struct nx_flow_removed) == 40); /* Nicira vendor stats request of type NXST_FLOW (analogous to OFPST_FLOW * request). * * It is possible to limit matches to certain cookies by using the * NXM_NX_COOKIE and NXM_NX_COOKIE_W matches. */ struct nx_flow_stats_request { ovs_be16 out_port; /* Require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. */ ovs_be16 match_len; /* Length of nx_match. */ uint8_t table_id; /* ID of table to read (from ofp_table_stats) or 0xff for all tables. */ uint8_t pad[3]; /* Align to 64 bits. */ /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes, which must also exactly fill out the length of the * message. */ }; OFP_ASSERT(sizeof(struct nx_flow_stats_request) == 8); /* Body for Nicira vendor stats reply of type NXST_FLOW (analogous to * OFPST_FLOW reply). * * The values of 'idle_age' and 'hard_age' are only meaningful when talking to * a switch that implements the NXT_FLOW_AGE extension. Zero means that the * true value is unknown, perhaps because hardware does not track the value. * (Zero is also the value that one should ordinarily expect to see talking to * a switch that does not implement NXT_FLOW_AGE, since those switches zero the * padding bytes that these fields replaced.) A nonzero value X represents X-1 * seconds. A value of 65535 represents 65534 or more seconds. * * 'idle_age' is the number of seconds that the flow has been idle, that is, * the number of seconds since a packet passed through the flow. 'hard_age' is * the number of seconds since the flow was last modified (e.g. OFPFC_MODIFY or * OFPFC_MODIFY_STRICT). (The 'duration_*' fields are the elapsed time since * the flow was added, regardless of subsequent modifications.) * * For a flow with an idle or hard timeout, 'idle_age' or 'hard_age', * respectively, will ordinarily be smaller than the timeout, but flow * expiration times are only approximate and so one must be prepared to * tolerate expirations that occur somewhat early or late. */ struct nx_flow_stats { ovs_be16 length; /* Length of this entry. */ uint8_t table_id; /* ID of table flow came from. */ uint8_t pad; ovs_be32 duration_sec; /* Time flow has been alive in seconds. */ ovs_be32 duration_nsec; /* Time flow has been alive in nanoseconds beyond duration_sec. */ ovs_be16 priority; /* Priority of the entry. */ ovs_be16 idle_timeout; /* Number of seconds idle before expiration. */ ovs_be16 hard_timeout; /* Number of seconds before expiration. */ ovs_be16 match_len; /* Length of nx_match. */ ovs_be16 idle_age; /* Seconds since last packet, plus one. */ ovs_be16 hard_age; /* Seconds since last modification, plus one. */ ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be64 packet_count; /* Number of packets, UINT64_MAX if unknown. */ ovs_be64 byte_count; /* Number of bytes, UINT64_MAX if unknown. */ /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes, then * - Actions to fill out the remainder 'length' bytes (always a multiple * of 8). */ }; OFP_ASSERT(sizeof(struct nx_flow_stats) == 48); /* Nicira vendor stats request of type NXST_AGGREGATE (analogous to * OFPST_AGGREGATE request). * * The reply format is identical to the reply format for OFPST_AGGREGATE, * except for the header. */ struct nx_aggregate_stats_request { ovs_be16 out_port; /* Require matching entries to include this as an output port. A value of OFPP_NONE indicates no restriction. */ ovs_be16 match_len; /* Length of nx_match. */ uint8_t table_id; /* ID of table to read (from ofp_table_stats) or 0xff for all tables. */ uint8_t pad[3]; /* Align to 64 bits. */ /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes, which must also exactly fill out the length of the * message. */ }; OFP_ASSERT(sizeof(struct nx_aggregate_stats_request) == 8); /* NXT_SET_CONTROLLER_ID. * * Each OpenFlow controller connection has a 16-bit identifier that is * initially 0. This message changes the connection's ID to 'id'. * * Controller connection IDs need not be unique. * * The NXAST_CONTROLLER action is the only current user of controller * connection IDs. */ struct nx_controller_id { uint8_t zero[6]; /* Must be zero. */ ovs_be16 controller_id; /* New controller connection ID. */ }; OFP_ASSERT(sizeof(struct nx_controller_id) == 8); /* Flow Table Monitoring * ===================== * * NXST_FLOW_MONITOR allows a controller to keep track of changes to OpenFlow * flow table(s) or subsets of them, with the following workflow: * * 1. The controller sends an NXST_FLOW_MONITOR request to begin monitoring * flows. The 'id' in the request must be unique among all monitors that * the controller has started and not yet canceled on this OpenFlow * connection. * * 2. The switch responds with an NXST_FLOW_MONITOR reply. If the request's * 'flags' included NXFMF_INITIAL, the reply includes all the flows that * matched the request at the time of the request (with event NXFME_ADDED). * If 'flags' did not include NXFMF_INITIAL, the reply is empty. * * The reply uses the xid of the request (as do all replies to OpenFlow * requests). * * 3. Whenever a change to a flow table entry matches some outstanding monitor * request's criteria and flags, the switch sends a notification to the * controller as an additional NXST_FLOW_MONITOR reply with xid 0. * * When multiple outstanding monitors match a single change, only a single * notification is sent. This merged notification includes the information * requested in any of the individual monitors. That is, if any of the * matching monitors requests actions (NXFMF_ACTIONS), the notification * includes actions, and if any of the monitors request full changes for the * controller's own changes (NXFMF_OWN), the controller's own changes will * be included in full. * * 4. The controller may cancel a monitor with NXT_FLOW_MONITOR_CANCEL. No * further notifications will be sent on the basis of the canceled monitor * afterward. * * * Buffer Management * ================= * * OpenFlow messages for flow monitor notifications can overflow the buffer * space available to the switch, either temporarily (e.g. due to network * conditions slowing OpenFlow traffic) or more permanently (e.g. the sustained * rate of flow table change exceeds the network bandwidth between switch and * controller). * * When Open vSwitch's notification buffer space reaches a limiting threshold, * OVS reacts as follows: * * 1. OVS sends an NXT_FLOW_MONITOR_PAUSED message to the controller, following * all the already queued notifications. After it receives this message, * the controller knows that its view of the flow table, as represented by * flow monitor notifications, is incomplete. * * 2. As long as the notification buffer is not empty: * * - NXMFE_ADD and NXFME_MODIFIED notifications will not be sent. * * - NXFME_DELETED notifications will still be sent, but only for flows * that existed before OVS sent NXT_FLOW_MONITOR_PAUSED. * * - NXFME_ABBREV notifications will not be sent. They are treated as * the expanded version (and therefore only the NXFME_DELETED * components, if any, are sent). * * 3. When the notification buffer empties, OVS sends NXFME_ADD notifications * for flows added since the buffer reached its limit and NXFME_MODIFIED * notifications for flows that existed before the limit was reached and * changed after the limit was reached. * * 4. OVS sends an NXT_FLOW_MONITOR_RESUMED message to the controller. After * it receives this message, the controller knows that its view of the flow * table, as represented by flow monitor notifications, is again complete. * * This allows the maximum buffer space requirement for notifications to be * bounded by the limit plus the maximum number of supported flows. * * * "Flow Removed" messages * ======================= * * The flow monitor mechanism is independent of OFPT_FLOW_REMOVED and * NXT_FLOW_REMOVED. Flow monitor updates for deletion are sent if * NXFMF_DELETE is set on a monitor, regardless of whether the * OFPFF_SEND_FLOW_REM flag was set when the flow was added. */ /* NXST_FLOW_MONITOR request. * * The NXST_FLOW_MONITOR request's body consists of an array of zero or more * instances of this structure. The request arranges to monitor the flows * that match the specified criteria, which are interpreted in the same way as * for NXST_FLOW. * * 'id' identifies a particular monitor for the purpose of allowing it to be * canceled later with NXT_FLOW_MONITOR_CANCEL. 'id' must be unique among * existing monitors that have not already been canceled. * * The reply includes the initial flow matches for monitors that have the * NXFMF_INITIAL flag set. No single flow will be included in the reply more * than once, even if more than one requested monitor matches that flow. The * reply will be empty if none of the monitors has NXFMF_INITIAL set or if none * of the monitors initially matches any flows. * * For NXFMF_ADD, an event will be reported if 'out_port' matches against the * actions of the flow being added or, for a flow that is replacing an existing * flow, if 'out_port' matches against the actions of the flow being replaced. * For NXFMF_DELETE, 'out_port' matches against the actions of a flow being * deleted. For NXFMF_MODIFY, an event will be reported if 'out_port' matches * either the old or the new actions. */ struct nx_flow_monitor_request { ovs_be32 id; /* Controller-assigned ID for this monitor. */ ovs_be16 flags; /* NXFMF_*. */ ovs_be16 out_port; /* Required output port, if not OFPP_NONE. */ ovs_be16 match_len; /* Length of nx_match. */ uint8_t table_id; /* One table's ID or 0xff for all tables. */ uint8_t zeros[5]; /* Align to 64 bits (must be zero). */ /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes. */ }; OFP_ASSERT(sizeof(struct nx_flow_monitor_request) == 16); /* 'flags' bits in struct nx_flow_monitor_request. */ enum nx_flow_monitor_flags { /* When to send updates. */ NXFMF_INITIAL = 1 << 0, /* Initially matching flows. */ NXFMF_ADD = 1 << 1, /* New matching flows as they are added. */ NXFMF_DELETE = 1 << 2, /* Old matching flows as they are removed. */ NXFMF_MODIFY = 1 << 3, /* Matching flows as they are changed. */ /* What to include in updates. */ NXFMF_ACTIONS = 1 << 4, /* If set, actions are included. */ NXFMF_OWN = 1 << 5, /* If set, include own changes in full. */ }; /* NXST_FLOW_MONITOR reply header. * * The body of an NXST_FLOW_MONITOR reply is an array of variable-length * structures, each of which begins with this header. The 'length' member may * be used to traverse the array, and the 'event' member may be used to * determine the particular structure. * * Every instance is a multiple of 8 bytes long. */ struct nx_flow_update_header { ovs_be16 length; /* Length of this entry. */ ovs_be16 event; /* One of NXFME_*. */ /* ...other data depending on 'event'... */ }; OFP_ASSERT(sizeof(struct nx_flow_update_header) == 4); /* 'event' values in struct nx_flow_update_header. */ enum nx_flow_update_event { /* struct nx_flow_update_full. */ NXFME_ADDED = 0, /* Flow was added. */ NXFME_DELETED = 1, /* Flow was deleted. */ NXFME_MODIFIED = 2, /* Flow (generally its actions) was changed. */ /* struct nx_flow_update_abbrev. */ NXFME_ABBREV = 3, /* Abbreviated reply. */ }; /* NXST_FLOW_MONITOR reply for NXFME_ADDED, NXFME_DELETED, and * NXFME_MODIFIED. */ struct nx_flow_update_full { ovs_be16 length; /* Length is 24. */ ovs_be16 event; /* One of NXFME_*. */ ovs_be16 reason; /* OFPRR_* for NXFME_DELETED, else zero. */ ovs_be16 priority; /* Priority of the entry. */ ovs_be16 idle_timeout; /* Number of seconds idle before expiration. */ ovs_be16 hard_timeout; /* Number of seconds before expiration. */ ovs_be16 match_len; /* Length of nx_match. */ uint8_t table_id; /* ID of flow's table. */ uint8_t pad; /* Reserved, currently zeroed. */ ovs_be64 cookie; /* Opaque controller-issued identifier. */ /* Followed by: * - Exactly match_len (possibly 0) bytes containing the nx_match, then * - Exactly (match_len + 7)/8*8 - match_len (between 0 and 7) bytes of * all-zero bytes, then * - Actions to fill out the remainder 'length' bytes (always a multiple * of 8). If NXFMF_ACTIONS was not specified, or 'event' is * NXFME_DELETED, no actions are included. */ }; OFP_ASSERT(sizeof(struct nx_flow_update_full) == 24); /* NXST_FLOW_MONITOR reply for NXFME_ABBREV. * * When the controller does not specify NXFMF_OWN in a monitor request, any * flow tables changes due to the controller's own requests (on the same * OpenFlow channel) will be abbreviated, when possible, to this form, which * simply specifies the 'xid' of the OpenFlow request (e.g. an OFPT_FLOW_MOD or * NXT_FLOW_MOD) that caused the change. * * Some changes cannot be abbreviated and will be sent in full: * * - Changes that only partially succeed. This can happen if, for example, * a flow_mod with type OFPFC_MODIFY affects multiple flows, but only some * of those modifications succeed (e.g. due to hardware limitations). * * This cannot occur with the Open vSwitch software datapath. This also * cannot occur in Open vSwitch 2.4 and later, because these versions only * execute any flow modifications if all of them will succeed. * * - Changes that race with conflicting changes made by other controllers or * other flow_mods (not separated by barriers) by the same controller. * * This cannot occur with the current Open vSwitch implementation * (regardless of datapath) because Open vSwitch internally serializes * potentially conflicting changes. * * - Changes that occur when flow notification is paused (see "Buffer * Management" above). * * A flow_mod that does not change the flow table will not trigger any * notification, even an abbreviated one. For example, a "modify" or "delete" * flow_mod that does not match any flows will not trigger a notification. * Whether an "add" or "modify" that specifies all the same parameters that a * flow already has triggers a notification is unspecified and subject to * change in future versions of Open vSwitch. * * OVS will always send the notifications for a given flow table change before * the reply to a OFPT_BARRIER_REQUEST request that follows the flow table * change. Thus, if the controller does not receive an abbreviated (or * unabbreviated) notification for a flow_mod before the next * OFPT_BARRIER_REPLY, it will never receive one. */ struct nx_flow_update_abbrev { ovs_be16 length; /* Length is 8. */ ovs_be16 event; /* NXFME_ABBREV. */ ovs_be32 xid; /* Controller-specified xid from flow_mod. */ }; OFP_ASSERT(sizeof(struct nx_flow_update_abbrev) == 8); /* NXT_FLOW_MONITOR_CANCEL. * * Used by a controller to cancel an outstanding monitor. */ struct nx_flow_monitor_cancel { ovs_be32 id; /* 'id' from nx_flow_monitor_request. */ }; OFP_ASSERT(sizeof(struct nx_flow_monitor_cancel) == 4); /* Variable-length option TLV table maintenance commands. * * The option in Type-Length-Value format is widely used in tunnel options, * e.g., the base Geneve header is followed by zero or more options in TLV * format. Each option consists of a four byte option header and a variable * amount of option data interpreted according to the type. The generic TLV * format in tunnel options is as following: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Option Class | Type |R|R|R| Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Variable Option Data | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * In order to work with this variable-length options in TLV format in * tunnel options, we need to maintain a mapping table between an option * TLV (defined by ) and an NXM field that can be * operated on for the purposes of matches, actions, etc. This mapping * must be explicitly specified by the user. * * There are two primary groups of OpenFlow messages that are introduced * as Nicira extensions: modification commands (add, delete, clear mappings) * and table status request/reply to dump the current table along with switch * information. * * Note that mappings should not be changed while they are in active use by * a flow. The result of doing so is undefined. */ /* TLV table commands */ enum nx_tlv_table_mod_command { NXTTMC_ADD, /* New mappings (fails if an option is already mapped). */ NXTTMC_DELETE, /* Delete mappings, identified by index * (unmapped options are ignored). */ NXTTMC_CLEAR, /* Clear all mappings. Additional information in this command is ignored. */ }; /* Map between an option TLV and an NXM field. */ struct nx_tlv_map { ovs_be16 option_class; /* TLV class. */ uint8_t option_type; /* TLV type. */ uint8_t option_len; /* TLV length (multiple of 4). */ ovs_be16 index; /* NXM_NX_TUN_METADATA index */ uint8_t pad[2]; }; OFP_ASSERT(sizeof(struct nx_tlv_map) == 8); /* NXT_TLV_TABLE_MOD. * * Use to configure a mapping between option TLVs (class, type, length) * and NXM fields (NXM_NX_TUN_METADATA where 'index' is ). * * This command is atomic: all operations on different options will * either succeed or fail. */ struct nx_tlv_table_mod { ovs_be16 command; /* One of NTTTMC_* */ uint8_t pad[6]; /* struct nx_tlv_map[0]; Array of maps between indicies and option TLVs. The number of elements is inferred from the length field in the header. */ }; OFP_ASSERT(sizeof(struct nx_tlv_table_mod) == 8); /* NXT_TLV_TABLE_REPLY. * * Issued in reponse to an NXT_TLV_TABLE_REQUEST to give information * about the current status of the TLV table in the switch. Provides * both static information about the switch's capabilities as well as * the configured TLV table. */ struct nx_tlv_table_reply { ovs_be32 max_option_space; /* Maximum total of option sizes supported. */ ovs_be16 max_fields; /* Maximum number of match fields supported. */ uint8_t reserved[10]; /* struct nx_tlv_map[0]; Array of maps between indicies and option TLVs. The number of elements is inferred from the length field in the header. */ }; OFP_ASSERT(sizeof(struct nx_tlv_table_reply) == 16); #endif /* openflow/nicira-ext.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow-1.4.h0000644000000000000000000000013212664352753021424 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.182815687 30 ctime=1456594660.329294538 openvswitch-2.5.0/include/openflow/openflow-1.4.h0000664000175000017500000004476312664352753023132 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2014 The Board of Trustees of The Leland Stanford * Junior University * Copyright (c) 2011, 2012 Open Networking Foundation * * We are making the OpenFlow specification and associated documentation * (Software) available for public use and benefit with the expectation * that others will use, modify and enhance the Software and contribute * those enhancements back to the community. However, since we would * like to make the Software available for broadest use, with as few * restrictions as possible permission is hereby granted, free of * charge, to any person obtaining a copy of this Software to deal in * the Software under the copyrights without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * The name and trademarks of copyright holder(s) may NOT be used in * advertising or publicity pertaining to the Software or any * derivatives without specific, written prior permission. */ /* OpenFlow: protocol between controller and datapath. */ #ifndef OPENFLOW_14_H #define OPENFLOW_14_H 1 #include /* ## ---------- ## */ /* ## ofp14_port ## */ /* ## ---------- ## */ /* Port description property types. */ enum ofp_port_desc_prop_type { OFPPDPT14_ETHERNET = 0, /* Ethernet property. */ OFPPDPT14_OPTICAL = 1, /* Optical property. */ OFPPDPT14_EXPERIMENTER = 0xFFFF, /* Experimenter property. */ }; /* Ethernet port description property. */ struct ofp14_port_desc_prop_ethernet { ovs_be16 type; /* OFPPDPT14_ETHERNET. */ ovs_be16 length; /* Length in bytes of this property. */ uint8_t pad[4]; /* Align to 64 bits. */ /* Bitmaps of OFPPF_* that describe features. All bits zeroed if * unsupported or unavailable. */ ovs_be32 curr; /* Current features. */ ovs_be32 advertised; /* Features being advertised by the port. */ ovs_be32 supported; /* Features supported by the port. */ ovs_be32 peer; /* Features advertised by peer. */ ovs_be32 curr_speed; /* Current port bitrate in kbps. */ ovs_be32 max_speed; /* Max port bitrate in kbps */ }; OFP_ASSERT(sizeof(struct ofp14_port_desc_prop_ethernet) == 32); struct ofp14_port { ovs_be32 port_no; ovs_be16 length; uint8_t pad[2]; struct eth_addr hw_addr; uint8_t pad2[2]; /* Align to 64 bits. */ char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */ ovs_be32 config; /* Bitmap of OFPPC_* flags. */ ovs_be32 state; /* Bitmap of OFPPS_* flags. */ /* Followed by 0 or more OFPPDPT14_* properties. */ }; OFP_ASSERT(sizeof(struct ofp14_port) == 40); /* ## -------------- ## */ /* ## ofp14_port_mod ## */ /* ## -------------- ## */ enum ofp14_port_mod_prop_type { OFPPMPT14_ETHERNET = 0, /* Ethernet property. */ OFPPMPT14_OPTICAL = 1, /* Optical property. */ OFPPMPT14_EXPERIMENTER = 0xFFFF, /* Experimenter property. */ }; /* Ethernet port mod property. */ struct ofp14_port_mod_prop_ethernet { ovs_be16 type; /* OFPPMPT14_ETHERNET. */ ovs_be16 length; /* Length in bytes of this property. */ ovs_be32 advertise; /* Bitmap of OFPPF_*. Zero all bits to prevent any action taking place. */ }; OFP_ASSERT(sizeof(struct ofp14_port_mod_prop_ethernet) == 8); struct ofp14_port_mod { ovs_be32 port_no; uint8_t pad[4]; struct eth_addr hw_addr; uint8_t pad2[2]; ovs_be32 config; /* Bitmap of OFPPC_* flags. */ ovs_be32 mask; /* Bitmap of OFPPC_* flags to be changed. */ /* Followed by 0 or more OFPPMPT14_* properties. */ }; OFP_ASSERT(sizeof(struct ofp14_port_mod) == 24); /* ## --------------- ## */ /* ## ofp14_table_mod ## */ /* ## --------------- ## */ enum ofp14_table_mod_prop_type { OFPTMPT14_EVICTION = 0x2, /* Eviction property. */ OFPTMPT14_VACANCY = 0x3, /* Vacancy property. */ OFPTMPT14_EXPERIMENTER = 0xFFFF, /* Experimenter property. */ }; enum ofp14_table_mod_prop_eviction_flag { OFPTMPEF14_OTHER = 1 << 0, /* Using other factors. */ OFPTMPEF14_IMPORTANCE = 1 << 1, /* Using flow entry importance. */ OFPTMPEF14_LIFETIME = 1 << 2, /* Using flow entry lifetime. */ }; /* What changed about the table */ enum ofp14_table_reason { OFPTR_VACANCY_DOWN = 3, /* Vacancy down threshold event. */ OFPTR_VACANCY_UP = 4, /* Vacancy up threshold event. */ OFPTR_N_REASONS /* Denotes number of reasons. */ }; struct ofp14_table_mod_prop_eviction { ovs_be16 type; /* OFPTMPT14_EVICTION. */ ovs_be16 length; /* Length in bytes of this property. */ ovs_be32 flags; /* Bitmap of OFPTMPEF14_* flags */ }; OFP_ASSERT(sizeof(struct ofp14_table_mod_prop_eviction) == 8); struct ofp14_table_mod_prop_vacancy { ovs_be16 type; /* OFPTMPT14_VACANCY. */ ovs_be16 length; /* Length in bytes of this property. */ uint8_t vacancy_down; /* Vacancy threshold when space decreases (%). */ uint8_t vacancy_up; /* Vacancy threshold when space increases (%). */ uint8_t vacancy; /* Current vacancy (%) - only in ofp14_table_desc. */ uint8_t pad[1]; /* Align to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp14_table_mod_prop_vacancy) == 8); struct ofp14_table_mod { uint8_t table_id; /* ID of the table, OFPTT_ALL indicates all tables */ uint8_t pad[3]; /* Pad to 32 bits */ ovs_be32 config; /* Bitmap of OFPTC_* flags */ /* Followed by 0 or more OFPTMPT14_* properties. */ }; OFP_ASSERT(sizeof(struct ofp14_table_mod) == 8); /* Body of reply to OFPMP_TABLE_DESC request. */ struct ofp14_table_desc { ovs_be16 length; /* Length is padded to 64 bits. */ uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */ uint8_t pad[1]; /* Align to 32-bits. */ ovs_be32 config; /* Bitmap of OFPTC_* values. */ /* Followed by 0 or more OFPTMPT14_* properties. */ }; OFP_ASSERT(sizeof(struct ofp14_table_desc) == 8); /* ## ---------------- ## */ /* ## ofp14_port_stats ## */ /* ## ---------------- ## */ enum ofp14_port_stats_prop_type { OFPPSPT14_ETHERNET = 0, /* Ethernet property. */ OFPPSPT14_OPTICAL = 1, /* Optical property. */ OFPPSPT14_EXPERIMENTER = 0xFFFF, /* Experimenter property. */ }; struct ofp14_port_stats_prop_ethernet { ovs_be16 type; /* OFPPSPT14_ETHERNET. */ ovs_be16 length; /* Length in bytes of this property. */ uint8_t pad[4]; /* Align to 64 bits. */ ovs_be64 rx_frame_err; /* Number of frame alignment errors. */ ovs_be64 rx_over_err; /* Number of packets with RX overrun. */ ovs_be64 rx_crc_err; /* Number of CRC errors. */ ovs_be64 collisions; /* Number of collisions. */ }; OFP_ASSERT(sizeof(struct ofp14_port_stats_prop_ethernet) == 40); struct ofp14_port_stats { ovs_be16 length; /* Length of this entry. */ uint8_t pad[2]; /* Align to 64 bits. */ ovs_be32 port_no; ovs_be32 duration_sec; /* Time port has been alive in seconds. */ ovs_be32 duration_nsec; /* Time port has been alive in nanoseconds beyond duration_sec. */ ovs_be64 rx_packets; /* Number of received packets. */ ovs_be64 tx_packets; /* Number of transmitted packets. */ ovs_be64 rx_bytes; /* Number of received bytes. */ ovs_be64 tx_bytes; /* Number of transmitted bytes. */ ovs_be64 rx_dropped; /* Number of packets dropped by RX. */ ovs_be64 tx_dropped; /* Number of packets dropped by TX. */ ovs_be64 rx_errors; /* Number of receive errors. This is a super-set of more specific receive errors and should be greater than or equal to the sum of all rx_*_err values in properties. */ ovs_be64 tx_errors; /* Number of transmit errors. This is a super-set of more specific transmit errors and should be greater than or equal to the sum of all tx_*_err values (none currently defined.) */ /* Followed by 0 or more OFPPSPT14_* properties. */ }; OFP_ASSERT(sizeof(struct ofp14_port_stats) == 80); /* ## ----------------- ## */ /* ## ofp14_queue_stats ## */ /* ## ----------------- ## */ struct ofp14_queue_stats { ovs_be16 length; /* Length of this entry. */ uint8_t pad[6]; /* Align to 64 bits. */ struct ofp13_queue_stats qs; /* Followed by 0 or more properties (none yet defined). */ }; OFP_ASSERT(sizeof(struct ofp14_queue_stats) == 48); /* ## -------------- ## */ /* ## Miscellaneous. ## */ /* ## -------------- ## */ /* Common header for all async config Properties */ struct ofp14_async_config_prop_header { ovs_be16 type; /* One of OFPACPT_*. */ ovs_be16 length; /* Length in bytes of this property. */ }; OFP_ASSERT(sizeof(struct ofp14_async_config_prop_header) == 4); /* Asynchronous message configuration. * OFPT_GET_ASYNC_REPLY or OFPT_SET_ASYNC. */ struct ofp14_async_config { struct ofp_header header; /* Async config Property list - 0 or more */ struct ofp14_async_config_prop_header properties[0]; }; OFP_ASSERT(sizeof(struct ofp14_async_config) == 8); /* Request forward reason */ enum ofp14_requestforward_reason { OFPRFR_GROUP_MOD = 0, /* Forward group mod requests. */ OFPRFR_METER_MOD = 1, /* Forward meter mod requests. */ OFPRFR_N_REASONS /* Denotes number of reasons. */ }; /* Async Config property types. * Low order bit cleared indicates a property for the slave role. * Low order bit set indicates a property for the master/equal role. */ enum ofp14_async_config_prop_type { OFPACPT_PACKET_IN_SLAVE = 0, /* Packet-in mask for slave. */ OFPACPT_PACKET_IN_MASTER = 1, /* Packet-in mask for master. */ OFPACPT_PORT_STATUS_SLAVE = 2, /* Port-status mask for slave. */ OFPACPT_PORT_STATUS_MASTER = 3, /* Port-status mask for master. */ OFPACPT_FLOW_REMOVED_SLAVE = 4, /* Flow removed mask for slave. */ OFPACPT_FLOW_REMOVED_MASTER = 5, /* Flow removed mask for master. */ OFPACPT_ROLE_STATUS_SLAVE = 6, /* Role status mask for slave. */ OFPACPT_ROLE_STATUS_MASTER = 7, /* Role status mask for master. */ OFPACPT_TABLE_STATUS_SLAVE = 8, /* Table status mask for slave. */ OFPACPT_TABLE_STATUS_MASTER = 9, /* Table status mask for master. */ OFPACPT_REQUESTFORWARD_SLAVE = 10, /* RequestForward mask for slave. */ OFPACPT_REQUESTFORWARD_MASTER = 11, /* RequestForward mask for master. */ OFPTFPT_EXPERIMENTER_SLAVE = 0xFFFE, /* Experimenter for slave. */ OFPTFPT_EXPERIMENTER_MASTER = 0xFFFF, /* Experimenter for master. */ }; /* Various reason based properties */ struct ofp14_async_config_prop_reasons { /* 'type' is one of OFPACPT_PACKET_IN_*, OFPACPT_PORT_STATUS_*, * OFPACPT_FLOW_REMOVED_*, OFPACPT_ROLE_STATUS_*, * OFPACPT_TABLE_STATUS_*, OFPACPT_REQUESTFORWARD_*. */ ovs_be16 type; ovs_be16 length; /* Length in bytes of this property. */ ovs_be32 mask; /* Bitmasks of reason values. */ }; OFP_ASSERT(sizeof(struct ofp14_async_config_prop_reasons) == 8); /* Experimenter async config property */ struct ofp14_async_config_prop_experimenter { ovs_be16 type; /* One of OFPTFPT_EXPERIMENTER_SLAVE, OFPTFPT_EXPERIMENTER_MASTER. */ ovs_be16 length; /* Length in bytes of this property. */ ovs_be32 experimenter; /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ ovs_be32 exp_type; /* Experimenter defined. */ /* Followed by: * - Exactly (length - 12) bytes containing the experimenter data, then * - Exactly (length + 7)/8*8 - (length) (between 0 and 7) * bytes of all-zero bytes */ }; OFP_ASSERT(sizeof(struct ofp14_async_config_prop_experimenter) == 12); /* Common header for all Role Properties */ struct ofp14_role_prop_header { ovs_be16 type; /* One of OFPRPT_*. */ ovs_be16 length; /* Length in bytes of this property. */ }; OFP_ASSERT(sizeof(struct ofp14_role_prop_header) == 4); /* Role status event message. */ struct ofp14_role_status { ovs_be32 role; /* One of OFPCR_ROLE_*. */ uint8_t reason; /* One of OFPCRR_*. */ uint8_t pad[3]; /* Align to 64 bits. */ ovs_be64 generation_id; /* Master Election Generation Id */ /* Followed by a list of struct ofp14_role_prop_header */ }; OFP_ASSERT(sizeof(struct ofp14_role_status) == 16); /* What changed about the controller role */ enum ofp14_controller_role_reason { OFPCRR_MASTER_REQUEST = 0, /* Another controller asked to be master. */ OFPCRR_CONFIG = 1, /* Configuration changed on the switch. */ OFPCRR_EXPERIMENTER = 2, /* Experimenter data changed. */ OFPCRR_N_REASONS /* Denotes number of reasons. */ }; /* Role property types. */ enum ofp14_role_prop_type { OFPRPT_EXPERIMENTER = 0xFFFF, /* Experimenter property. */ }; /* Experimenter role property */ struct ofp14_role_prop_experimenter { ovs_be16 type; /* One of OFPRPT_EXPERIMENTER. */ ovs_be16 length; /* Length in bytes of this property. */ ovs_be32 experimenter; /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ ovs_be32 exp_type; /* Experimenter defined. */ /* Followed by: * - Exactly (length - 12) bytes containing the experimenter data, then * - Exactly (length + 7)/8*8 - (length) (between 0 and 7) * bytes of all-zero bytes */ }; OFP_ASSERT(sizeof(struct ofp14_role_prop_experimenter) == 12); /* Group/Meter request forwarding. */ struct ofp14_requestforward { struct ofp_header request; /* Request being forwarded. */ }; OFP_ASSERT(sizeof(struct ofp14_requestforward) == 8); /* Bundle control message types */ enum ofp14_bundle_ctrl_type { OFPBCT_OPEN_REQUEST = 0, OFPBCT_OPEN_REPLY = 1, OFPBCT_CLOSE_REQUEST = 2, OFPBCT_CLOSE_REPLY = 3, OFPBCT_COMMIT_REQUEST = 4, OFPBCT_COMMIT_REPLY = 5, OFPBCT_DISCARD_REQUEST = 6, OFPBCT_DISCARD_REPLY = 7, }; /* Bundle configuration flags. */ enum ofp14_bundle_flags { OFPBF_ATOMIC = 1 << 0, /* Execute atomically. */ OFPBF_ORDERED = 1 << 1, /* Execute in specified order. */ }; /* Message structure for OFPT_BUNDLE_CONTROL and OFPT_BUNDLE_ADD_MESSAGE. */ struct ofp14_bundle_ctrl_msg { ovs_be32 bundle_id; /* Identify the bundle. */ ovs_be16 type; /* OFPT_BUNDLE_CONTROL: one of OFPBCT_*. * OFPT_BUNDLE_ADD_MESSAGE: not used. */ ovs_be16 flags; /* Bitmap of OFPBF_* flags. */ /* Followed by: * - For OFPT_BUNDLE_ADD_MESSAGE only, an encapsulated OpenFlow message, * beginning with an ofp_header whose xid is identical to this message's * outer xid. * - For OFPT_BUNDLE_ADD_MESSAGE only, and only if at least one property is * present, 0 to 7 bytes of padding to align on a 64-bit boundary. * - Zero or more properties (see struct ofp14_bundle_prop_header). */ }; OFP_ASSERT(sizeof(struct ofp14_bundle_ctrl_msg) == 8); /* Body for ofp14_multipart_request of type OFPMP_FLOW_MONITOR. * * The OFPMP_FLOW_MONITOR request's body consists of an array of zero or more * instances of this structure. The request arranges to monitor the flows * that match the specified criteria, which are interpreted in the same way as * for OFPMP_FLOW. * * 'id' identifies a particular monitor for the purpose of allowing it to be * canceled later with OFPFMC_DELETE. 'id' must be unique among * existing monitors that have not already been canceled. */ struct ofp14_flow_monitor_request { ovs_be32 monitor_id; /* Controller-assigned ID for this monitor. */ ovs_be32 out_port; /* Required output port, if not OFPP_ANY. */ ovs_be32 out_group; /* Required output port, if not OFPG_ANY. */ ovs_be16 flags; /* OFPMF14_*. */ uint8_t table_id; /* One table's ID or OFPTT_ALL (all tables). */ uint8_t command; /* One of OFPFMC14_*. */ /* Followed by an ofp11_match structure. */ }; OFP_ASSERT(sizeof(struct ofp14_flow_monitor_request) == 16); /* Flow monitor commands */ enum ofp14_flow_monitor_command { OFPFMC14_ADD = 0, /* New flow monitor. */ OFPFMC14_MODIFY = 1, /* Modify existing flow monitor. */ OFPFMC14_DELETE = 2, /* Delete/cancel existing flow monitor. */ }; /* 'flags' bits in struct of_flow_monitor_request. */ enum ofp14_flow_monitor_flags { /* When to send updates. */ /* Common to NX and OpenFlow 1.4 */ OFPFMF14_INITIAL = 1 << 0, /* Initially matching flows. */ OFPFMF14_ADD = 1 << 1, /* New matching flows as they are added. */ OFPFMF14_REMOVED = 1 << 2, /* Old matching flows as they are removed. */ OFPFMF14_MODIFY = 1 << 3, /* Matching flows as they are changed. */ /* What to include in updates. */ /* Common to NX and OpenFlow 1.4 */ OFPFMF14_INSTRUCTIONS = 1 << 4, /* If set, instructions are included. */ OFPFMF14_NO_ABBREV = 1 << 5, /* If set, include own changes in full. */ /* OpenFlow 1.4 */ OFPFMF14_ONLY_OWN = 1 << 6, /* If set, don't include other controllers. */ }; #endif /* openflow/openflow-1.4.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow-1.1.h0000644000000000000000000000013212664352753021421 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.182815687 30 ctime=1456594660.325294369 openvswitch-2.5.0/include/openflow/openflow-1.1.h0000664000175000017500000007060512664352753023121 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2011, 2012, 2013, 2014 The Board of Trustees of The Leland Stanford * Junior University * * We are making the OpenFlow specification and associated documentation * (Software) available for public use and benefit with the expectation * that others will use, modify and enhance the Software and contribute * those enhancements back to the community. However, since we would * like to make the Software available for broadest use, with as few * restrictions as possible permission is hereby granted, free of * charge, to any person obtaining a copy of this Software to deal in * the Software under the copyrights without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * The name and trademarks of copyright holder(s) may NOT be used in * advertising or publicity pertaining to the Software or any * derivatives without specific, written prior permission. */ /* * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* OpenFlow: protocol between controller and datapath. */ #ifndef OPENFLOW_11_H #define OPENFLOW_11_H 1 #include /* OpenFlow 1.1 uses 32-bit port numbers. Open vSwitch, for now, uses OpenFlow * 1.0 port numbers internally. We map them to OpenFlow 1.0 as follows: * * OF1.1 <=> OF1.0 * ----------------------- --------------- * 0x00000000...0x0000feff <=> 0x0000...0xfeff "physical" ports * 0x0000ff00...0xfffffeff <=> not supported * 0xffffff00...0xffffffff <=> 0xff00...0xffff "reserved" OFPP_* ports * * OFPP11_OFFSET is the value that must be added or subtracted to convert * an OpenFlow 1.0 reserved port number to or from, respectively, the * corresponding OpenFlow 1.1 reserved port number. */ #define OFPP11_MAX OFP11_PORT_C(0xffffff00) #define OFPP11_OFFSET 0xffff0000 /* OFPP11_MAX - OFPP_MAX */ /* Reserved wildcard port used only for flow mod (delete) and flow stats * requests. Selects all flows regardless of output port * (including flows with no output port) * * Define it via OFPP_NONE (0xFFFF) so that OFPP_ANY is still an enum ofp_port */ #define OFPP_ANY OFPP_NONE /* OpenFlow 1.1 port config flags are just the common flags. */ #define OFPPC11_ALL \ (OFPPC_PORT_DOWN | OFPPC_NO_RECV | OFPPC_NO_FWD | OFPPC_NO_PACKET_IN) /* OpenFlow 1.1 specific current state of the physical port. These are not * configurable from the controller. */ enum ofp11_port_state { OFPPS11_BLOCKED = 1 << 1, /* Port is blocked */ OFPPS11_LIVE = 1 << 2, /* Live for Fast Failover Group. */ #define OFPPS11_ALL (OFPPS_LINK_DOWN | OFPPS11_BLOCKED | OFPPS11_LIVE) }; /* OpenFlow 1.1 specific features of ports available in a datapath. */ enum ofp11_port_features { OFPPF11_40GB_FD = 1 << 7, /* 40 Gb full-duplex rate support. */ OFPPF11_100GB_FD = 1 << 8, /* 100 Gb full-duplex rate support. */ OFPPF11_1TB_FD = 1 << 9, /* 1 Tb full-duplex rate support. */ OFPPF11_OTHER = 1 << 10, /* Other rate, not in the list. */ OFPPF11_COPPER = 1 << 11, /* Copper medium. */ OFPPF11_FIBER = 1 << 12, /* Fiber medium. */ OFPPF11_AUTONEG = 1 << 13, /* Auto-negotiation. */ OFPPF11_PAUSE = 1 << 14, /* Pause. */ OFPPF11_PAUSE_ASYM = 1 << 15 /* Asymmetric pause. */ #define OFPPF11_ALL ((1 << 16) - 1) }; /* Description of a port */ struct ofp11_port { ovs_be32 port_no; uint8_t pad[4]; struct eth_addr hw_addr; uint8_t pad2[2]; /* Align to 64 bits. */ char name[OFP_MAX_PORT_NAME_LEN]; /* Null-terminated */ ovs_be32 config; /* Bitmap of OFPPC_* flags. */ ovs_be32 state; /* Bitmap of OFPPS_* and OFPPS11_* flags. */ /* Bitmaps of OFPPF_* and OFPPF11_* that describe features. All bits * zeroed if unsupported or unavailable. */ ovs_be32 curr; /* Current features. */ ovs_be32 advertised; /* Features being advertised by the port. */ ovs_be32 supported; /* Features supported by the port. */ ovs_be32 peer; /* Features advertised by peer. */ ovs_be32 curr_speed; /* Current port bitrate in kbps. */ ovs_be32 max_speed; /* Max port bitrate in kbps */ }; OFP_ASSERT(sizeof(struct ofp11_port) == 64); /* Modify behavior of the physical port */ struct ofp11_port_mod { ovs_be32 port_no; uint8_t pad[4]; struct eth_addr hw_addr; /* The hardware address is not configurable. This is used to sanity-check the request, so it must be the same as returned in an ofp11_port struct. */ uint8_t pad2[2]; /* Pad to 64 bits. */ ovs_be32 config; /* Bitmap of OFPPC_* flags. */ ovs_be32 mask; /* Bitmap of OFPPC_* flags to be changed. */ ovs_be32 advertise; /* Bitmap of OFPPF_* and OFPPF11_*. Zero all bits to prevent any action taking place. */ uint8_t pad3[4]; /* Pad to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp11_port_mod) == 32); /* Group setup and teardown (controller -> datapath). */ struct ofp11_group_mod { ovs_be16 command; /* One of OFPGC11_*. */ uint8_t type; /* One of OFPGT11_*. */ uint8_t pad; /* Pad to 64 bits. */ ovs_be32 group_id; /* Group identifier. */ /* struct ofp11_bucket buckets[0]; The bucket length is inferred from the length field in the header. */ }; OFP_ASSERT(sizeof(struct ofp11_group_mod) == 8); /* Query for port queue configuration. */ struct ofp11_queue_get_config_request { ovs_be32 port; /* Port to be queried. Should refer to a valid physical port (i.e. < OFPP_MAX) */ uint8_t pad[4]; }; OFP_ASSERT(sizeof(struct ofp11_queue_get_config_request) == 8); /* Group commands */ enum ofp11_group_mod_command { OFPGC11_ADD, /* New group. */ OFPGC11_MODIFY, /* Modify all matching groups. */ OFPGC11_DELETE, /* Delete all matching groups. */ }; /* OpenFlow 1.1 specific capabilities supported by the datapath (struct * ofp_switch_features, member capabilities). */ enum ofp11_capabilities { OFPC11_GROUP_STATS = 1 << 3, /* Group statistics. */ }; #define OFPMT11_STANDARD_LENGTH 88 struct ofp11_match_header { ovs_be16 type; /* One of OFPMT_* */ ovs_be16 length; /* Length of match */ }; OFP_ASSERT(sizeof(struct ofp11_match_header) == 4); /* Fields to match against flows */ struct ofp11_match { struct ofp11_match_header omh; ovs_be32 in_port; /* Input switch port. */ ovs_be32 wildcards; /* Wildcard fields. */ struct eth_addr dl_src; /* Ethernet source address. */ struct eth_addr dl_src_mask; /* Ethernet source address mask. */ struct eth_addr dl_dst; /* Ethernet destination address. */ struct eth_addr dl_dst_mask; /* Ethernet destination address mask. */ ovs_be16 dl_vlan; /* Input VLAN id. */ uint8_t dl_vlan_pcp; /* Input VLAN priority. */ uint8_t pad1[1]; /* Align to 32-bits */ ovs_be16 dl_type; /* Ethernet frame type. */ uint8_t nw_tos; /* IP ToS (actually DSCP field, 6 bits). */ uint8_t nw_proto; /* IP protocol or lower 8 bits of ARP opcode. */ ovs_be32 nw_src; /* IP source address. */ ovs_be32 nw_src_mask; /* IP source address mask. */ ovs_be32 nw_dst; /* IP destination address. */ ovs_be32 nw_dst_mask; /* IP destination address mask. */ ovs_be16 tp_src; /* TCP/UDP/SCTP source port. */ ovs_be16 tp_dst; /* TCP/UDP/SCTP destination port. */ ovs_be32 mpls_label; /* MPLS label. */ uint8_t mpls_tc; /* MPLS TC. */ uint8_t pad2[3]; /* Align to 64-bits */ ovs_be64 metadata; /* Metadata passed between tables. */ ovs_be64 metadata_mask; /* Mask for metadata. */ }; OFP_ASSERT(sizeof(struct ofp11_match) == OFPMT11_STANDARD_LENGTH); /* Flow wildcards. */ enum ofp11_flow_wildcards { OFPFW11_IN_PORT = 1 << 0, /* Switch input port. */ OFPFW11_DL_VLAN = 1 << 1, /* VLAN id. */ OFPFW11_DL_VLAN_PCP = 1 << 2, /* VLAN priority. */ OFPFW11_DL_TYPE = 1 << 3, /* Ethernet frame type. */ OFPFW11_NW_TOS = 1 << 4, /* IP ToS (DSCP field, 6 bits). */ OFPFW11_NW_PROTO = 1 << 5, /* IP protocol. */ OFPFW11_TP_SRC = 1 << 6, /* TCP/UDP/SCTP source port. */ OFPFW11_TP_DST = 1 << 7, /* TCP/UDP/SCTP destination port. */ OFPFW11_MPLS_LABEL = 1 << 8, /* MPLS label. */ OFPFW11_MPLS_TC = 1 << 9, /* MPLS TC. */ /* Wildcard all fields. */ OFPFW11_ALL = ((1 << 10) - 1) }; /* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate * special conditions. */ enum ofp11_vlan_id { OFPVID11_ANY = 0xfffe, /* Indicate that a VLAN id is set but don't care about it's value. Note: only valid when specifying the VLAN id in a match */ OFPVID11_NONE = 0xffff, /* No VLAN id was set. */ }; enum ofp11_instruction_type { OFPIT11_GOTO_TABLE = 1, /* Setup the next table in the lookup pipeline */ OFPIT11_WRITE_METADATA = 2, /* Setup the metadata field for use later in pipeline */ OFPIT11_WRITE_ACTIONS = 3, /* Write the action(s) onto the datapath action set */ OFPIT11_APPLY_ACTIONS = 4, /* Applies the action(s) immediately */ OFPIT11_CLEAR_ACTIONS = 5, /* Clears all actions from the datapath action set */ OFPIT11_EXPERIMENTER = 0xFFFF /* Experimenter instruction */ }; #define OFP11_INSTRUCTION_ALIGN 8 /* Generic ofp_instruction structure. */ struct ofp11_instruction { ovs_be16 type; /* Instruction type */ ovs_be16 len; /* Length of this struct in bytes. */ uint8_t pad[4]; /* Align to 64-bits */ }; OFP_ASSERT(sizeof(struct ofp11_instruction) == 8); /* Instruction structure for OFPIT_GOTO_TABLE */ struct ofp11_instruction_goto_table { ovs_be16 type; /* OFPIT_GOTO_TABLE */ ovs_be16 len; /* Length of this struct in bytes. */ uint8_t table_id; /* Set next table in the lookup pipeline */ uint8_t pad[3]; /* Pad to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp11_instruction_goto_table) == 8); /* Instruction structure for OFPIT_WRITE_METADATA */ struct ofp11_instruction_write_metadata { ovs_be16 type; /* OFPIT_WRITE_METADATA */ ovs_be16 len; /* Length of this struct in bytes. */ uint8_t pad[4]; /* Align to 64-bits */ ovs_be64 metadata; /* Metadata value to write */ ovs_be64 metadata_mask; /* Metadata write bitmask */ }; OFP_ASSERT(sizeof(struct ofp11_instruction_write_metadata) == 24); /* Instruction structure for OFPIT_WRITE/APPLY/CLEAR_ACTIONS */ struct ofp11_instruction_actions { ovs_be16 type; /* One of OFPIT_*_ACTIONS */ ovs_be16 len; /* Length of this struct in bytes. */ uint8_t pad[4]; /* Align to 64-bits */ /* struct ofp_action_header actions[0]; Actions associated with OFPIT_WRITE_ACTIONS and OFPIT_APPLY_ACTIONS */ }; OFP_ASSERT(sizeof(struct ofp11_instruction_actions) == 8); /* Instruction structure for experimental instructions */ struct ofp11_instruction_experimenter { ovs_be16 type; /* OFPIT11_EXPERIMENTER */ ovs_be16 len; /* Length of this struct in bytes */ ovs_be32 experimenter; /* Experimenter ID which takes the same form as in struct ofp_vendor_header. */ /* Experimenter-defined arbitrary additional data. */ }; OFP_ASSERT(sizeof(struct ofp11_instruction_experimenter) == 8); /* Configure/Modify behavior of a flow table */ struct ofp11_table_mod { uint8_t table_id; /* ID of the table, 0xFF indicates all tables */ uint8_t pad[3]; /* Pad to 32 bits */ ovs_be32 config; /* Bitmap of OFPTC_* flags */ }; OFP_ASSERT(sizeof(struct ofp11_table_mod) == 8); /* Flow setup and teardown (controller -> datapath). */ struct ofp11_flow_mod { ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be64 cookie_mask; /* Mask used to restrict the cookie bits that must match when the command is OFPFC_MODIFY* or OFPFC_DELETE*. A value of 0 indicates no restriction. */ /* Flow actions. */ uint8_t table_id; /* ID of the table to put the flow in */ uint8_t command; /* One of OFPFC_*. */ ovs_be16 idle_timeout; /* Idle time before discarding (seconds). */ ovs_be16 hard_timeout; /* Max time before discarding (seconds). */ ovs_be16 priority; /* Priority level of flow entry. */ ovs_be32 buffer_id; /* Buffered packet to apply to (or -1). Not meaningful for OFPFC_DELETE*. */ ovs_be32 out_port; /* For OFPFC_DELETE* commands, require matching entries to include this as an output port. A value of OFPP_ANY indicates no restriction. */ ovs_be32 out_group; /* For OFPFC_DELETE* commands, require matching entries to include this as an output group. A value of OFPG_ANY indicates no restriction. */ ovs_be16 flags; /* One of OFPFF_*. */ ovs_be16 importance; /* Eviction precedence (OF1.4+). */ /* Followed by an ofp11_match structure. */ /* Followed by an instruction set. */ }; OFP_ASSERT(sizeof(struct ofp11_flow_mod) == 40); /* Group types. Values in the range [128, 255] are reserved for experimental * use. */ enum ofp11_group_type { OFPGT11_ALL, /* All (multicast/broadcast) group. */ OFPGT11_SELECT, /* Select group. */ OFPGT11_INDIRECT, /* Indirect group. */ OFPGT11_FF /* Fast failover group. */ }; /* Bucket for use in groups. */ struct ofp11_bucket { ovs_be16 len; /* Length the bucket in bytes, including this header and any padding to make it 64-bit aligned. */ ovs_be16 weight; /* Relative weight of bucket. Only defined for select groups. */ ovs_be32 watch_port; /* Port whose state affects whether this bucket is live. Only required for fast failover groups. */ ovs_be32 watch_group; /* Group whose state affects whether this bucket is live. Only required for fast failover groups. */ uint8_t pad[4]; /* struct ofp_action_header actions[0]; The action length is inferred from the length field in the header. */ }; OFP_ASSERT(sizeof(struct ofp11_bucket) == 16); /* Queue configuration for a given port. */ struct ofp11_queue_get_config_reply { ovs_be32 port; uint8_t pad[4]; /* struct ofp_packet_queue queues[0]; List of configured queues. */ }; OFP_ASSERT(sizeof(struct ofp11_queue_get_config_reply) == 8); struct ofp11_stats_msg { struct ofp_header header; ovs_be16 type; /* One of the OFPST_* constants. */ ovs_be16 flags; /* OFPSF_REQ_* flags (none yet defined). */ uint8_t pad[4]; /* Followed by the body of the request. */ }; OFP_ASSERT(sizeof(struct ofp11_stats_msg) == 16); /* Vendor extension stats message. */ struct ofp11_vendor_stats_msg { struct ofp11_stats_msg osm; /* Type OFPST_VENDOR. */ ovs_be32 vendor; /* Vendor ID: * - MSB 0: low-order bytes are IEEE OUI. * - MSB != 0: defined by OpenFlow * consortium. */ /* Followed by vendor-defined arbitrary additional data. */ }; OFP_ASSERT(sizeof(struct ofp11_vendor_stats_msg) == 20); /* Stats request of type OFPST_FLOW. */ struct ofp11_flow_stats_request { uint8_t table_id; /* ID of table to read (from ofp_table_stats), 0xff for all tables. */ uint8_t pad[3]; /* Align to 64 bits. */ ovs_be32 out_port; /* Require matching entries to include this as an output port. A value of OFPP_ANY indicates no restriction. */ ovs_be32 out_group; /* Require matching entries to include this as an output group. A value of OFPG_ANY indicates no restriction. */ uint8_t pad2[4]; /* Align to 64 bits. */ ovs_be64 cookie; /* Require matching entries to contain this cookie value */ ovs_be64 cookie_mask; /* Mask used to restrict the cookie bits that must match. A value of 0 indicates no restriction. */ /* Followed by an ofp11_match structure. */ }; OFP_ASSERT(sizeof(struct ofp11_flow_stats_request) == 32); /* Body of reply to OFPST_FLOW request. */ struct ofp11_flow_stats { ovs_be16 length; /* Length of this entry. */ uint8_t table_id; /* ID of table flow came from. */ uint8_t pad; ovs_be32 duration_sec; /* Time flow has been alive in seconds. */ ovs_be32 duration_nsec; /* Time flow has been alive in nanoseconds beyond duration_sec. */ ovs_be16 priority; /* Priority of the entry. Only meaningful when this is not an exact-match entry. */ ovs_be16 idle_timeout; /* Number of seconds idle before expiration. */ ovs_be16 hard_timeout; /* Number of seconds before expiration. */ ovs_be16 flags; /* OF 1.3: Set of OFPFF*. */ ovs_be16 importance; /* Eviction precedence (OF1.4+). */ uint8_t pad2[2]; /* Align to 64-bits. */ ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be64 packet_count; /* Number of packets in flow. */ ovs_be64 byte_count; /* Number of bytes in flow. */ /* OpenFlow version specific match */ /* struct ofp11_instruction instructions[0]; Instruction set. */ }; OFP_ASSERT(sizeof(struct ofp11_flow_stats) == 48); /* Body for ofp_stats_request of type OFPST_AGGREGATE. */ /* Identical to ofp11_flow_stats_request */ /* Flow match fields. */ enum ofp11_flow_match_fields { OFPFMF11_IN_PORT = 1 << 0, /* Switch input port. */ OFPFMF11_DL_VLAN = 1 << 1, /* VLAN id. */ OFPFMF11_DL_VLAN_PCP = 1 << 2, /* VLAN priority. */ OFPFMF11_DL_TYPE = 1 << 3, /* Ethernet frame type. */ OFPFMF11_NW_TOS = 1 << 4, /* IP ToS (DSCP field, 6 bits). */ OFPFMF11_NW_PROTO = 1 << 5, /* IP protocol. */ OFPFMF11_TP_SRC = 1 << 6, /* TCP/UDP/SCTP source port. */ OFPFMF11_TP_DST = 1 << 7, /* TCP/UDP/SCTP destination port. */ OFPFMF11_MPLS_LABEL = 1 << 8, /* MPLS label. */ OFPFMF11_MPLS_TC = 1 << 9, /* MPLS TC. */ OFPFMF11_TYPE = 1 << 10, /* Match type. */ OFPFMF11_DL_SRC = 1 << 11, /* Ethernet source address. */ OFPFMF11_DL_DST = 1 << 12, /* Ethernet destination address. */ OFPFMF11_NW_SRC = 1 << 13, /* IP source address. */ OFPFMF11_NW_DST = 1 << 14, /* IP destination address. */ OFPFMF11_METADATA = 1 << 15, /* Metadata passed between tables. */ }; /* Body of reply to OFPST_TABLE request. */ struct ofp11_table_stats { uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */ uint8_t pad[7]; /* Align to 64-bits. */ char name[OFP_MAX_TABLE_NAME_LEN]; ovs_be32 wildcards; /* Bitmap of OFPFMF_* wildcards that are supported by the table. */ ovs_be32 match; /* Bitmap of OFPFMF_* that indicate the fields the table can match on. */ ovs_be32 instructions; /* Bitmap of OFPIT_* values supported. */ ovs_be32 write_actions; /* Bitmap of OFPAT_* that are supported by the table with OFPIT_WRITE_ACTIONS. */ ovs_be32 apply_actions; /* Bitmap of OFPAT_* that are supported by the table with OFPIT_APPLY_ACTIONS. */ ovs_be32 config; /* Bitmap of OFPTC_* values */ ovs_be32 max_entries; /* Max number of entries supported. */ ovs_be32 active_count; /* Number of active entries. */ ovs_be64 lookup_count; /* Number of packets looked up in table. */ ovs_be64 matched_count; /* Number of packets that hit table. */ }; OFP_ASSERT(sizeof(struct ofp11_table_stats) == 88); /* Body for ofp_stats_request of type OFPST_PORT. */ struct ofp11_port_stats_request { ovs_be32 port_no; /* OFPST_PORT message must request statistics * either for a single port (specified in * port_no) or for all ports (if port_no == * OFPP_ANY). */ uint8_t pad[4]; }; OFP_ASSERT(sizeof(struct ofp11_port_stats_request) == 8); /* Body of reply to OFPST_PORT request. If a counter is unsupported, set * the field to all ones. */ struct ofp11_port_stats { ovs_be32 port_no; uint8_t pad[4]; /* Align to 64-bits. */ ovs_be64 rx_packets; /* Number of received packets. */ ovs_be64 tx_packets; /* Number of transmitted packets. */ ovs_be64 rx_bytes; /* Number of received bytes. */ ovs_be64 tx_bytes; /* Number of transmitted bytes. */ ovs_be64 rx_dropped; /* Number of packets dropped by RX. */ ovs_be64 tx_dropped; /* Number of packets dropped by TX. */ ovs_be64 rx_errors; /* Number of receive errors. This is a super-set of receive errors and should be great than or equal to the sum of all rx_*_err values. */ ovs_be64 tx_errors; /* Number of transmit errors. This is a super-set of transmit errors. */ ovs_be64 rx_frame_err; /* Number of frame alignment errors. */ ovs_be64 rx_over_err; /* Number of packets with RX overrun. */ ovs_be64 rx_crc_err; /* Number of CRC errors. */ ovs_be64 collisions; /* Number of collisions. */ }; OFP_ASSERT(sizeof(struct ofp11_port_stats) == 104); struct ofp11_queue_stats_request { ovs_be32 port_no; /* All ports if OFPP_ANY. */ ovs_be32 queue_id; /* All queues if OFPQ_ALL. */ }; OFP_ASSERT(sizeof(struct ofp11_queue_stats_request) == 8); struct ofp11_queue_stats { ovs_be32 port_no; ovs_be32 queue_id; /* Queue id. */ ovs_be64 tx_bytes; /* Number of transmitted bytes. */ ovs_be64 tx_packets; /* Number of transmitted packets. */ ovs_be64 tx_errors; /* # of packets dropped due to overrun. */ }; OFP_ASSERT(sizeof(struct ofp11_queue_stats) == 32); struct ofp11_group_stats_request { ovs_be32 group_id; /* All groups if OFPG_ALL. */ uint8_t pad[4]; /* Align to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp11_group_stats_request) == 8); /* Used in group stats replies. */ struct ofp11_bucket_counter { ovs_be64 packet_count; /* Number of packets processed by bucket. */ ovs_be64 byte_count; /* Number of bytes processed by bucket. */ }; OFP_ASSERT(sizeof(struct ofp11_bucket_counter) == 16); /* Body of reply to OFPST11_GROUP request */ struct ofp11_group_stats { ovs_be16 length; /* Length of this entry. */ uint8_t pad[2]; /* Align to 64 bits. */ ovs_be32 group_id; /* Group identifier. */ ovs_be32 ref_count; /* Number of flows or groups that directly forward to this group. */ uint8_t pad2[4]; /* Align to 64 bits. */ ovs_be64 packet_count; /* Number of packets processed by group. */ ovs_be64 byte_count; /* Number of bytes processed by group. */ /* struct ofp11_bucket_counter bucket_stats[]; */ }; OFP_ASSERT(sizeof(struct ofp11_group_stats) == 32); /* Body of reply to OFPST11_GROUP_DESC request. */ struct ofp11_group_desc_stats { ovs_be16 length; /* Length of this entry. */ uint8_t type; /* One of OFPGT11_*. */ uint8_t pad; /* Pad to 64 bits. */ ovs_be32 group_id; /* Group identifier. */ /* struct ofp11_bucket buckets[0]; */ }; OFP_ASSERT(sizeof(struct ofp11_group_desc_stats) == 8); /* Send packet (controller -> datapath). */ struct ofp11_packet_out { ovs_be32 buffer_id; /* ID assigned by datapath (-1 if none). */ ovs_be32 in_port; /* Packet's input port or OFPP_CONTROLLER. */ ovs_be16 actions_len; /* Size of action array in bytes. */ uint8_t pad[6]; /* struct ofp_action_header actions[0]; Action list. */ /* uint8_t data[0]; */ /* Packet data. The length is inferred from the length field in the header. (Only meaningful if buffer_id == -1.) */ }; OFP_ASSERT(sizeof(struct ofp11_packet_out) == 16); /* Packet received on port (datapath -> controller). */ struct ofp11_packet_in { ovs_be32 buffer_id; /* ID assigned by datapath. */ ovs_be32 in_port; /* Port on which frame was received. */ ovs_be32 in_phy_port; /* Physical Port on which frame was received. */ ovs_be16 total_len; /* Full length of frame. */ uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */ uint8_t table_id; /* ID of the table that was looked up */ /* Followed by Ethernet frame. */ }; OFP_ASSERT(sizeof(struct ofp11_packet_in) == 16); /* Flow removed (datapath -> controller). */ struct ofp11_flow_removed { ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be16 priority; /* Priority level of flow entry. */ uint8_t reason; /* One of OFPRR_*. */ uint8_t table_id; /* ID of the table */ ovs_be32 duration_sec; /* Time flow was alive in seconds. */ ovs_be32 duration_nsec; /* Time flow was alive in nanoseconds beyond duration_sec. */ ovs_be16 idle_timeout; /* Idle timeout from original flow mod. */ uint8_t pad2[2]; /* Align to 64-bits. */ ovs_be64 packet_count; ovs_be64 byte_count; /* Followed by an ofp11_match structure. */ }; OFP_ASSERT(sizeof(struct ofp11_flow_removed) == 40); #endif /* openflow/openflow-1.1.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow.h0000644000000000000000000000013012631676263021121 xustar0029 mtime=1449622707.12644481 29 atime=1456592608.54068042 30 ctime=1456594660.333294706 openvswitch-2.5.0/include/openflow/openflow.h0000664000175000017500000000164112631676263022615 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENFLOW_OPENFLOW_H #define OPENFLOW_OPENFLOW_H 1 #include #include #include #include #include #include #endif /* openflow/openflow.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow-common.h0000644000000000000000000000013212664352753022412 xustar0030 mtime=1456592363.442621001 30 atime=1456592368.182815687 30 ctime=1456594660.333294706 openvswitch-2.5.0/include/openflow/openflow-common.h0000664000175000017500000004155212664352753024111 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2011, 2012, 2013, 2014 The Board of Trustees of The Leland Stanford * Junior University * * We are making the OpenFlow specification and associated documentation * (Software) available for public use and benefit with the expectation * that others will use, modify and enhance the Software and contribute * those enhancements back to the community. However, since we would * like to make the Software available for broadest use, with as few * restrictions as possible permission is hereby granted, free of * charge, to any person obtaining a copy of this Software to deal in * the Software under the copyrights without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * The name and trademarks of copyright holder(s) may NOT be used in * advertising or publicity pertaining to the Software or any * derivatives without specific, written prior permission. */ /* * Copyright (c) 2008-2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENFLOW_COMMON_H #define OPENFLOW_COMMON_H 1 #include #ifdef SWIG #define OFP_ASSERT(EXPR) /* SWIG can't handle OFP_ASSERT. */ #elif !defined(__cplusplus) /* Build-time assertion for use in a declaration context. */ #define OFP_ASSERT(EXPR) \ extern int (*build_assert(void))[ sizeof(struct { \ unsigned int build_assert_failed : (EXPR) ? 1 : -1; })] #else /* __cplusplus */ #include #define OFP_ASSERT BOOST_STATIC_ASSERT #endif /* __cplusplus */ /* Version number: * Non-experimental versions released: 0x01 0x02 * Experimental versions released: 0x81 -- 0x99 */ /* The most significant bit being set in the version field indicates an * experimental OpenFlow version. */ enum ofp_version { OFP10_VERSION = 0x01, OFP11_VERSION = 0x02, OFP12_VERSION = 0x03, OFP13_VERSION = 0x04, OFP14_VERSION = 0x05, OFP15_VERSION = 0x06 }; /* Vendor (aka experimenter) IDs. * * These are used in various places in OpenFlow to identify an extension * defined by some vendor, as opposed to a standardized part of the core * OpenFlow protocol. * * Vendor IDs whose top 8 bits are 0 hold an Ethernet OUI in their low 24 bits. * The Open Networking Foundation assigns vendor IDs whose top 8 bits are * nonzero. * * A few vendor IDs are special: * * - OF_VENDOR_ID is not a real vendor ID and does not appear in the * OpenFlow protocol itself. It can occasionally be useful within Open * vSwitch to identify a standardized part of OpenFlow. * * - ONF_VENDOR_ID is being used within the ONF "extensibility" working * group to identify extensions being proposed for standardization. * * The list is sorted numerically. */ #define OF_VENDOR_ID 0 #define HPL_VENDOR_ID 0x000004EA /* HP Labs. */ #define NTR_VENDOR_ID 0x0000154d /* Netronome. */ #define NTR_COMPAT_VENDOR_ID 0x00001540 /* Incorrect value used in v2.4. */ #define NX_VENDOR_ID 0x00002320 /* Nicira. */ #define ONF_VENDOR_ID 0x4f4e4600 /* Open Networking Foundation. */ #define OFP_MAX_TABLE_NAME_LEN 32 #define OFP_MAX_PORT_NAME_LEN 16 #define OFP_OLD_PORT 6633 #define OFP_PORT 6653 #define OFP_DEFAULT_MISS_SEND_LEN 128 /* Values below this cutoff are 802.3 packets and the two bytes * following MAC addresses are used as a frame length. Otherwise, the * two bytes are used as the Ethernet type. */ #define OFP_DL_TYPE_ETH2_CUTOFF 0x0600 /* Value of dl_type to indicate that the frame does not include an * Ethernet type. */ #define OFP_DL_TYPE_NOT_ETH_TYPE 0x05ff /* Value used in "idle_timeout" and "hard_timeout" to indicate that the entry * is permanent. */ #define OFP_FLOW_PERMANENT 0 /* By default, choose a priority in the middle. */ #define OFP_DEFAULT_PRIORITY 0x8000 /* Header on all OpenFlow packets. */ struct ofp_header { uint8_t version; /* An OpenFlow version number, e.g. OFP10_VERSION. */ uint8_t type; /* One of the OFPT_ constants. */ ovs_be16 length; /* Length including this ofp_header. */ ovs_be32 xid; /* Transaction id associated with this packet. Replies use the same id as was in the request to facilitate pairing. */ }; OFP_ASSERT(sizeof(struct ofp_header) == 8); /* OFPT_ERROR: Error message (datapath -> controller). */ struct ofp_error_msg { ovs_be16 type; ovs_be16 code; uint8_t data[0]; /* Variable-length data. Interpreted based on the type and code. */ }; OFP_ASSERT(sizeof(struct ofp_error_msg) == 4); enum ofp_config_flags { /* Handling of IP fragments. */ OFPC_FRAG_NORMAL = 0, /* No special handling for fragments. */ OFPC_FRAG_DROP = 1, /* Drop fragments. */ OFPC_FRAG_REASM = 2, /* Reassemble (only if OFPC_IP_REASM set). */ OFPC_FRAG_NX_MATCH = 3, /* Make first fragments available for matching. */ OFPC_FRAG_MASK = 3, /* OFPC_INVALID_TTL_TO_CONTROLLER is deprecated in OpenFlow 1.3 */ /* TTL processing - applicable for IP and MPLS packets. */ OFPC_INVALID_TTL_TO_CONTROLLER = 1 << 2, /* Send packets with invalid TTL to the controller. */ }; /* Switch configuration. */ struct ofp_switch_config { ovs_be16 flags; /* OFPC_* flags. */ ovs_be16 miss_send_len; /* Max bytes of new flow that datapath should send to the controller. */ }; OFP_ASSERT(sizeof(struct ofp_switch_config) == 4); /* Common flags to indicate behavior of the physical port. These flags are * used in ofp_port to describe the current configuration. They are used in * the ofp_port_mod message to configure the port's behavior. */ enum ofp_port_config { OFPPC_PORT_DOWN = 1 << 0, /* Port is administratively down. */ OFPPC_NO_RECV = 1 << 2, /* Drop all packets received by port. */ OFPPC_NO_FWD = 1 << 5, /* Drop packets forwarded to port. */ OFPPC_NO_PACKET_IN = 1 << 6 /* Do not send packet-in msgs for port. */ }; /* Common current state of the physical port. These are not configurable from * the controller. */ enum ofp_port_state { OFPPS_LINK_DOWN = 1 << 0, /* No physical link present. */ }; /* Common features of physical ports available in a datapath. */ enum ofp_port_features { OFPPF_10MB_HD = 1 << 0, /* 10 Mb half-duplex rate support. */ OFPPF_10MB_FD = 1 << 1, /* 10 Mb full-duplex rate support. */ OFPPF_100MB_HD = 1 << 2, /* 100 Mb half-duplex rate support. */ OFPPF_100MB_FD = 1 << 3, /* 100 Mb full-duplex rate support. */ OFPPF_1GB_HD = 1 << 4, /* 1 Gb half-duplex rate support. */ OFPPF_1GB_FD = 1 << 5, /* 1 Gb full-duplex rate support. */ OFPPF_10GB_FD = 1 << 6, /* 10 Gb full-duplex rate support. */ }; enum ofp_queue_properties { OFPQT_MIN_RATE = 1, /* Minimum datarate guaranteed. */ OFPQT_MAX_RATE = 2, /* Maximum guaranteed rate. */ OFPQT_EXPERIMENTER = 0xffff, /* Experimenter defined property. */ }; /* Common description for a queue. */ struct ofp_queue_prop_header { ovs_be16 property; /* One of OFPQT_. */ ovs_be16 len; /* Length of property, including this header. */ uint8_t pad[4]; /* 64-bit alignemnt. */ }; OFP_ASSERT(sizeof(struct ofp_queue_prop_header) == 8); /* Min-Rate and Max-Rate queue property description (OFPQT_MIN and * OFPQT_MAX). */ struct ofp_queue_prop_rate { struct ofp_queue_prop_header prop_header; ovs_be16 rate; /* In 1/10 of a percent; >1000 -> disabled. */ uint8_t pad[6]; /* 64-bit alignment */ }; OFP_ASSERT(sizeof(struct ofp_queue_prop_rate) == 16); /* Switch features. */ struct ofp_switch_features { ovs_be64 datapath_id; /* Datapath unique ID. The lower 48-bits are for a MAC address, while the upper 16-bits are implementer-defined. */ ovs_be32 n_buffers; /* Max packets buffered at once. */ uint8_t n_tables; /* Number of tables supported by datapath. */ uint8_t auxiliary_id; /* OF 1.3: Identify auxiliary connections */ uint8_t pad[2]; /* Align to 64-bits. */ /* Features. */ ovs_be32 capabilities; /* OFPC_*, OFPC10_*, OFPC11_*, OFPC12_*. */ ovs_be32 actions; /* Bitmap of supported "ofp_action_type"s. * DEPRECATED in OpenFlow 1.1 */ /* Followed by an array of struct ofp10_phy_port or struct ofp11_port * structures. The number is inferred from header.length. * REMOVED in OpenFlow 1.3 */ }; OFP_ASSERT(sizeof(struct ofp_switch_features) == 24); /* Common capabilities supported by the datapath (struct ofp_switch_features, * member capabilities). */ enum ofp_capabilities { OFPC_FLOW_STATS = 1 << 0, /* Flow statistics. */ OFPC_TABLE_STATS = 1 << 1, /* Table statistics. */ OFPC_PORT_STATS = 1 << 2, /* Port statistics. */ OFPC_IP_REASM = 1 << 5, /* Can reassemble IP fragments. */ OFPC_QUEUE_STATS = 1 << 6, /* Queue statistics. */ OFPC_ARP_MATCH_IP = 1 << 7 /* Match IP addresses in ARP pkts. */ }; /* Why is this packet being sent to the controller? */ enum ofp_packet_in_reason { OFPR_NO_MATCH, /* No matching flow. */ OFPR_ACTION, /* Action explicitly output to controller. */ OFPR_INVALID_TTL, /* Packet has invalid TTL. */ OFPR_ACTION_SET, /* Output to controller in action set */ OFPR_GROUP, /* Output to controller in group bucket */ OFPR_PACKET_OUT, /* Output to controller in packet-out */ OFPR_N_REASONS }; enum ofp_flow_mod_command { OFPFC_ADD, /* New flow. */ OFPFC_MODIFY, /* Modify all matching flows. */ OFPFC_MODIFY_STRICT, /* Modify entry strictly matching wildcards */ OFPFC_DELETE, /* Delete all matching flows. */ OFPFC_DELETE_STRICT /* Strictly match wildcards and priority. */ }; enum ofp_flow_mod_flags { OFPFF_SEND_FLOW_REM = 1 << 0, /* Send flow removed message when flow * expires or is deleted. */ OFPFF_CHECK_OVERLAP = 1 << 1, /* Check for overlapping entries first. */ }; /* Why was this flow removed? */ enum ofp_flow_removed_reason { OFPRR_IDLE_TIMEOUT, /* Flow idle time exceeded idle_timeout. */ OFPRR_HARD_TIMEOUT, /* Time exceeded hard_timeout. */ OFPRR_DELETE, /* Evicted by a DELETE flow mod. */ OFPRR_GROUP_DELETE, /* Group was removed. */ OFPRR_METER_DELETE, /* Meter was removed. */ OFPRR_EVICTION, /* Switch eviction to free resources. */ OVS_OFPRR_NONE /* OVS internal_use only, keep last!. */ }; /* What changed about the physical port */ enum ofp_port_reason { OFPPR_ADD, /* The port was added. */ OFPPR_DELETE, /* The port was removed. */ OFPPR_MODIFY, /* Some attribute of the port has changed. */ OFPPR_N_REASONS /* Denotes number of reasons. */ }; /* A physical port has changed in the datapath */ struct ofp_port_status { uint8_t reason; /* One of OFPPR_*. */ uint8_t pad[7]; /* Align to 64-bits. */ /* Followed by struct ofp10_phy_port, struct ofp11_port, or struct * ofp14_port. */ }; OFP_ASSERT(sizeof(struct ofp_port_status) == 8); enum ofp_stats_reply_flags { OFPSF_REPLY_MORE = 1 << 0 /* More replies to follow. */ }; #define DESC_STR_LEN 256 #define SERIAL_NUM_LEN 32 /* Body of reply to OFPST_DESC request. Each entry is a NULL-terminated ASCII * string. */ struct ofp_desc_stats { char mfr_desc[DESC_STR_LEN]; /* Manufacturer description. */ char hw_desc[DESC_STR_LEN]; /* Hardware description. */ char sw_desc[DESC_STR_LEN]; /* Software description. */ char serial_num[SERIAL_NUM_LEN]; /* Serial number. */ char dp_desc[DESC_STR_LEN]; /* Human readable description of the datapath. */ }; OFP_ASSERT(sizeof(struct ofp_desc_stats) == 1056); /* Reply to OFPST_AGGREGATE request. */ struct ofp_aggregate_stats_reply { ovs_32aligned_be64 packet_count; /* Number of packets in flows. */ ovs_32aligned_be64 byte_count; /* Number of bytes in flows. */ ovs_be32 flow_count; /* Number of flows. */ uint8_t pad[4]; /* Align to 64 bits. */ }; OFP_ASSERT(sizeof(struct ofp_aggregate_stats_reply) == 24); /* The match type indicates the match structure (set of fields that compose the * match) in use. The match type is placed in the type field at the beginning * of all match structures. The "OpenFlow Extensible Match" type corresponds * to OXM TLV format described below and must be supported by all OpenFlow * switches. Extensions that define other match types may be published on the * ONF wiki. Support for extensions is optional. */ enum ofp_match_type { OFPMT_STANDARD = 0, /* The match fields defined in the ofp11_match structure apply */ OFPMT_OXM = 1, /* OpenFlow Extensible Match */ }; /* Group numbering. Groups can use any number up to OFPG_MAX. */ enum ofp_group { /* Last usable group number. */ OFPG_MAX = 0xffffff00, /* Fake groups. */ OFPG_ALL = 0xfffffffc, /* All groups, for group delete commands. */ OFPG_ANY = 0xffffffff /* Wildcard, for flow stats requests. */ }; /* Group configuration flags */ enum ofp_group_capabilities { OFPGFC_SELECT_WEIGHT = 1 << 0, /* Support weight for select groups */ OFPGFC_SELECT_LIVENESS = 1 << 1, /* Support liveness for select groups */ OFPGFC_CHAINING = 1 << 2, /* Support chaining groups */ OFPGFC_CHAINING_CHECKS = 1 << 3, /* Check chaining for loops and delete */ }; enum ofp_hello_elem_type { OFPHET_VERSIONBITMAP = 1, /* Bitmap of version supported. */ }; /* Common header for all Hello Elements */ struct ofp_hello_elem_header { ovs_be16 type; /* One of OFPHET_*. */ ovs_be16 length; /* Length in bytes of this element. */ }; OFP_ASSERT(sizeof(struct ofp_hello_elem_header) == 4); /* Vendor extension. */ struct ofp_vendor_header { struct ofp_header header; /* Type OFPT_VENDOR or OFPT_EXPERIMENTER. */ ovs_be32 vendor; /* Vendor ID: * - MSB 0: low-order bytes are IEEE OUI. * - MSB != 0: defined by OpenFlow * consortium. */ /* Vendor-defined arbitrary additional data. */ }; OFP_ASSERT(sizeof(struct ofp_vendor_header) == 12); /* Table numbering. Tables can use any number up to OFPT_MAX. */ enum ofp_table { /* Last usable table number. */ OFPTT_MAX = 0xfe, /* Fake tables. */ OFPTT_ALL = 0xff /* Wildcard table used for table config, flow stats and flow deletes. */ }; enum ofp_table_config { /* OpenFlow 1.1 and 1.2 defined this field as shown. * OpenFlow 1.3 and later mark this field as deprecated, but have not * reused it for any new purpose. */ OFPTC11_TABLE_MISS_CONTROLLER = 0 << 0, /* Send to controller. */ OFPTC11_TABLE_MISS_CONTINUE = 1 << 0, /* Go to next table, like OF1.0. */ OFPTC11_TABLE_MISS_DROP = 2 << 0, /* Drop the packet. */ OFPTC11_TABLE_MISS_MASK = 3 << 0, /* OpenFlow 1.4. */ OFPTC14_EVICTION = 1 << 2, /* Allow table to evict flows. */ OFPTC14_VACANCY_EVENTS = 1 << 3, /* Enable vacancy events. */ }; #endif /* openflow/openflow-common.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/openflow-1.2.h0000644000000000000000000000013212664352753021422 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.182815687 30 ctime=1456594660.329294538 openvswitch-2.5.0/include/openflow/openflow-1.2.h0000664000175000017500000002536112664352753023121 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2011, 2012, 2013, 2014 The Board of Trustees of The Leland Stanford * Junior University * * We are making the OpenFlow specification and associated documentation * (Software) available for public use and benefit with the expectation * that others will use, modify and enhance the Software and contribute * those enhancements back to the community. However, since we would * like to make the Software available for broadest use, with as few * restrictions as possible permission is hereby granted, free of * charge, to any person obtaining a copy of this Software to deal in * the Software under the copyrights without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * The name and trademarks of copyright holder(s) may NOT be used in * advertising or publicity pertaining to the Software or any * derivatives without specific, written prior permission. */ /* * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. * Copyright (c) 2012 Horms Solutions Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* OpenFlow: protocol between controller and datapath. */ #ifndef OPENFLOW_12_H #define OPENFLOW_12_H 1 #include /* Error type for experimenter error messages. */ #define OFPET12_EXPERIMENTER 0xffff /* The VLAN id is 12-bits, so we can use the entire 16 bits to indicate * special conditions. */ enum ofp12_vlan_id { OFPVID12_PRESENT = 0x1000, /* Bit that indicate that a VLAN id is set */ OFPVID12_NONE = 0x0000, /* No VLAN id was set. */ }; /* Bit definitions for IPv6 Extension Header pseudo-field. */ enum ofp12_ipv6exthdr_flags { OFPIEH12_NONEXT = 1 << 0, /* "No next header" encountered. */ OFPIEH12_ESP = 1 << 1, /* Encrypted Sec Payload header present. */ OFPIEH12_AUTH = 1 << 2, /* Authentication header present. */ OFPIEH12_DEST = 1 << 3, /* 1 or 2 dest headers present. */ OFPIEH12_FRAG = 1 << 4, /* Fragment header present. */ OFPIEH12_ROUTER = 1 << 5, /* Router header present. */ OFPIEH12_HOP = 1 << 6, /* Hop-by-hop header present. */ OFPIEH12_UNREP = 1 << 7, /* Unexpected repeats encountered. */ OFPIEH12_UNSEQ = 1 << 8 /* Unexpected sequencing encountered. */ }; /* Header for OXM experimenter match fields. */ struct ofp12_oxm_experimenter_header { ovs_be32 oxm_header; /* oxm_class = OFPXMC_EXPERIMENTER */ ovs_be32 experimenter; /* Experimenter ID which takes the same form as in struct ofp11_experimenter_header. */ }; OFP_ASSERT(sizeof(struct ofp12_oxm_experimenter_header) == 8); enum ofp12_controller_max_len { OFPCML12_MAX = 0xffe5, /* maximum max_len value which can be used * to request a specific byte length. */ OFPCML12_NO_BUFFER = 0xffff /* indicates that no buffering should be * applied and the whole packet is to be * sent to the controller. */ }; /* OpenFlow 1.2 specific flags * (struct ofp12_flow_mod, member flags). */ enum ofp12_flow_mod_flags { OFPFF12_RESET_COUNTS = 1 << 2 /* Reset flow packet and byte counts. */ }; /* OpenFlow 1.2 specific capabilities * (struct ofp_switch_features, member capabilities). */ enum ofp12_capabilities { OFPC12_PORT_BLOCKED = 1 << 8 /* Switch will block looping ports. */ }; /* Full description for a queue. */ struct ofp12_packet_queue { ovs_be32 queue_id; /* id for the specific queue. */ ovs_be32 port; /* Port this queue is attached to. */ ovs_be16 len; /* Length in bytes of this queue desc. */ uint8_t pad[6]; /* 64-bit alignment. */ /* Followed by any number of queue properties expressed using * ofp_queue_prop_header, to fill out a total of 'len' bytes. */ }; OFP_ASSERT(sizeof(struct ofp12_packet_queue) == 16); /* Body of reply to OFPST_TABLE request. */ struct ofp12_table_stats { uint8_t table_id; /* Identifier of table. Lower numbered tables are consulted first. */ uint8_t pad[7]; /* Align to 64-bits. */ char name[OFP_MAX_TABLE_NAME_LEN]; ovs_be64 match; /* Bitmap of (1 << OFPXMT_*) that indicate the fields the table can match on. */ ovs_be64 wildcards; /* Bitmap of (1 << OFPXMT_*) wildcards that are supported by the table. */ ovs_be32 write_actions; /* Bitmap of OFPAT_* that are supported by the table with OFPIT_WRITE_ACTIONS. */ ovs_be32 apply_actions; /* Bitmap of OFPAT_* that are supported by the table with OFPIT_APPLY_ACTIONS. */ ovs_be64 write_setfields;/* Bitmap of (1 << OFPXMT_*) header fields that can be set with OFPIT_WRITE_ACTIONS. */ ovs_be64 apply_setfields;/* Bitmap of (1 << OFPXMT_*) header fields that can be set with OFPIT_APPLY_ACTIONS. */ ovs_be64 metadata_match; /* Bits of metadata table can match. */ ovs_be64 metadata_write; /* Bits of metadata table can write. */ ovs_be32 instructions; /* Bitmap of OFPIT_* values supported. */ ovs_be32 config; /* Bitmap of OFPTC_* values */ ovs_be32 max_entries; /* Max number of entries supported. */ ovs_be32 active_count; /* Number of active entries. */ ovs_be64 lookup_count; /* Number of packets looked up in table. */ ovs_be64 matched_count; /* Number of packets that hit table. */ }; OFP_ASSERT(sizeof(struct ofp12_table_stats) == 128); /* Number of types of groups supported by ofp12_group_features_stats. */ #define OFPGT12_N_TYPES 4 /* Body of reply to OFPST12_GROUP_FEATURES request. Group features. */ struct ofp12_group_features_stats { ovs_be32 types; /* Bitmap of OFPGT11_* values supported. */ ovs_be32 capabilities; /* Bitmap of OFPGFC12_* capability supported. */ /* Each element in the following arrays corresponds to the group type with * the same number, e.g. max_groups[0] is the maximum number of OFPGT11_ALL * groups, actions[2] is the actions supported by OFPGT11_INDIRECT * groups. */ ovs_be32 max_groups[OFPGT12_N_TYPES]; /* Max number of groups. */ ovs_be32 actions[OFPGT12_N_TYPES]; /* Bitmaps of supported OFPAT_*. */ }; OFP_ASSERT(sizeof(struct ofp12_group_features_stats) == 40); /* Group configuration flags */ enum ofp12_group_capabilities { OFPGFC12_SELECT_WEIGHT = 1 << 0, /* Support weight for select groups */ OFPGFC12_SELECT_LIVENESS = 1 << 1, /* Support liveness for select groups */ OFPGFC12_CHAINING = 1 << 2, /* Support chaining groups */ OFPGFC12_CHAINING_CHECKS = 1 << 3, /* Check chaining for loops and delete */ }; /* Body for ofp12_stats_request/reply of type OFPST_EXPERIMENTER. */ struct ofp12_experimenter_stats_header { ovs_be32 experimenter; /* Experimenter ID which takes the same form as in struct ofp_experimenter_header. */ ovs_be32 exp_type; /* Experimenter defined. */ /* Experimenter-defined arbitrary additional data. */ }; OFP_ASSERT(sizeof(struct ofp12_experimenter_stats_header) == 8); /* Role request and reply message. */ struct ofp12_role_request { ovs_be32 role; /* One of OFPCR12_ROLE_*. */ uint8_t pad[4]; /* Align to 64 bits. */ ovs_be64 generation_id; /* Master Election Generation Id */ }; OFP_ASSERT(sizeof(struct ofp12_role_request) == 16); /* Controller roles. */ enum ofp12_controller_role { OFPCR12_ROLE_NOCHANGE, /* Don't change current role. */ OFPCR12_ROLE_EQUAL, /* Default role, full access. */ OFPCR12_ROLE_MASTER, /* Full access, at most one master. */ OFPCR12_ROLE_SLAVE, /* Read-only access. */ }; /* Packet received on port (datapath -> controller). */ struct ofp12_packet_in { ovs_be32 buffer_id; /* ID assigned by datapath. */ ovs_be16 total_len; /* Full length of frame. */ uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */ uint8_t table_id; /* ID of the table that was looked up */ /* Followed by: * - Match * - Exactly 2 all-zero padding bytes, then * - An Ethernet frame whose length is inferred from header.length. * The padding bytes preceding the Ethernet frame ensure that the IP * header (if any) following the Ethernet header is 32-bit aligned. */ /* struct ofp12_match match; */ /* uint8_t pad[2]; Align to 64 bit + 16 bit */ /* uint8_t data[0]; Ethernet frame */ }; OFP_ASSERT(sizeof(struct ofp12_packet_in) == 8); /* Flow removed (datapath -> controller). */ struct ofp12_flow_removed { ovs_be64 cookie; /* Opaque controller-issued identifier. */ ovs_be16 priority; /* Priority level of flow entry. */ uint8_t reason; /* One of OFPRR_*. */ uint8_t table_id; /* ID of the table */ ovs_be32 duration_sec; /* Time flow was alive in seconds. */ ovs_be32 duration_nsec; /* Time flow was alive in nanoseconds beyond duration_sec. */ ovs_be16 idle_timeout; /* Idle timeout from original flow mod. */ ovs_be16 hard_timeout; /* Hard timeout from original flow mod. */ ovs_be64 packet_count; ovs_be64 byte_count; /* struct ofp12_match match; Description of fields. Variable size. */ }; OFP_ASSERT(sizeof(struct ofp12_flow_removed) == 40); #endif /* openflow/openflow-1.2.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/netronome-ext.h0000644000000000000000000000013012631676263022074 xustar0030 mtime=1449622707.114444389 30 atime=1456592608.628684029 28 ctime=1456594660.3212942 openvswitch-2.5.0/include/openflow/netronome-ext.h0000664000175000017500000000512012631676263023564 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Netronome. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef OPENFLOW_NETRONOME_EXT_H #define OPENFLOW_NETRONOME_EXT_H 1 #include "openflow/openflow.h" #include "openvswitch/types.h" /* The following vendor extension, proposed by Netronome, is not yet * standardized, so they are not included in openflow.h. It may * be suitable for standardization */ /* Netronome enhanced select group */ enum ntr_group_mod_subtype { NTRT_SELECTION_METHOD = 1, }; #define NTR_MAX_SELECTION_METHOD_LEN 16 struct ntr_group_prop_selection_method { ovs_be16 type; /* OFPGPT15_EXPERIMENTER. */ ovs_be16 length; /* Length in bytes of this property * excluding trailing padding. */ ovs_be32 experimenter; /* NTR_VENDOR_ID. */ ovs_be32 exp_type; /* NTRT_SELECTION_METHOD. */ ovs_be32 pad; char selection_method[NTR_MAX_SELECTION_METHOD_LEN]; /* Null-terminated */ ovs_be64 selection_method_param; /* Non-Field parameter for * bucket selection. */ /* Followed by: * - Exactly (length - 40) (possibly 0) bytes containing OXM TLVs, then * - Exactly ((length + 7)/8*8 - length) (between 0 and 7) bytes of * all-zero bytes * In summary, ntr_group_prop_selection_method is padded as needed, * to make its overall size a multiple of 8, to preserve alignment * in structures using it. */ /* uint8_t field_array[0]; */ /* Zero or more fields encoded as * OXM TLVs where the has_mask bit must * be zero and the value it specifies is * a mask to apply to packet fields and * then input them to the selection * method of a select group. */ /* uint8_t pad2[0]; */ }; OFP_ASSERT(sizeof(struct ntr_group_prop_selection_method) == 40); #endif /* openflow/netronome-ext.h */ openvswitch-2.5.0/include/openflow/PaxHeaders.69223/automake.mk0000644000000000000000000000013212631676263021260 xustar0030 mtime=1449622707.114444389 30 atime=1456592426.449208317 30 ctime=1456594659.573262755 openvswitch-2.5.0/include/openflow/automake.mk0000664000175000017500000000143212631676263022750 0ustar00jpettitjpettit00000000000000openflowincludedir = $(includedir)/openflow openflowinclude_HEADERS = \ include/openflow/netronome-ext.h \ include/openflow/nicira-ext.h \ include/openflow/openflow-1.0.h \ include/openflow/openflow-1.1.h \ include/openflow/openflow-1.2.h \ include/openflow/openflow-1.3.h \ include/openflow/openflow-1.4.h \ include/openflow/openflow-1.5.h \ include/openflow/openflow-common.h \ include/openflow/openflow.h if HAVE_PYTHON SUFFIXES += .h .hstamp .h.hstamp: $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/check-structs -I$(srcdir)/include $< && \ touch $@ HSTAMP_FILES = $(openflowinclude_HEADERS:.h=.hstamp) CLEANFILES += $(HSTAMP_FILES) ALL_LOCAL += $(HSTAMP_FILES) $(HSTAMP_FILES): build-aux/check-structs $(openflowinclude_HEADERS) endif EXTRA_DIST += build-aux/check-structs openvswitch-2.5.0/include/PaxHeaders.69223/automake.mk0000644000000000000000000000013212631676263017427 xustar0030 mtime=1449622707.114444389 30 atime=1456592426.441207989 30 ctime=1456594659.573262755 openvswitch-2.5.0/include/automake.mk0000664000175000017500000000073012631676263021117 0ustar00jpettitjpettit00000000000000BUILT_SOURCES += include/odp-netlink.h include/odp-netlink.h: datapath/linux/compat/include/linux/openvswitch.h \ build-aux/extract-odp-netlink-h $(AM_V_GEN)sed -f $(srcdir)/build-aux/extract-odp-netlink-h < $< > $@ EXTRA_DIST += build-aux/extract-odp-netlink-h CLEANFILES += include/odp-netlink.h include include/openflow/automake.mk include include/openvswitch/automake.mk include include/sparse/automake.mk include include/windows/automake.mk openvswitch-2.5.0/include/PaxHeaders.69223/sparse0000644000000000000000000000013212664357344016512 xustar0030 mtime=1456594660.289292856 30 atime=1456594661.701352216 30 ctime=1456594660.289292856 openvswitch-2.5.0/include/sparse/0000775000175000017500000000000012664357344020257 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/sparse/PaxHeaders.69223/rte_vect.h0000644000000000000000000000013212631676263020551 xustar0030 mtime=1449622707.146445513 30 atime=1456592667.331091225 30 ctime=1456594660.289292856 openvswitch-2.5.0/include/sparse/rte_vect.h0000664000175000017500000000147712631676263022252 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif typedef int __m128i; /* Get actual definitions for us to annotate and build on. */ #include_next openvswitch-2.5.0/include/sparse/PaxHeaders.69223/sys0000644000000000000000000000013212664357344017330 xustar0030 mtime=1456594660.293293024 30 atime=1456594661.701352216 30 ctime=1456594660.293293024 openvswitch-2.5.0/include/sparse/sys/0000775000175000017500000000000012664357344021075 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/sparse/sys/PaxHeaders.69223/wait.h0000644000000000000000000000013112130751561020504 xustar0029 mtime=1365496689.37487859 30 atime=1456592667.331091225 30 ctime=1456594660.293293024 openvswitch-2.5.0/include/sparse/sys/wait.h0000664000175000017500000000174212130751561022201 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2011 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif #ifndef __SYS_WAIT_SPARSE #define __SYS_WAIT_SPARSE 1 #include_next #undef wait #define wait(a) rpl_wait(a) pid_t rpl_wait(int *); #undef waitpid #define waitpid(a, b, c) rpl_waitpid(a, b, c) pid_t rpl_waitpid(pid_t, int *, int); #endif /* for sparse */ openvswitch-2.5.0/include/sparse/sys/PaxHeaders.69223/socket.h0000644000000000000000000000013212631676263021044 xustar0030 mtime=1449622707.146445513 30 atime=1456592667.331091225 30 ctime=1456594660.289292856 openvswitch-2.5.0/include/sparse/sys/socket.h0000664000175000017500000000765512631676263022551 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2011, 2012, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif #ifndef __SYS_SOCKET_SPARSE #define __SYS_SOCKET_SPARSE 1 #include "openvswitch/types.h" #include #include typedef unsigned short int sa_family_t; typedef __socklen_t socklen_t; struct sockaddr { sa_family_t sa_family; char sa_data[64]; }; struct sockaddr_storage { sa_family_t ss_family; char sa_data[64]; }; struct msghdr { void *msg_name; socklen_t msg_namelen; struct iovec *msg_iov; int msg_iovlen; void *msg_control; socklen_t msg_controllen; int msg_flags; }; struct cmsghdr { size_t cmsg_len; int cmsg_level; int cmsg_type; unsigned char cmsg_data[]; }; #define __CMSG_ALIGNTO sizeof(size_t) #define CMSG_ALIGN(LEN) \ (((LEN) + __CMSG_ALIGNTO - 1) / __CMSG_ALIGNTO * __CMSG_ALIGNTO) #define CMSG_DATA(CMSG) ((CMSG)->cmsg_data) #define CMSG_LEN(LEN) (sizeof(struct cmsghdr) + (LEN)) #define CMSG_SPACE(LEN) CMSG_ALIGN(CMSG_LEN(LEN)) #define CMSG_FIRSTHDR(MSG) \ ((MSG)->msg_controllen ? (struct cmsghdr *) (MSG)->msg_control : NULL) #define CMSG_NXTHDR(MSG, CMSG) __cmsg_nxthdr(MSG, CMSG) static inline struct cmsghdr * __cmsg_nxthdr(struct msghdr *msg, struct cmsghdr *cmsg) { size_t ofs = (char *) cmsg - (char *) msg->msg_control; size_t next_ofs = ofs + CMSG_ALIGN(cmsg->cmsg_len); return (next_ofs < msg->msg_controllen ? (void *) ((char *) msg->msg_control + next_ofs) : NULL); } enum { SCM_RIGHTS = 1 }; enum { SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET, SOCK_STREAM }; enum { SOL_PACKET, SOL_SOCKET }; enum { SO_ACCEPTCONN, SO_BROADCAST, SO_DEBUG, SO_DONTROUTE, SO_ERROR, SO_KEEPALIVE, SO_LINGER, SO_OOBINLINE, SO_RCVBUF, SO_RCVLOWAT, SO_RCVTIMEO, SO_REUSEADDR, SO_SNDBUF, SO_SNDLOWAT, SO_SNDTIMEO, SO_TYPE, SO_RCVBUFFORCE, SO_ATTACH_FILTER }; enum { MSG_CTRUNC, MSG_DONTROUTE, MSG_EOR, MSG_OOB, MSG_NOSIGNAL, MSG_PEEK, MSG_TRUNC, MSG_WAITALL, MSG_DONTWAIT }; enum { AF_UNSPEC, PF_UNSPEC = AF_UNSPEC, AF_INET, PF_INET = AF_INET, AF_INET6, PF_INET6 = AF_INET6, AF_UNIX, PF_UNIX = AF_UNIX, AF_NETLINK, PF_NETLINK = AF_NETLINK, AF_PACKET, PF_PACKET = AF_PACKET }; enum { SHUT_RD, SHUT_RDWR, SHUT_WR }; int accept(int, struct sockaddr *, socklen_t *); int bind(int, const struct sockaddr *, socklen_t); int connect(int, const struct sockaddr *, socklen_t); int getpeername(int, struct sockaddr *, socklen_t *); int getsockname(int, struct sockaddr *, socklen_t *); int getsockopt(int, int, int, void *, socklen_t *); int listen(int, int); ssize_t recv(int, void *, size_t, int); ssize_t recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *); ssize_t recvmsg(int, struct msghdr *, int); ssize_t send(int, const void *, size_t, int); ssize_t sendmsg(int, const struct msghdr *, int); ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t); int setsockopt(int, int, int, const void *, socklen_t); int shutdown(int, int); int sockatmark(int); int socket(int, int, int); int socketpair(int, int, int, int[2]); #endif /* for sparse */ openvswitch-2.5.0/include/sparse/PaxHeaders.69223/pthread.h0000644000000000000000000000013112631676263020364 xustar0030 mtime=1449622707.142445372 29 atime=1456592667.32709106 30 ctime=1456594660.285292688 openvswitch-2.5.0/include/sparse/pthread.h0000664000175000017500000000227612631676263022064 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif /* Get actual definitions for us to annotate and build on. */ #include_next /* Sparse complains about the proper PTHREAD_*_INITIALIZER definitions. * Luckily, it's not a real compiler so we can overwrite it with something * simple. */ #undef PTHREAD_MUTEX_INITIALIZER #define PTHREAD_MUTEX_INITIALIZER {} #undef PTHREAD_RWLOCK_INITIALIZER #define PTHREAD_RWLOCK_INITIALIZER {} #undef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP #define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP {} openvswitch-2.5.0/include/sparse/PaxHeaders.69223/arpa0000644000000000000000000000013212664357344017435 xustar0030 mtime=1456594660.277292351 30 atime=1456594661.701352216 30 ctime=1456594660.277292351 openvswitch-2.5.0/include/sparse/arpa/0000775000175000017500000000000012664357344021202 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/sparse/arpa/PaxHeaders.69223/inet.h0000644000000000000000000000013012130751561020603 xustar0029 mtime=1365496689.37487859 29 atime=1456592667.32709106 30 ctime=1456594660.277292351 openvswitch-2.5.0/include/sparse/arpa/inet.h0000664000175000017500000000133612130751561022300 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2011 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif #include openvswitch-2.5.0/include/sparse/PaxHeaders.69223/netpacket0000644000000000000000000000013212664357344020470 xustar0030 mtime=1456594660.285292688 30 atime=1456594661.701352216 30 ctime=1456594660.285292688 openvswitch-2.5.0/include/sparse/netpacket/0000775000175000017500000000000012664357344022235 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/sparse/netpacket/PaxHeaders.69223/packet.h0000644000000000000000000000013112631676263022162 xustar0030 mtime=1449622707.142445372 29 atime=1456592667.32709106 30 ctime=1456594660.285292688 openvswitch-2.5.0/include/sparse/netpacket/packet.h0000664000175000017500000000210412631676263023650 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif #ifndef __NETPACKET_PACKET_SPARSE #define __NETPACKET_PACKET_SPARSE 1 #include "openvswitch/types.h" struct sockaddr_ll { unsigned short int sll_family; ovs_be16 sll_protocol; int sll_ifindex; unsigned short int sll_hatype; unsigned char sll_pkttype; unsigned char sll_halen; unsigned char sll_addr[8]; }; #endif /* sparse */ openvswitch-2.5.0/include/sparse/PaxHeaders.69223/assert.h0000644000000000000000000000012712130751561020230 xustar0029 mtime=1365496689.37487859 29 atime=1456592667.32709106 29 ctime=1456594660.28129252 openvswitch-2.5.0/include/sparse/assert.h0000664000175000017500000000143312130751561021715 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2011 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif extern void __ovs_assert(_Bool); #define assert(EXPRESSION) __ovs_assert(EXPRESSION) openvswitch-2.5.0/include/sparse/PaxHeaders.69223/math.h0000644000000000000000000000013012631676263017665 xustar0030 mtime=1449622707.142445372 29 atime=1456592667.32709106 29 ctime=1456594660.28129252 openvswitch-2.5.0/include/sparse/math.h0000664000175000017500000001313212631676263021357 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2011, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif #ifndef __SYS_MATH_SPARSE #define __SYS_MATH_SPARSE 1 double acos(double); float acosf(float); double acosh(double); float acoshf(float); long double acoshl(long double); long double acosl(long double); double asin(double); float asinf(float); double asinh(double); float asinhf(float); long double asinhl(long double); long double asinl(long double); double atan(double); double atan2(double, double); float atan2f(float, float); long double atan2l(long double, long double); float atanf(float); double atanh(double); float atanhf(float); long double atanhl(long double); long double atanl(long double); double cbrt(double); float cbrtf(float); long double cbrtl(long double); double ceil(double); float ceilf(float); long double ceill(long double); double copysign(double, double); float copysignf(float, float); long double copysignl(long double, long double); double cos(double); float cosf(float); double cosh(double); float coshf(float); long double coshl(long double); long double cosl(long double); double erf(double); double erfc(double); float erfcf(float); long double erfcl(long double); float erff(float); long double erfl(long double); double exp(double); double exp2(double); float exp2f(float); long double exp2l(long double); float expf(float); long double expl(long double); double expm1(double); float expm1f(float); long double expm1l(long double); double fabs(double); float fabsf(float); long double fabsl(long double); double fdim(double, double); float fdimf(float, float); long double fdiml(long double, long double); double floor(double); float floorf(float); long double floorl(long double); double fma(double, double, double); float fmaf(float, float, float); long double fmal(long double, long double, long double); double fmax(double, double); float fmaxf(float, float); long double fmaxl(long double, long double); double fmin(double, double); float fminf(float, float); long double fminl(long double, long double); double fmod(double, double); float fmodf(float, float); long double fmodl(long double, long double); double frexp(double, int *); float frexpf(float value, int *); long double frexpl(long double value, int *); double hypot(double, double); float hypotf(float, float); long double hypotl(long double, long double); int ilogb(double); int ilogbf(float); int ilogbl(long double); double j0(double); double j1(double); double jn(int, double); double ldexp(double, int); float ldexpf(float, int); long double ldexpl(long double, int); long long llrint(double); long long llrintf(float); long long llrintl(long double); long long llround(double); long long llroundf(float); long long llroundl(long double); double log(double); double log10(double); float log10f(float); long double log10l(long double); double log1p(double); float log1pf(float); long double log1pl(long double); double log2(double); float log2f(float); long double log2l(long double); double logb(double); float logbf(float); long double logbl(long double); float logf(float); long double logl(long double); long lrint(double); long lrintf(float); long lrintl(long double); long lround(double); long lroundf(float); long lroundl(long double); double modf(double, double *); float modff(float, float *); long double modfl(long double, long double *); double nan(const char *); float nanf(const char *); long double nanl(const char *); double nearbyint(double); float nearbyintf(float); long double nearbyintl(long double); double nextafter(double, double); float nextafterf(float, float); long double nextafterl(long double, long double); double nexttoward(double, long double); float nexttowardf(float, long double); long double nexttowardl(long double, long double); double pow(double, double); float powf(float, float); long double powl(long double, long double); double remainder(double, double); float remainderf(float, float); long double remainderl(long double, long double); double remquo(double, double, int *); float remquof(float, float, int *); long double remquol(long double, long double, int *); double rint(double); float rintf(float); long double rintl(long double); double round(double); float roundf(float); long double roundl(long double); double scalb(double, double); double scalbln(double, long); float scalblnf(float, long); long double scalblnl(long double, long); double scalbn(double, int); float scalbnf(float, int); long double scalbnl(long double, int); double sin(double); float sinf(float); double sinh(double); float sinhf(float); long double sinhl(long double); long double sinl(long double); double sqrt(double); float sqrtf(float); long double sqrtl(long double); double tan(double); float tanf(float); double tanh(double); float tanhf(float); long double tanhl(long double); long double tanl(long double); double tgamma(double); float tgammaf(float); long double tgammal(long double); double trunc(double); float truncf(float); long double truncl(long double); double y0(double); double y1(double); double yn(int, double); #endif /* for sparse */ openvswitch-2.5.0/include/sparse/PaxHeaders.69223/netinet0000644000000000000000000000013212664357344020160 xustar0030 mtime=1456594660.285292688 30 atime=1456594661.701352216 30 ctime=1456594660.285292688 openvswitch-2.5.0/include/sparse/netinet/0000775000175000017500000000000012664357344021725 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/include/sparse/netinet/PaxHeaders.69223/ip6.h0000644000000000000000000000013112631270603021065 xustar0030 mtime=1449488771.915992872 29 atime=1456592667.32709106 30 ctime=1456594660.285292688 openvswitch-2.5.0/include/sparse/netinet/ip6.h0000664000175000017500000000337712631270603022570 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2011 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif #ifndef __NETINET_IP6_SPARSE #define __NETINET_IP6_SPARSE 1 #include struct ip6_hdr { union { struct ip6_hdrctl { ovs_be32 ip6_un1_flow; ovs_be16 ip6_un1_plen; uint8_t ip6_un1_nxt; uint8_t ip6_un1_hlim; } ip6_un1; uint8_t ip6_un2_vfc; } ip6_ctlun; struct in6_addr ip6_src; struct in6_addr ip6_dst; }; #define ip6_vfc ip6_ctlun.ip6_un2_vfc #define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow #define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen #define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt #define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim #define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim struct ip6_rthdr { uint8_t ip6r_nxt; uint8_t ip6r_len; uint8_t ip6r_type; uint8_t ip6r_segleft; }; struct ip6_ext { uint8_t ip6e_nxt; uint8_t ip6e_len; }; struct ip6_frag { uint8_t ip6f_nxt; uint8_t ip6f_reserved; ovs_be16 ip6f_offlg; ovs_be32 ip6f_ident; }; #define IP6F_OFF_MASK ((OVS_FORCE ovs_be16) 0xfff8) #endif /* netinet/ip6.h sparse */ openvswitch-2.5.0/include/sparse/netinet/PaxHeaders.69223/in.h0000644000000000000000000000013212664352753021013 xustar0030 mtime=1456592363.442621001 30 atime=1456592368.182815687 30 ctime=1456594660.285292688 openvswitch-2.5.0/include/sparse/netinet/in.h0000664000175000017500000000737012664352753022512 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2011, 2013, 2014, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif #ifndef __NETINET_IN_SPARSE #define __NETINET_IN_SPARSE 1 #include "openvswitch/types.h" #include #include typedef ovs_be16 in_port_t; typedef ovs_be32 in_addr_t; struct in_addr { in_addr_t s_addr; }; struct sockaddr_in { sa_family_t sin_family; in_port_t sin_port; struct in_addr sin_addr; }; struct in6_addr { union { uint8_t u_s6_addr[16]; } u; }; #define s6_addr u.u_s6_addr extern const struct in6_addr in6addr_any; /* Ditto, for IPv6. */ struct sockaddr_in6 { sa_family_t sin6_family; in_port_t sin6_port; /* Transport layer port # */ uint32_t sin6_flowinfo; /* IPv6 flow information */ struct in6_addr sin6_addr; /* IPv6 address */ uint32_t sin6_scope_id; /* IPv6 scope-id */ }; #define IPPROTO_IP 0 #define IPPROTO_IPV6 41 #define IPPROTO_HOPOPTS 0 #define IPPROTO_ICMP 1 #define IPPROTO_IGMP 2 #define IPPROTO_TCP 6 #define IPPROTO_UDP 17 #define IPPROTO_ROUTING 43 #define IPPROTO_FRAGMENT 44 #define IPPROTO_GRE 47 #define IPPROTO_ESP 50 #define IPPROTO_AH 51 #define IPPROTO_ICMPV6 58 #define IPPROTO_NONE 59 #define IPPROTO_DSTOPTS 60 #define IPPROTO_SCTP 132 #define IPPORT_FTP 21 /* All the IP options documented in Linux ip(7). */ #define IP_ADD_MEMBERSHIP 0 #define IP_DROP_MEMBERSHIP 1 #define IP_HDRINCL 2 #define IP_MTU 3 #define IP_MTU_DISCOVER 4 #define IP_MULTICAST_IF 5 #define IP_MULTICAST_LOOP 6 #define IP_MULTICAST_TTL 7 #define IP_NODEFRAG 8 #define IP_OPTIONS 9 #define IP_PKTINFO 10 #define IP_RECVERR 11 #define IP_RECVOPTS 12 #define IP_RECVTOS 13 #define IP_RECVTTL 14 #define IP_RETOPTS 15 #define IP_ROUTER_ALERT 16 #define IP_TOS 17 #define IP_TTL 18 #define INADDR_ANY 0x00000000 #define INADDR_BROADCAST 0xffffffff #define INADDR_LOOPBACK 0x7f000001 #define INADDR_NONE 0xffffffff #define IN6_IS_ADDR_V4MAPPED(X) \ ((X)->s6_addr[0] == 0 && \ (X)->s6_addr[1] == 0 && \ (X)->s6_addr[2] == 0 && \ (X)->s6_addr[3] == 0 && \ (X)->s6_addr[4] == 0 && \ (X)->s6_addr[5] == 0 && \ (X)->s6_addr[6] == 0 && \ (X)->s6_addr[7] == 0 && \ (X)->s6_addr[8] == 0 && \ (X)->s6_addr[9] == 0 && \ (X)->s6_addr[10] == 0xff && \ (X)->s6_addr[11] == 0xff) #define INET6_ADDRSTRLEN 46 #define IPV6_TCLASS 67 static inline ovs_be32 htonl(uint32_t x) { return (OVS_FORCE ovs_be32) x; } static inline ovs_be16 htons(uint16_t x) { return (OVS_FORCE ovs_be16) x; } static inline uint32_t ntohl(ovs_be32 x) { return (OVS_FORCE uint32_t) x; } static inline uint16_t ntohs(ovs_be16 x) { return (OVS_FORCE uint16_t) x; } in_addr_t inet_addr(const char *); int inet_aton (const char *, struct in_addr *); const char *inet_ntop(int, const void *, char *, socklen_t); int inet_pton(int, const char *, void *); #endif /* sparse */ openvswitch-2.5.0/include/sparse/PaxHeaders.69223/rte_lcore.h0000644000000000000000000000013212631676263020714 xustar0030 mtime=1449622707.146445513 30 atime=1456592667.331091225 30 ctime=1456594660.289292856 openvswitch-2.5.0/include/sparse/rte_lcore.h0000664000175000017500000000150612631676263022406 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif typedef int rte_cpuset_t; /* Get actual definitions for us to annotate and build on. */ #include_next openvswitch-2.5.0/include/sparse/PaxHeaders.69223/bmi2intrin.h0000644000000000000000000000013012631676263021011 xustar0030 mtime=1449622707.142445372 29 atime=1456592667.32709106 29 ctime=1456594660.28129252 openvswitch-2.5.0/include/sparse/bmi2intrin.h0000664000175000017500000000166212631676263022510 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif /* Sparse doesn't know the __int128 type used by GCC 4.9 *intrin.h headers. * We cannot use a typedef because the type is used with a qualifier * ('unsigned __int128') */ #define __int128 int #include_next #undef __int128 openvswitch-2.5.0/include/sparse/PaxHeaders.69223/rte_atomic.h0000644000000000000000000000013212631676263021064 xustar0030 mtime=1449622707.146445513 30 atime=1456592667.331091225 30 ctime=1456594660.289292856 openvswitch-2.5.0/include/sparse/rte_atomic.h0000664000175000017500000000166412631676263022563 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif /* Fix sparse technicality about types in one of the function calls by just * ignoring it. */ #define __sync_add_and_fetch(a, b) (0) /* Get actual definitions for us to annotate and build on. */ #include_next openvswitch-2.5.0/include/sparse/PaxHeaders.69223/emmintrin.h0000644000000000000000000000013012631676263020736 xustar0030 mtime=1449622707.142445372 29 atime=1456592667.32709106 29 ctime=1456594660.28129252 openvswitch-2.5.0/include/sparse/emmintrin.h0000664000175000017500000000160312631676263022430 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKER__ #error "Use this header only with sparse. It is not a correct implementation." #endif /* GCC 4.8 *intrin.h headers do not work if these are not defined */ #define __SSE2__ #define __SSE__ #define __MMX__ #include_next #undef __MMX__ #undef __SSE__ #undef __SSE2__ openvswitch-2.5.0/include/sparse/PaxHeaders.69223/automake.mk0000644000000000000000000000013212631676263020724 xustar0030 mtime=1449622707.142445372 30 atime=1456592426.457208646 30 ctime=1456594659.577262924 openvswitch-2.5.0/include/sparse/automake.mk0000664000175000017500000000103112631676263022407 0ustar00jpettitjpettit00000000000000noinst_HEADERS += \ include/sparse/arpa/inet.h \ include/sparse/assert.h \ include/sparse/bmi2intrin.h \ include/sparse/emmintrin.h \ include/sparse/math.h \ include/sparse/netinet/in.h \ include/sparse/netinet/ip6.h \ include/sparse/netpacket/packet.h \ include/sparse/pthread.h \ include/sparse/rte_atomic.h \ include/sparse/rte_lcore.h \ include/sparse/rte_vect.h \ include/sparse/sys/socket.h \ include/sparse/sys/wait.h openvswitch-2.5.0/PaxHeaders.69223/IntegrationGuide.md0000644000000000000000000000013212631676262017427 xustar0030 mtime=1449622706.906437079 30 atime=1456592667.291089585 30 ctime=1456594659.661266455 openvswitch-2.5.0/IntegrationGuide.md0000664000175000017500000001727712631676262021135 0ustar00jpettitjpettit00000000000000Integration Guide for Centralized Control ========================================= This document describes how to integrate Open vSwitch onto a new platform to expose the state of the switch and attached devices for centralized control. (If you are looking to port the switching components of Open vSwitch to a new platform, please see the PORTING document.) The focus of this guide is on hypervisors, but many of the interfaces are useful for hardware switches, as well. The XenServer integration is the most mature implementation, so most of the examples are drawn from it. The externally visible interface to this integration is platform-agnostic. We encourage anyone who integrates Open vSwitch to use the same interface, because keeping a uniform interface means that controllers require less customization for individual platforms (and perhaps no customization at all). Integration centers around the Open vSwitch database and mostly involves the 'external_ids' columns in several of the tables. These columns are not interpreted by Open vSwitch itself. Instead, they provide information to a controller that permits it to associate a database record with a more meaningful entity. In contrast, the 'other_config' column is used to configure behavior of the switch. The main job of the integrator, then, is to ensure that these values are correctly populated and maintained. An integrator sets the columns in the database by talking to the ovsdb-server daemon. A few of the columns can be set during startup by calling the ovs-ctl tool from inside the startup scripts. The 'xenserver/etc_init.d_openvswitch' script provides examples of its use, and the ovs-ctl(8) manpage contains complete documentation. At runtime, ovs-vsctl can be be used to set columns in the database. The script 'xenserver/etc_xensource_scripts_vif' contains examples of its use, and ovs-vsctl(8) manpage contains complete documentation. Python and C bindings to the database are provided if deeper integration with a program are needed. The XenServer ovs-xapi-sync daemon ('xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync') provides an example of using the Python bindings. More information on the python bindings is available at 'python/ovs/db/idl.py'. Information on the C bindings is available at 'lib/ovsdb-idl.h'. The following diagram shows how integration scripts fit into the Open vSwitch architecture: +----------------------------------------+ | Controller Cluster + +----------------------------------------+ | | +----------------------------------------------------------+ | | | | +--------------+---------------+ | | | | | | +-------------------+ +------------------+ | | | ovsdb-server |-----------| ovs-vswitchd | | | +-------------------+ +------------------+ | | | | | | +---------------------+ | | | | Integration scripts | | | | | (ex: ovs-xapi-sync) | | | | +---------------------+ | | | | Userspace | |----------------------------------------------------------| | | Kernel | | | | | +---------------------+ | | | OVS Kernel Module | | | +---------------------+ | +----------------------------------------------------------+ A description of the most relevant fields for integration follows. By setting these values, controllers are able to understand the network and manage it more dynamically and precisely. For more details about the database and each individual column, please refer to the ovs-vswitchd.conf.db(5) manpage. Open_vSwitch table ------------------ The Open_vSwitch table describes the switch as a whole. The 'system_type' and 'system_version' columns identify the platform to the controller. The 'external_ids:system-id' key uniquely identifies the physical host. In XenServer, the system-id will likely be the same as the UUID returned by 'xe host-list'. This key allows controllers to distinguish between multiple hypervisors. Most of this configuration can be done with the ovs-ctl command at startup. For example: ovs-ctl --system-type="XenServer" --system-version="6.0.0-50762p" \ --system-id="${UUID}" "${other_options}" start Alternatively, the ovs-vsctl command may be used to set a particular value at runtime. For example: ovs-vsctl set open_vswitch . external-ids:system-id='"${UUID}"' The 'other_config:enable-statistics' key may be set to "true" to have OVS populate the database with statistics (e.g., number of CPUs, memory, system load) for the controller's use. Bridge table ------------ The Bridge table describes individual bridges within an Open vSwitch instance. The 'external-ids:bridge-id' key uniquely identifies a particular bridge. In XenServer, this will likely be the same as the UUID returned by 'xe network-list' for that particular bridge. For example, to set the identifier for bridge "br0", the following command can be used: ovs-vsctl set Bridge br0 external-ids:bridge-id='"${UUID}"' The MAC address of the bridge may be manually configured by setting it with the "other_config:hwaddr" key. For example: ovs-vsctl set Bridge br0 other_config:hwaddr="12:34:56:78:90:ab" Interface table --------------- The Interface table describes an interface under the control of Open vSwitch. The 'external_ids' column contains keys that are used to provide additional information about the interface: attached-mac This field contains the MAC address of the device attached to the interface. On a hypervisor, this is the MAC address of the interface as seen inside a VM. It does not necessarily correlate to the host-side MAC address. For example, on XenServer, the MAC address on a VIF in the hypervisor is always FE:FF:FF:FF:FF:FF, but inside the VM a normal MAC address is seen. iface-id This field uniquely identifies the interface. In hypervisors, this allows the controller to follow VM network interfaces as VMs migrate. A well-chosen identifier should also allow an administrator or a controller to associate the interface with the corresponding object in the VM management system. For example, the Open vSwitch integration with XenServer by default uses the XenServer assigned UUID for a VIF record as the iface-id. iface-status In a hypervisor, there are situations where there are multiple interface choices for a single virtual ethernet interface inside a VM. Valid values are "active" and "inactive". A complete description is available in the ovs-vswitchd.conf.db(5) manpage. vm-id This field uniquely identifies the VM to which this interface belongs. A single VM may have multiple interfaces attached to it. As in the previous tables, the ovs-vsctl command may be used to configure the values. For example, to set the 'iface-id' on eth0, the following command can be used: ovs-vsctl set Interface eth0 external-ids:iface-id='"${UUID}"' openvswitch-2.5.0/PaxHeaders.69223/windows0000644000000000000000000000013212664357344015264 xustar0030 mtime=1456594660.241290838 30 atime=1456594661.701352216 30 ctime=1456594660.241290838 openvswitch-2.5.0/windows/0000775000175000017500000000000012664357344017031 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/windows/PaxHeaders.69223/ovs-windows-installer.sln0000644000000000000000000000013212631676263022347 xustar0030 mtime=1449622707.606461677 30 atime=1456592667.491097785 30 ctime=1456594660.241290838 openvswitch-2.5.0/windows/ovs-windows-installer.sln0000664000175000017500000000171312631676263024041 0ustar00jpettitjpettit00000000000000Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "ovs-windows-installer", "ovs-windows-installer\ovs-windows-installer.wixproj", "{259905A2-7434-4190-8A33-8FBA67171DD6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {259905A2-7434-4190-8A33-8FBA67171DD6}.Release|x64.ActiveCfg = Release|x86 {259905A2-7434-4190-8A33-8FBA67171DD6}.Release|x64.Build.0 = Release|x86 {259905A2-7434-4190-8A33-8FBA67171DD6}.Release|x86.ActiveCfg = Release|x86 {259905A2-7434-4190-8A33-8FBA67171DD6}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal openvswitch-2.5.0/windows/PaxHeaders.69223/ovs-windows-installer0000644000000000000000000000013012664357344021554 xustar0029 mtime=1456594660.25729151 30 atime=1456594661.701352216 29 ctime=1456594660.25729151 openvswitch-2.5.0/windows/ovs-windows-installer/0000775000175000017500000000000012664357344023323 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/Product.wxs0000644000000000000000000000013212631676263024014 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.495097949 30 ctime=1456594660.253291342 openvswitch-2.5.0/windows/ovs-windows-installer/Product.wxs0000664000175000017500000003022312631676263025504 0ustar00jpettitjpettit00000000000000 = 602)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> "ALL" AND (&OpenvSwitchDriver = 3)]]> openvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/Actions0000644000000000000000000000013212664357344023156 xustar0030 mtime=1456594660.245291006 30 atime=1456594661.701352216 30 ctime=1456594660.245291006 openvswitch-2.5.0/windows/ovs-windows-installer/Actions/0000775000175000017500000000000012664357344024723 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/windows/ovs-windows-installer/Actions/PaxHeaders.69223/OVSActions.js0000644000000000000000000000013212631676263025557 xustar0030 mtime=1449622707.606461677 30 atime=1456592667.491097785 30 ctime=1456594660.245291006 openvswitch-2.5.0/windows/ovs-windows-installer/Actions/OVSActions.js0000664000175000017500000001626612631676263027262 0ustar00jpettitjpettit00000000000000/* Copyright 2015 Cloudbase Solutions Srl All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // http://msdn.microsoft.com/en-us/library/sfw6660x(VS.85).aspx var Buttons = { OkOnly: 0, OkCancel: 1, AbortRetryIgnore: 2, YesNoCancel: 3 }; var Icons = { Critical: 16, Question: 32, Exclamation: 48, Information: 64 } var MsgKind = { Error: 0x01000000, Warning: 0x02000000, User: 0x03000000, Log: 0x04000000 }; // http://msdn.microsoft.com/en-us/library/aa371254(VS.85).aspx var MsiActionStatus = { None: 0, Ok: 1, // success Cancel: 2, Abort: 3, Retry: 4, // aka suspend? Ignore: 5 // skip remaining actions; this is not an error. }; var ServiceStartAction = { Stop: "Stop", Start: "Start", Restart: "Restart" }; var ServiceStartMode = { Boot: "Boot", System: "System", Auto: "Auto", Manual: "Manual", Disabled: "Disabled" }; function throwException(num, msg) { throw { number: num, message: msg }; } function decimalToHexString(number) { if (number < 0) number = 0xFFFFFFFF + number + 1; return number.toString(16).toUpperCase(); } function logMessage(msg) { var record = Session.Installer.CreateRecord(0); record.StringData(0) = "CustomActions: " + msg; Session.Message(MsgKind.Log, record); } function logMessageEx(msg, type) { var record = Session.Installer.CreateRecord(0); record.StringData(0) = msg; Session.Message(type, record); } function logException(exc) { var record = Session.Installer.CreateRecord(0); record.StringData(0) = exc.message == "" ? "An exception occurred: 0x" + decimalToHexString(exc.number) : exc.message; Session.Message(MsgKind.Error + Icons.Critical + Buttons.OkOnly, record); // Log the full exception as well record.StringData(0) = "CustomAction exception details: 0x" + decimalToHexString(exc.number) + " : " + exc.message; Session.Message(MsgKind.Log, record); } function runCommand(cmd, expectedReturnValue, envVars, windowStyle, waitOnReturn, workingDir) { var shell = new ActiveXObject("WScript.Shell"); logMessage("Running command: " + cmd); if (envVars) { var env = shell.Environment("Process"); for (var k in envVars) env(k) = envVars[k]; } if (typeof windowStyle == 'undefined') windowStyle = 0; if (typeof waitOnReturn == 'undefined') waitOnReturn = true; if (typeof workingDir == 'undefined') workingDir = null; if (workingDir) { shell.CurrentDirectory = workingDir; } var retVal = shell.run(cmd, windowStyle, waitOnReturn); if (waitOnReturn && expectedReturnValue != undefined && expectedReturnValue != null && retVal != expectedReturnValue) throwException(-1, "Command failed. Return value: " + retVal.toString()); logMessage("Command completed. Return value: " + retVal); return retVal; } function getWmiCimV2Svc() { return GetObject("winmgmts:\\\\.\\root\\cimv2"); } function getSafeArray(jsArr) { var dict = new ActiveXObject("Scripting.Dictionary"); for (var i = 0; i < jsArr.length; i++) dict.add(i, jsArr[i]); return dict.Items(); } function invokeWMIMethod(svc, methodName, inParamsValues, wmiSvc, jobOutParamName) { logMessage("Invoking " + methodName); var inParams = null; if (inParamsValues) { for (var k in inParamsValues) { if (!inParams) inParams = svc.Methods_(methodName).InParameters.SpawnInstance_(); var val = inParamsValues[k]; if (val instanceof Array) inParams[k] = getSafeArray(val); else inParams[k] = val; } } var outParams = svc.ExecMethod_(methodName, inParams); if (outParams.ReturnValue == 4096) { var job = wmiSvc.Get(outParams[jobOutParamName]); waitForJob(wmiSvc, job); } else if (outParams.ReturnValue != 0) throwException(-1, methodName + " failed. Return value: " + outParams.ReturnValue.toString()); return outParams; } function sleep(interval) { // WScript.Sleep is not supported in MSI's WSH. Here's a workaround for the moment. // interval is ignored var numPings = 2; cmd = "ping -n " + numPings + " 127.0.0.1"; var shell = new ActiveXObject("WScript.Shell"); shell.run(cmd, 0, true); } function getService(serviceName) { var wmiSvc = getWmiCimV2Svc(); return wmiSvc.ExecQuery("SELECT * FROM Win32_Service WHERE Name='" + serviceName + "'").ItemIndex(0); } function changeService(serviceName, startMode, startAction) { var svc = getService(serviceName); if ((startAction == ServiceStartAction.Stop || startAction == ServiceStartAction.Restart) && svc.Started) invokeWMIMethod(svc, "StopService"); if (startMode && svc.StartMode != startMode) invokeWMIMethod(svc, "ChangeStartMode", { "StartMode": (startMode == ServiceStartMode.Auto ? "Automatic" : startMode) }); if (startAction == ServiceStartAction.Restart && svc.Started) { var wmiSvc = getWmiCimV2Svc(); do { sleep(200); svc = wmiSvc.Get(svc.Path_); } while (svc.Started); } if ((startAction == ServiceStartAction.Start || startAction == ServiceStartAction.Restart) && !svc.Started) invokeWMIMethod(svc, "StartService"); } function runCommandAction() { var exceptionMsg = null; try { var data = Session.Property("CustomActionData").split('|'); var i = 0; var cmd = data[i++]; var expectedRetValue = data.length > i ? data[i++] : 0; var exceptionMsg = data.length > i ? data[i++] : null; var workingDir = data.length > i ? data[i++] : null; runCommand(cmd, expectedRetValue, null, 0, true, workingDir); return MsiActionStatus.Ok; } catch (ex) { if (exceptionMsg) { logMessageEx(exceptionMsg, MsgKind.Error + Icons.Critical + Buttons.OkOnly); // log also the original exception logMessage(ex.message); } else logException(ex); return MsiActionStatus.Abort; } } function changeServiceAction() { try { var data = Session.Property("CustomActionData").split('|'); var serviceName = data[0]; var startMode = data[1]; var startAction = data[2]; logMessage("Changing service " + serviceName + ", startMode: " + startMode + ", startAction: " + startAction); changeService(serviceName, startMode, startAction); return MsiActionStatus.Ok; } catch (ex) { logMessage(ex.message); return MsiActionStatus.Abort; } }openvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/License.rtf0000644000000000000000000000013212631676263023730 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.495097949 30 ctime=1456594660.249291174 openvswitch-2.5.0/windows/ovs-windows-installer/License.rtf0000664000175000017500000011754012631676263025430 0ustar00jpettitjpettit00000000000000{\rtf1\adeflang1025\ansi\ansicpg1252\uc1\adeff0\deff0\stshfdbch31505\stshfloch31506\stshfhich31506\stshfbi0\deflang1033\deflangfe1033\themelang1033\themelangfe0\themelangcs0{\fonttbl{\f0\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fbidi \fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} {\f34\fbidi \froman\fcharset0\fprq2{\*\panose 02040503050406030204}Cambria Math;}{\flomajor\f31500\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbmajor\f31501\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhimajor\f31502\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0302020204030204}Calibri Light;} {\fbimajor\f31503\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\flominor\f31504\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;} {\fdbminor\f31505\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\fhiminor\f31506\fbidi \fswiss\fcharset0\fprq2{\*\panose 020f0502020204030204}Calibri;} {\fbiminor\f31507\fbidi \froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f39\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\f40\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} {\f42\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\f44\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} {\f46\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\f49\fbidi \fswiss\fcharset238\fprq2 Arial CE;}{\f50\fbidi \fswiss\fcharset204\fprq2 Arial Cyr;} {\f52\fbidi \fswiss\fcharset161\fprq2 Arial Greek;}{\f53\fbidi \fswiss\fcharset162\fprq2 Arial Tur;}{\f54\fbidi \fswiss\fcharset177\fprq2 Arial (Hebrew);}{\f55\fbidi \fswiss\fcharset178\fprq2 Arial (Arabic);} {\f56\fbidi \fswiss\fcharset186\fprq2 Arial Baltic;}{\f57\fbidi \fswiss\fcharset163\fprq2 Arial (Vietnamese);}{\f379\fbidi \froman\fcharset238\fprq2 Cambria Math CE;}{\f380\fbidi \froman\fcharset204\fprq2 Cambria Math Cyr;} {\f382\fbidi \froman\fcharset161\fprq2 Cambria Math Greek;}{\f383\fbidi \froman\fcharset162\fprq2 Cambria Math Tur;}{\f386\fbidi \froman\fcharset186\fprq2 Cambria Math Baltic;}{\f387\fbidi \froman\fcharset163\fprq2 Cambria Math (Vietnamese);} {\flomajor\f31508\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flomajor\f31509\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flomajor\f31511\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} {\flomajor\f31512\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flomajor\f31513\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flomajor\f31514\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} {\flomajor\f31515\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flomajor\f31516\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbmajor\f31518\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} {\fdbmajor\f31519\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbmajor\f31521\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbmajor\f31522\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} {\fdbmajor\f31523\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbmajor\f31524\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbmajor\f31525\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} {\fdbmajor\f31526\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhimajor\f31528\fbidi \fswiss\fcharset238\fprq2 Calibri Light CE;}{\fhimajor\f31529\fbidi \fswiss\fcharset204\fprq2 Calibri Light Cyr;} {\fhimajor\f31531\fbidi \fswiss\fcharset161\fprq2 Calibri Light Greek;}{\fhimajor\f31532\fbidi \fswiss\fcharset162\fprq2 Calibri Light Tur;}{\fhimajor\f31535\fbidi \fswiss\fcharset186\fprq2 Calibri Light Baltic;} {\fhimajor\f31536\fbidi \fswiss\fcharset163\fprq2 Calibri Light (Vietnamese);}{\fbimajor\f31538\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbimajor\f31539\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} {\fbimajor\f31541\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbimajor\f31542\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbimajor\f31543\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} {\fbimajor\f31544\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbimajor\f31545\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbimajor\f31546\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);} {\flominor\f31548\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\flominor\f31549\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\flominor\f31551\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;} {\flominor\f31552\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\flominor\f31553\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\flominor\f31554\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);} {\flominor\f31555\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\flominor\f31556\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fdbminor\f31558\fbidi \froman\fcharset238\fprq2 Times New Roman CE;} {\fdbminor\f31559\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;}{\fdbminor\f31561\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fdbminor\f31562\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;} {\fdbminor\f31563\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\fdbminor\f31564\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fdbminor\f31565\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;} {\fdbminor\f31566\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}{\fhiminor\f31568\fbidi \fswiss\fcharset238\fprq2 Calibri CE;}{\fhiminor\f31569\fbidi \fswiss\fcharset204\fprq2 Calibri Cyr;} {\fhiminor\f31571\fbidi \fswiss\fcharset161\fprq2 Calibri Greek;}{\fhiminor\f31572\fbidi \fswiss\fcharset162\fprq2 Calibri Tur;}{\fhiminor\f31575\fbidi \fswiss\fcharset186\fprq2 Calibri Baltic;} {\fhiminor\f31576\fbidi \fswiss\fcharset163\fprq2 Calibri (Vietnamese);}{\fbiminor\f31578\fbidi \froman\fcharset238\fprq2 Times New Roman CE;}{\fbiminor\f31579\fbidi \froman\fcharset204\fprq2 Times New Roman Cyr;} {\fbiminor\f31581\fbidi \froman\fcharset161\fprq2 Times New Roman Greek;}{\fbiminor\f31582\fbidi \froman\fcharset162\fprq2 Times New Roman Tur;}{\fbiminor\f31583\fbidi \froman\fcharset177\fprq2 Times New Roman (Hebrew);} {\fbiminor\f31584\fbidi \froman\fcharset178\fprq2 Times New Roman (Arabic);}{\fbiminor\f31585\fbidi \froman\fcharset186\fprq2 Times New Roman Baltic;}{\fbiminor\f31586\fbidi \froman\fcharset163\fprq2 Times New Roman (Vietnamese);}} {\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0; \red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\*\defchp \fs22\loch\af31506\hich\af31506\dbch\af31505 }{\*\defpap \ql \li0\ri0\sa160\sl259\slmult1 \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 }\noqfpromote {\upr{\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1 \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}}{\*\ud\uc0{\stylesheet{\ql \li0\ri0\sa160\sl259\slmult1\widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext0 \sqformat \spriority0 Normal;}{\*\cs10 \additive \ssemihidden \sunhideused \spriority1 Default Paragraph Font;}{\* \ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tblind0\tblindtype3\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv \ql \li0\ri0\sa160\sl259\slmult1 \widctlpar\wrapdefault\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\f31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 \snext11 \ssemihidden \sunhideused Normal Table;}}}}{\*\rsidtbl \rsid2365717\rsid7145912\rsid7612545}{\mmathPr\mmathFont34\mbrkBin0\mbrkBinSub0\msmallFrac0\mdispDef1\mlMargin0\mrMargin0\mdefJc1\mwrapIndent1440\mintLim0\mnaryLim1}{\info{\operator alin.cloudbase} {\creatim\yr2015\mo4\dy2\hr16\min46}{\revtim\yr2015\mo5\dy25\hr20\min39}{\version3}{\edmins0}{\nofpages1}{\nofwords86}{\nofchars492}{\nofcharsws577}{\vern57439}}{\*\xmlnstbl {\xmlns1 http://schemas.microsoft.com/office/word/2003/wordml}} \paperw12240\paperh15840\margl1440\margr1440\margt1440\margb1440\gutter0\ltrsect \widowctrl\ftnbj\aenddoc\trackmoves0\trackformatting1\donotembedsysfont0\relyonvml0\donotembedlingdata1\grfdocevents0\validatexml0\showplaceholdtext0\ignoremixedcontent0\saveinvalidxml0\showxmlerrors0\horzdoc\dghspace120\dgvspace120\dghorigin1701 \dgvorigin1984\dghshow0\dgvshow3\jcompress\viewkind1\viewscale100\rsidroot7145912 \nouicompat \fet0{\*\wgrffmtfilter 2450}\nofeaturethrottle1\ilfomacatclnup0\ltrpar \sectd \ltrsect\linex0\sectdefaultcl\sftnbj {\*\pnseclvl1 \pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5 \pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain \ltrpar\qj \li0\ri0\nowidctlpar\tx959\tx1918\tx2877\tx3836\tx4795\tx5754\tx6713\tx7672\tx8631\wrapdefault\faauto\rin0\lin0\itap0 \rtlch\fcs1 \af0\afs22\alang1025 \ltrch\fcs0 \fs22\lang1033\langfe1033\loch\af31506\hich\af31506\dbch\af31505\cgrid\langnp1033\langfenp1033 {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\insrsid2365717 \hich\af1\dbch\af31505\loch\f1 Licensed under the Apache License, Version 2.0 (the "License"); \par \hich\af1\dbch\af31505\loch\f1 you may not use this file except in compliance with the License. \par \hich\af1\dbch\af31505\loch\f1 You may obtain a copy of the License at \par \par }{\field{\*\fldinst {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\insrsid2365717 \hich\af1\dbch\af31505\loch\f1 HYPERLINK http://www.apache.org/licenses/LICENSE-2.0 }{\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\insrsid7145912 {\*\datafield 00d0c9ea79f9bace118c8200aa004ba90b0200000003000000e0c9ea79f9bace118c8200aa004ba90b6e00000068007400740070003a002f002f007700770077002e006100700061006300680065002e006f00720067002f006c006900630065006e007300650073002f004c004900430045004e00530045002d0032002e00 30000000795881f43b1d7f48af2c825dc485276300000000a5ab000069}}}{\fldrslt {\rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\insrsid2365717 \hich\af1\dbch\af31505\loch\f1 http://www.apache.org/licenses/LICENSE-2.0}}}\sectd \ltrsect\linex0\sectdefaultcl\sftnbj { \rtlch\fcs1 \af1\afs18 \ltrch\fcs0 \f1\fs18\insrsid2365717 \par \par \hich\af1\dbch\af31505\loch\f1 Un\hich\af1\dbch\af31505\loch\f1 less required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, \par \hich\af1\dbch\af31505\loch\f1 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. \par \hich\af1\dbch\af31505\loch\f1 See the License for the specific language governing\hich\af1\dbch\af31505\loch\f1 permissions and \par \hich\af1\dbch\af31505\loch\f1 limitations under the License. \par }\pard \ltrpar\qj \li0\ri0\sa200\sl276\slmult1\nowidctlpar\wrapdefault\faauto\rin0\lin0\itap0 {\rtlch\fcs1 \af1\afs20 \ltrch\fcs0 \f1\fs20\lang16\langfe1033\langnp16\insrsid2365717 \par }{\*\themedata 504b030414000600080000002100e9de0fbfff0000001c020000130000005b436f6e74656e745f54797065735d2e786d6cac91cb4ec3301045f748fc83e52d4a 9cb2400825e982c78ec7a27cc0c8992416c9d8b2a755fbf74cd25442a820166c2cd933f79e3be372bd1f07b5c3989ca74aaff2422b24eb1b475da5df374fd9ad 5689811a183c61a50f98f4babebc2837878049899a52a57be670674cb23d8e90721f90a4d2fa3802cb35762680fd800ecd7551dc18eb899138e3c943d7e503b6 b01d583deee5f99824e290b4ba3f364eac4a430883b3c092d4eca8f946c916422ecab927f52ea42b89a1cd59c254f919b0e85e6535d135a8de20f20b8c12c3b0 0c895fcf6720192de6bf3b9e89ecdbd6596cbcdd8eb28e7c365ecc4ec1ff1460f53fe813d3cc7f5b7f020000ffff0300504b030414000600080000002100a5d6 a7e7c0000000360100000b0000005f72656c732f2e72656c73848fcf6ac3300c87ef85bd83d17d51d2c31825762fa590432fa37d00e1287f68221bdb1bebdb4f c7060abb0884a4eff7a93dfeae8bf9e194e720169aaa06c3e2433fcb68e1763dbf7f82c985a4a725085b787086a37bdbb55fbc50d1a33ccd311ba548b6309512 0f88d94fbc52ae4264d1c910d24a45db3462247fa791715fd71f989e19e0364cd3f51652d73760ae8fa8c9ffb3c330cc9e4fc17faf2ce545046e37944c69e462 a1a82fe353bd90a865aad41ed0b5b8f9d6fd010000ffff0300504b0304140006000800000021006b799616830000008a0000001c0000007468656d652f746865 6d652f7468656d654d616e616765722e786d6c0ccc4d0ac3201040e17da17790d93763bb284562b2cbaebbf600439c1a41c7a0d29fdbd7e5e38337cedf14d59b 4b0d592c9c070d8a65cd2e88b7f07c2ca71ba8da481cc52c6ce1c715e6e97818c9b48d13df49c873517d23d59085adb5dd20d6b52bd521ef2cdd5eb9246a3d8b 4757e8d3f729e245eb2b260a0238fd010000ffff0300504b030414000600080000002100e67505bed10600008b1a0000160000007468656d652f7468656d652f 7468656d65312e786d6cec59cf8b1b3714be17fa3f0c7377fc6bc63f9638c11edb499b6c1262272547d9963dca6a466624efc68440498e8542695a7a68a0b71e 4adb4002bda4b7fe276953da14fa2ff449331e4bb6dcdd2c292c256b58c6f2f79e3ebdf7e67b9ad1f98bf722ea1ce2841316b7dcf2b992ebe078cc26249eb5dc 5bc37ea1e13a5ca07882288b71cb5d62ee5ebcf0fe7be7d19e0871841db08ff91e6ab9a110f3bd62918f6118f1736c8e63f86dca920809f89acc8a93041d81df 88162ba552ad182112bb4e8c22703bc4d12f8f9cebd3291963f7c2ca798fc20cb1e072604c9381748d330b0d3b39284b045ff28026ce21a22d17e699b0a321be 275c87222ee087965b527f6ef1c2f922dacb8ca8d861abd9f5d55f6697194c0e2a6ace6436ca27f53cdfabb573ff0a40c536ae57efd57ab5dc9f02a0f118569a 72d17dfa9d66a7eb67580d945e5a7c77ebdd6ad9c06bfeab5b9cdbbefc1878054afd7b5bf87e3f80281a78054af1fe16def3ea95c033f00a94e26b5bf87aa9dd f5ea065e81424ae2832d74c9af5583d56a73c894d1cb5678d3f7faf54ae67c8d826ac8ab4b4e3165b1d8556b11bacb923e002490224162472ce7788ac650c501 a2649410e72a998550787314330ec3a54aa95faac27ff9f1d4958a08dac348b396bc8009df1a927c1c3e4ec85cb4dc0fc1abab41fe7ef1fddf2f9e392f1f3e7f f9f0a7978f1ebd7cf863eac8b0ba8ce2996ef5fadbcffe7af2b1f3e7b36f5e3ffec28ee73afeb71f3ef9f5e7cfed4058e93a04afbe7cfafbf3a7afbefaf48fef 1e5be0ed048d74f89044983bd7f091739345b030150293391e256f66310c11d12ddaf18ca318c9592cfe7b2234d0d79688220bae83cd08de4e40626cc04b8bbb 06e141982c04b178bc124606709f31da6189350a57e45c5a98878b78669f3c59e8b89b081ddae60e506ce4b7b79883b6129bcb20c406cd1b14c502cd708c8523 7f6307185b5677871023aefb649c30cea6c2b9439c0e22d6900cc9c8a8a6b5d16512415e963682906f2336fbb79d0ea3b65577f1a18984bb02510bf921a64618 2fa1854091cde51045540ff85524421bc9c13219ebb81e1790e919a6cce94d30e7369beb09ac574bfa1590177bdaf7e9323291892007369f5711633ab2cb0e82 1045731b7640e250c77ec00fa044917383091b7c9f997788fc0e7940f1ce74df26d848f7f16a700b9455a7b42e10f9cb22b1e4f2126646fd0e96748ab0921a10 7e43cf23121f2bee1bb2eeffb7b20e42faeaeb2796559d55416f27c47a475dde90f15db84df10e583221675fbbbb6811dfc070bb6c37b077d2fd4ebaddffbd74 efba9fdfbe60af351ae45b6e15d3adbadab8473bf7ed5342e9402c29becad5d69d43679af46150daa967569c3fc7cd43b89477324c60e0660952364ec2c44744 848310cd617f5f76a59319cf5ccfb833671cb6fd6ad8ea5be2e922da6793f471b55c968fa6a9787024d6e3253f1f87470d91a26bf5f52358ee5eb19da947e515 0169fb2624b4c94c12550b89fa6a5006493d9843d02c24d4cade0a8ba6854543ba5fa56a8b0550cbb3025b2707365c2dd7f7c0048ce0890a513c91794a53bdca ae4ae6dbccf4ae601a1500fb885505ac33dd945c772e4fae2e2db51364da20a1959b49424546f5301ea209ceaa538e9e84c69be6bab94ea9414f8642cd07a5b5 a6516ffc1b8bd3e61aec36b581c6ba52d0d8396ab9b5aa0f253346f3963b85c77eb88ce6503b5c6e79119dc1bbb3b148d21bfe34ca324fb8e8221ea60157a293 aa4144044e1c4aa2962b979fa781c64a4314b7720504e1cc926b82ac9c3572907433c9783ac563a1a75d1b91914ebf82c2a75a61fd55999f1e2c2dd902d23d08 2747ce882e929b084accaf9765002784c3db9f721acd0981d799b990adeb6fa33165b2abbf4f5435948e233a0f51d65174314fe14aca733aea5b1e03ed5bb666 08a81692ac118e66b2c1ea4135ba69de35520e3bbbeef14632729a68ae7ba6a12ab26bda55cc9861d506366279ba26afb15a8518344deff0a9746f4a6e73a575 1bfb84bc4b40c0f3f859baee091a82466d3d99414d32de9661a9d9d9a8d93b560b3c86da499a84a6fab595db8db8e53dc23a1d0c9eaaf383dd66d5c2d074b5af 549156e71efad1041bdd05f1e8c24be005155ca5120e1e12041ba281da93a4b201b7c83d91dd1a70e52c12d272ef97fcb61754fca0506af8bd8257f54a8586df ae16dabe5f2df7fc72a9dba93c80c622c2a8eca7672e7d78154597d9c98b1adf3a7d89566fdbce8d595464ea5ca5a888abd39772c5387d49cf529ca13c5e711d 02a273bf56e937abcd4eadd0acb6fb05afdb69149a41ad53e8d6827ab7df0dfc46b3ffc0750e15d86b5703afd66b146ae5202878b592a4df6816ea5ea5d2f6ea ed46cf6b3fc8b631b0f2543eb258407815af0bff000000ffff0300504b0304140006000800000021000dd1909fb60000001b010000270000007468656d652f74 68656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73848f4d0ac2301484f78277086f6fd3ba109126dd88d0add40384e4350d363f24 51eced0dae2c082e8761be9969bb979dc9136332de3168aa1a083ae995719ac16db8ec8e4052164e89d93b64b060828e6f37ed1567914b284d262452282e3198 720e274a939cd08a54f980ae38a38f56e422a3a641c8bbd048f7757da0f19b017cc524bd62107bd5001996509affb3fd381a89672f1f165dfe514173d9850528 a2c6cce0239baa4c04ca5bbabac4df000000ffff0300504b01022d0014000600080000002100e9de0fbfff0000001c0200001300000000000000000000000000 000000005b436f6e74656e745f54797065735d2e786d6c504b01022d0014000600080000002100a5d6a7e7c0000000360100000b000000000000000000000000 00300100005f72656c732f2e72656c73504b01022d00140006000800000021006b799616830000008a0000001c00000000000000000000000000190200007468 656d652f7468656d652f7468656d654d616e616765722e786d6c504b01022d0014000600080000002100e67505bed10600008b1a000016000000000000000000 00000000d60200007468656d652f7468656d652f7468656d65312e786d6c504b01022d00140006000800000021000dd1909fb60000001b010000270000000000 0000000000000000db0900007468656d652f7468656d652f5f72656c732f7468656d654d616e616765722e786d6c2e72656c73504b050600000000050005005d010000d60a00000000} {\*\colorschememapping 3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d225554462d3822207374616e64616c6f6e653d22796573223f3e0d0a3c613a636c724d 617020786d6c6e733a613d22687474703a2f2f736368656d61732e6f70656e786d6c666f726d6174732e6f72672f64726177696e676d6c2f323030362f6d6169 6e22206267313d226c743122207478313d22646b3122206267323d226c743222207478323d22646b322220616363656e74313d22616363656e74312220616363 656e74323d22616363656e74322220616363656e74333d22616363656e74332220616363656e74343d22616363656e74342220616363656e74353d22616363656e74352220616363656e74363d22616363656e74362220686c696e6b3d22686c696e6b2220666f6c486c696e6b3d22666f6c486c696e6b222f3e} {\*\latentstyles\lsdstimax371\lsdlockeddef0\lsdsemihiddendef0\lsdunhideuseddef0\lsdqformatdef0\lsdprioritydef99{\lsdlockedexcept \lsdqformat1 \lsdpriority0 \lsdlocked0 Normal;\lsdqformat1 \lsdpriority9 \lsdlocked0 heading 1; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 2;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 3;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 4; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 5;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 6;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 7; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 8;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority9 \lsdlocked0 heading 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 5; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 6;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 7;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 8;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index 9; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 1;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 2;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 3; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 4;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 5;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 6; \lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 7;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 8;\lsdsemihidden1 \lsdunhideused1 \lsdpriority39 \lsdlocked0 toc 9;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 header;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footer; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 index heading;\lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority35 \lsdlocked0 caption;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of figures; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 envelope return;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 footnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation reference; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 line number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 page number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote reference;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 endnote text; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 table of authorities;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 macro;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 toa heading;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Bullet 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 4;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Number 5;\lsdqformat1 \lsdpriority10 \lsdlocked0 Title;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Closing; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Signature;\lsdsemihidden1 \lsdunhideused1 \lsdpriority1 \lsdlocked0 Default Paragraph Font;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 4; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 List Continue 5;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Message Header;\lsdqformat1 \lsdpriority11 \lsdlocked0 Subtitle;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Salutation; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Date;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text First Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Note Heading; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Body Text Indent 3; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Block Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Hyperlink;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 FollowedHyperlink;\lsdqformat1 \lsdpriority22 \lsdlocked0 Strong; \lsdqformat1 \lsdpriority20 \lsdlocked0 Emphasis;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Document Map;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Plain Text;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 E-mail Signature; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Top of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Bottom of Form;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Normal (Web);\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Acronym; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Address;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Cite;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Code;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Definition; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Keyboard;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Preformatted;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Sample;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Typewriter; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 HTML Variable;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 annotation subject;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 No List;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 1; \lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 2;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Outline List 3;\lsdsemihidden1 \lsdunhideused1 \lsdlocked0 Balloon Text;\lsdpriority39 \lsdlocked0 Table Grid; \lsdsemihidden1 \lsdlocked0 Placeholder Text;\lsdqformat1 \lsdpriority1 \lsdlocked0 No Spacing;\lsdpriority60 \lsdlocked0 Light Shading;\lsdpriority61 \lsdlocked0 Light List;\lsdpriority62 \lsdlocked0 Light Grid; \lsdpriority63 \lsdlocked0 Medium Shading 1;\lsdpriority64 \lsdlocked0 Medium Shading 2;\lsdpriority65 \lsdlocked0 Medium List 1;\lsdpriority66 \lsdlocked0 Medium List 2;\lsdpriority67 \lsdlocked0 Medium Grid 1;\lsdpriority68 \lsdlocked0 Medium Grid 2; \lsdpriority69 \lsdlocked0 Medium Grid 3;\lsdpriority70 \lsdlocked0 Dark List;\lsdpriority71 \lsdlocked0 Colorful Shading;\lsdpriority72 \lsdlocked0 Colorful List;\lsdpriority73 \lsdlocked0 Colorful Grid;\lsdpriority60 \lsdlocked0 Light Shading Accent 1; \lsdpriority61 \lsdlocked0 Light List Accent 1;\lsdpriority62 \lsdlocked0 Light Grid Accent 1;\lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 1;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 1;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 1; \lsdsemihidden1 \lsdlocked0 Revision;\lsdqformat1 \lsdpriority34 \lsdlocked0 List Paragraph;\lsdqformat1 \lsdpriority29 \lsdlocked0 Quote;\lsdqformat1 \lsdpriority30 \lsdlocked0 Intense Quote;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 1; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 1;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 1;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 1;\lsdpriority70 \lsdlocked0 Dark List Accent 1;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 1; \lsdpriority72 \lsdlocked0 Colorful List Accent 1;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 1;\lsdpriority60 \lsdlocked0 Light Shading Accent 2;\lsdpriority61 \lsdlocked0 Light List Accent 2;\lsdpriority62 \lsdlocked0 Light Grid Accent 2; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 2;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 2;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 2;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 2; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 2;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 2;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 2;\lsdpriority70 \lsdlocked0 Dark List Accent 2;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 2; \lsdpriority72 \lsdlocked0 Colorful List Accent 2;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 2;\lsdpriority60 \lsdlocked0 Light Shading Accent 3;\lsdpriority61 \lsdlocked0 Light List Accent 3;\lsdpriority62 \lsdlocked0 Light Grid Accent 3; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 3;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 3;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 3;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 3; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 3;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 3;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 3;\lsdpriority70 \lsdlocked0 Dark List Accent 3;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 3; \lsdpriority72 \lsdlocked0 Colorful List Accent 3;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 3;\lsdpriority60 \lsdlocked0 Light Shading Accent 4;\lsdpriority61 \lsdlocked0 Light List Accent 4;\lsdpriority62 \lsdlocked0 Light Grid Accent 4; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 4;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 4;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 4;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 4; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 4;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 4;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 4;\lsdpriority70 \lsdlocked0 Dark List Accent 4;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 4; \lsdpriority72 \lsdlocked0 Colorful List Accent 4;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 4;\lsdpriority60 \lsdlocked0 Light Shading Accent 5;\lsdpriority61 \lsdlocked0 Light List Accent 5;\lsdpriority62 \lsdlocked0 Light Grid Accent 5; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 5;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 5;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 5;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 5; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 5;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 5;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 5;\lsdpriority70 \lsdlocked0 Dark List Accent 5;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 5; \lsdpriority72 \lsdlocked0 Colorful List Accent 5;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 5;\lsdpriority60 \lsdlocked0 Light Shading Accent 6;\lsdpriority61 \lsdlocked0 Light List Accent 6;\lsdpriority62 \lsdlocked0 Light Grid Accent 6; \lsdpriority63 \lsdlocked0 Medium Shading 1 Accent 6;\lsdpriority64 \lsdlocked0 Medium Shading 2 Accent 6;\lsdpriority65 \lsdlocked0 Medium List 1 Accent 6;\lsdpriority66 \lsdlocked0 Medium List 2 Accent 6; \lsdpriority67 \lsdlocked0 Medium Grid 1 Accent 6;\lsdpriority68 \lsdlocked0 Medium Grid 2 Accent 6;\lsdpriority69 \lsdlocked0 Medium Grid 3 Accent 6;\lsdpriority70 \lsdlocked0 Dark List Accent 6;\lsdpriority71 \lsdlocked0 Colorful Shading Accent 6; \lsdpriority72 \lsdlocked0 Colorful List Accent 6;\lsdpriority73 \lsdlocked0 Colorful Grid Accent 6;\lsdqformat1 \lsdpriority19 \lsdlocked0 Subtle Emphasis;\lsdqformat1 \lsdpriority21 \lsdlocked0 Intense Emphasis; \lsdqformat1 \lsdpriority31 \lsdlocked0 Subtle Reference;\lsdqformat1 \lsdpriority32 \lsdlocked0 Intense Reference;\lsdqformat1 \lsdpriority33 \lsdlocked0 Book Title;\lsdsemihidden1 \lsdunhideused1 \lsdpriority37 \lsdlocked0 Bibliography; \lsdsemihidden1 \lsdunhideused1 \lsdqformat1 \lsdpriority39 \lsdlocked0 TOC Heading;\lsdpriority41 \lsdlocked0 Plain Table 1;\lsdpriority42 \lsdlocked0 Plain Table 2;\lsdpriority43 \lsdlocked0 Plain Table 3;\lsdpriority44 \lsdlocked0 Plain Table 4; \lsdpriority45 \lsdlocked0 Plain Table 5;\lsdpriority40 \lsdlocked0 Grid Table Light;\lsdpriority46 \lsdlocked0 Grid Table 1 Light;\lsdpriority47 \lsdlocked0 Grid Table 2;\lsdpriority48 \lsdlocked0 Grid Table 3;\lsdpriority49 \lsdlocked0 Grid Table 4; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 1; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 1;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 1;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 1; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 1;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 2;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 2; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 2;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 2; \lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 3;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 3;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 3;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 3; \lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 3;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 4; \lsdpriority47 \lsdlocked0 Grid Table 2 Accent 4;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 4;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 4;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 4; \lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 4;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 5; \lsdpriority48 \lsdlocked0 Grid Table 3 Accent 5;\lsdpriority49 \lsdlocked0 Grid Table 4 Accent 5;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 5; \lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 5;\lsdpriority46 \lsdlocked0 Grid Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 Grid Table 2 Accent 6;\lsdpriority48 \lsdlocked0 Grid Table 3 Accent 6; \lsdpriority49 \lsdlocked0 Grid Table 4 Accent 6;\lsdpriority50 \lsdlocked0 Grid Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 Grid Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 Grid Table 7 Colorful Accent 6; \lsdpriority46 \lsdlocked0 List Table 1 Light;\lsdpriority47 \lsdlocked0 List Table 2;\lsdpriority48 \lsdlocked0 List Table 3;\lsdpriority49 \lsdlocked0 List Table 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark; \lsdpriority51 \lsdlocked0 List Table 6 Colorful;\lsdpriority52 \lsdlocked0 List Table 7 Colorful;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 1;\lsdpriority47 \lsdlocked0 List Table 2 Accent 1;\lsdpriority48 \lsdlocked0 List Table 3 Accent 1; \lsdpriority49 \lsdlocked0 List Table 4 Accent 1;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 1;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 1;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 1; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 2;\lsdpriority47 \lsdlocked0 List Table 2 Accent 2;\lsdpriority48 \lsdlocked0 List Table 3 Accent 2;\lsdpriority49 \lsdlocked0 List Table 4 Accent 2; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 2;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 2;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 2;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 3; \lsdpriority47 \lsdlocked0 List Table 2 Accent 3;\lsdpriority48 \lsdlocked0 List Table 3 Accent 3;\lsdpriority49 \lsdlocked0 List Table 4 Accent 3;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 3; \lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 3;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 3;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 4;\lsdpriority47 \lsdlocked0 List Table 2 Accent 4; \lsdpriority48 \lsdlocked0 List Table 3 Accent 4;\lsdpriority49 \lsdlocked0 List Table 4 Accent 4;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 4;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 4; \lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 4;\lsdpriority46 \lsdlocked0 List Table 1 Light Accent 5;\lsdpriority47 \lsdlocked0 List Table 2 Accent 5;\lsdpriority48 \lsdlocked0 List Table 3 Accent 5; \lsdpriority49 \lsdlocked0 List Table 4 Accent 5;\lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 5;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 5;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 5; \lsdpriority46 \lsdlocked0 List Table 1 Light Accent 6;\lsdpriority47 \lsdlocked0 List Table 2 Accent 6;\lsdpriority48 \lsdlocked0 List Table 3 Accent 6;\lsdpriority49 \lsdlocked0 List Table 4 Accent 6; \lsdpriority50 \lsdlocked0 List Table 5 Dark Accent 6;\lsdpriority51 \lsdlocked0 List Table 6 Colorful Accent 6;\lsdpriority52 \lsdlocked0 List Table 7 Colorful Accent 6;}}{\*\datastore 010500000200000018000000 4d73786d6c322e534158584d4c5265616465722e362e3000000000000000000000060000 d0cf11e0a1b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001000000010000000000000000100000feffffff00000000feffffff0000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff fffffffffffffffffdfffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ffffffffffffffffffffffffffffffff52006f006f007400200045006e00740072007900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000016000500ffffffffffffffffffffffff0c6ad98892f1d411a65f0040963251e500000000000000000000000000ca 63ca1197d001feffffff00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff0000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000105000000000000}}openvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/images0000644000000000000000000000013212664357344023023 xustar0030 mtime=1456594660.253291342 30 atime=1456594661.701352216 30 ctime=1456594660.253291342 openvswitch-2.5.0/windows/ovs-windows-installer/images/0000775000175000017500000000000012664357344024570 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/windows/ovs-windows-installer/images/PaxHeaders.69223/bannrbmp.bmp0000644000000000000000000000013212631676263025375 xustar0030 mtime=1449622707.614461958 30 atime=1456592667.495097949 30 ctime=1456594660.253291342 openvswitch-2.5.0/windows/ovs-windows-installer/images/bannrbmp.bmp0000664000175000017500000040745612631676263027105 0ustar00jpettitjpettit00000000000000BM.6(hIø  ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææáááÊÊÊææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒšššccc=== ---OOO}}}···ãããææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææŒŒŒVVVææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå³³³jjj444BBByyyÂÂÂææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÛÛÛˆˆˆ777aaa···æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââ ÆÆÆæææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå•••'''222   ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØppp;;;«««æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææWWWææææææææææææææææææææææææææææææææææææææææææææææææææææææÉÉÉ777===ÍÍÍææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææåååLLLÍÍÍææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææäää$$$ËËËææææææææææææææææææææææææææææææææææææææææææææææææ®®®°°°ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÖÖÖFFFœœœæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ———]]]æææææææææææææææææææææææææææææææææææææææææææææ¯¯¯¬¬¬ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÁÁÁmmmåååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå%%%ËËËæææææææææææææææææææææææææææææææææææææææÊÊÊÆÆÆææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ´´´WWWãããæææææææææææææææææææææææææææææææææææææææææææææææææææææææææžžžbbbææææææææææææææææææææææææææææææææææææååå888333åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¿¿¿ 222999)))aaaææææææææææææææææææææææææææææææææææææææææææææææææææææææååå+++ÏÏÏæææææææææææææææææææææææææææææææææ”””444&&&æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÔÔÔjjj®®®àààæææææææææææææææËËË???~~~æææææææææææææææææææææææææææææææææææææææææææææææææææ¡¡¡dddææææææææææææææææææææææææææææææäää$$$kkkËËËæææææææææÖÖÖvvv###åååæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææåååAAAâââæææææææææææææææææææææææææææææææææÆÆÆRRR°°°ææææææææææææææææææææææææææææææææææææææææææææææææ222ÔÔÔæææææææææææææææææææææææææææ¬¬¬¶¶¶æææææææææææææææææææææ¸¸¸±±±æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææˆˆˆ]]]ÛÛÛæææææææææææææææææææææææææææææææææææææææææææææ«««ßßßææææææææææææææææææææææææææææææææææææææææææ¥¥¥kkkæææææææææææææææææææææææææææ```­­­æææææææææææææææææææææææææææ¡¡¡kkkææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒ111sssææææææææææææææææææææææææææææææææææææææææææ777 ÔÔÔææææææææææææææææææææææææ%%%LLLæææææææææææææææææææææææææææææææææ999777ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææiiišššææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÜÜÜ222 ÔÔÔææææææææææææææææææææææææææææææææææææ¬¬¬mmmæææææææææææææææææææææßßß™™™æææææææææææææææææææææææææææææææææŒŒŒæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÔÔÔ }}}ææææææææææææËØÃæææææææææææææææææææææææææææææææææææææææææææææææææææÓÓÓoooææææææææææææææææææææææææææææææææææææ:::ØØØææææææææææææææææææ¿¿¿¿¿¿æææææææææææææææææææææææææææææææææ¶¶¶æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ@@@åååæææææææææ¤ÅPš"ææææææææææææææææææææææææææææææææææææææææææææææææææææææ®®®âââææææææææææææææææææææææææææææææ³³³sssææææææææææææææææææÚÚÚ˜˜˜hhh777 ÉÉÉæææææææææææææææææææææææææææææææææÄÄÄæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ---ÆÆÆææææææäåㇶj6K˜æææææææææææææææææææææææææææææææææææææææææææææææææææææææææWWW£££ææææææææææææææææææææææææææææææ@@@ØØØæææææææææææææææææææææææææææããã½½½]]],,,ËËËæææææææææææææææææææææææææææææææææ©©©ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÌÌÌ]]]ææææææÜáÙj¨E66K˜æææææææææææææææææææææææææææææææææææææææææææææææææææææææææËËËYYYæææææææææææææææææææææææææææ¶¶¶zzzææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææYYYææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÀÀÀæææÏÚÈSœ&6668ŽK˜K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜¶Î§ææææææææææææææææææææææææJJJ æææææææææææææææææææææææææææGGG XXXÛÛÛææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¯¯¯EEEææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ\\\***æææºÐ¬C”6666666666666666¯ÊžææææææææææææææææææææææææšššÒÒÒæææææææææææææææææææææººº‰‰‰ÃÃÃzzzæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ§§§ €€€ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ999hhhÑÛÊ= 66666666666666666¯ÊžææææææææææææææææææææææææÖÖÖ®®®æææææææææææææææææææææMMMÞÞÞæææJJJÞÞÞææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÏÏÏ[[[ÍÍÍææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ–––æææ»Ð­D”6666666666666666¯ÊžÏÚÈÕÝÏæææææææææææææææææææææ ŽŽŽææææææææææææææææææÀÀÀwwwææææææµµµææææææææææææææææææææææææææææææææææææææææææææææææææææææÃÃÃ```PPPæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ ¶¶¶ææææææÐÛÉV*666@’޹s޹s޹s޹s޹s޹s޹s޹s޹s޹s޹sÊØÂºÐ¬I–ÃÔ¸ææææææææææææææææææAAA€€€ææææææææææææææææææNNN ×××æææææææææ:::ÞÞÞææææææææææææææææææææææææææææææææææææææææææää䟟Ÿ>>> ËËËæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÅÅÅæææææææææÞâÜq«M66K˜ææææææææææææææææææææææææææææææææææææºÐ¬6<ªÈ˜æææææææææææææææNNNsssæææææææææææææææÆÆÆfffææææææææææææ¤¤¤………ææææææææææææææææææææææææææææææææææææÞÞÞ………”””ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÆÆÆææææææææææææåæå‘»w7K˜ææææææææææææææææææææææææææææææææææææºÐ¬666޹såæåæææææææææNNNsssæææææææææææææææVVVËËËææææææææææææååå)))áááæææææææææææææææææææææææææææãã㊊Šzzzæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ ···ææææææææææææææææææ°Ë U)æææm©G666666666666666oªKßãÝææææææBBB€€€ææææææææææææÈÈÈSSSææææææææææææææææææ•••ˆˆˆææææææææææææææææææææææææÂÂÂ222‡‡‡ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ›››æææææææææææææææææææææÔÝÏæææm©G6666666666666666Xž,ÓÜÍæææ###ææææææææææææ]]]½½½ææææææææææææææææææââââââææææææææææææææææææššš )))···æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ<<<pppæææææææææææææææææææææææææææm©G66666666666666666u­RÝÝݲ²²æææææææææËËËBBBææææææææææææææææææææææææ………æææææææææææææææ”””‚‚‚áááææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææaaa888æææææææææææææææææææææææææææm©G6666666666666666ƒ´eäåã§§§×××æææææææææaaa¬¬¬ææææææææææææææææææææææææÞÞÞ âââæææææææææ¶¶¶ ÛÛÛææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ™™™ÏÏÏææææææææææææææææææææææææ¸Ïª¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Äˆ·k666:¤Åææææææ\\\'''æææææææææÏÏÏ000æææææææææææææææææææææææææææææætttææææææâââ%%%NNN¨¨¨åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÓÓÓuuuæææææææææææææææææææææææææææææææææææææææææææææææææææææææææºÐ¬66G•ÀÓ´ææææææØØØ eeeææææææææædddšššææææææææææææææææææææææææææææææÕÕÕ %%%äääæææ•••ÕÕÕææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ<<<ØØØææææææææææææææææææææææææææææææææææææææææææææææææææææææºÐ¬6[ 1ÕÝÏæææææææææuuu²²²ææææææÛÛÛ'''333äääæææææææææææææææææææææææææææææææææooo§§§æææ@@@ŠŠŠâââææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææcccææææææææææææææææææææææææææææææææææææææææææææææææææææææºÐ¬w®UáäàæææææææææÊÊÊ åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææãããÄÄÄææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææààদ¦æææææææææææææææææææææææææææææææææææææææææææææææææææàãÞææææææææææææááá444‡‡‡æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÈÈÈ   ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ ½½½ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææåååVVVÞÞÞæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ»»»ãããææææææææææææææææææææææææææææææÛÛÛæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææààà!!!³³³ææææææææææææææææææææææææææææææææææææææææææææææææææææææáááUUU‘‘‘ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ½½½ÜÜÜæææææææææææææææææææææææææææááá%%%NNNÎÎÎææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ©©©ƒƒƒäääæææææææææææææææææææææææææææææææææææææææææææææÆÆÆ333999åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒ‹‹‹æææææææææææææææææææææææææææwww |||áááæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææhhh111¨¨¨ææææææææææææææææææææææææææææææææææææÔÔÔmmmËËËææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææºººæææææææææææææææææææææ¡¡¡###¨¨¨ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææááá555'''yyy···âââæææææææææææææææÒÒÒšššOOO ¥¥¥æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææUUUtttÓÓÓæææææææææÕÕÕrrrLLLÙÙÙæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØ(((!!!222999)))ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¬¬¬###999''')))äääææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÏÏÏ)))‡‡‡ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ888°°°ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØ:::šššæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÁÁÁdddææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææââânnn$$$½½½æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ™™™<<<áááææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ®®®)))kkkÝÝÝæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ˜˜˜<<<ØØØææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææââ≉‰RRRÃÃÃææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¹¹¹'''dddáááæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââšššFFFqqqÉÉÉæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææââ∈ˆ @@@±±±ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØ¡¡¡iiiCCC 222TTT………¾¾¾åååæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå±±±mmm;;;AAAvvvÂÂÂæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææopenvswitch-2.5.0/windows/ovs-windows-installer/images/PaxHeaders.69223/dlgbmp.bmp0000644000000000000000000000013212631676263025043 xustar0030 mtime=1449622707.614461958 30 atime=1456592667.499098113 30 ctime=1456594660.253291342 openvswitch-2.5.0/windows/ovs-windows-installer/images/dlgbmp.bmp0000664000175000017500000160343012631676263026542 0ustar00jpettitjpettit00000000000000BM6(ì8â  ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææGGG***ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææGGG***ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææGGG***ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææGGG***æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÄÄÄggg000***[[[³³³ææææææææææææGGG***¸¸¸AAA<<<¦¦¦æææææææææºººIII***nnnÚÚÚæææ°°°VVVËËËææææææ¹¹¹VVVÂÂÂææææææææææææææææææææææææ†††áááææææææææææææ¶¶¶GGG)))nnnÛÛÛææææææææææææœœœÍÍÍæææææææææææææææææææææŒŒŒ___ææææææ•••VVVæææææææææ¯¯¯EEE(((kkkæææžžžVVVæææææææææ§§§VVVÔÔÔæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææåååsss777TTT>>>UUUßßßææææææGGGZZZlll æææ¹¹¹jjjXXX'''ØØØ»»»ææææææžžž¬¬¬æææææææææææææææææææææÔÔÔ ˆˆˆæææææææææ«««HHH<<<,,,ÞÞÞææææææäää%%%jjjææææææ±±±ÆÆÆæææææææææVVVæææææædddææææææ```JJJæææsssæææææææææÉÉÉææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææænnn===ÈÈÈæææææææææÕÕÕWWWHHHåååæææGGG¡¡¡ææææææØØØ!!! æææ@@@ÑÑÑææææææ¨¨¨666ÄÄÄ»»»ææææææžžž¬¬¬ææææææææææææææææææææænnnâââææææææ&&&ËËËææææææ………€€€ææææææ———ÜÜÜæææKKKVVVæææææææææVVVæææææædddæææ××× 999ßßßææææææµµµæææsssæææææææææÉÉÉææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ»»»;;;âââææææææææææææææææææ^^^•••æææGGGææææææææææææuuuÍÍÍPPPØØØØØØØØØØØØØØØààà»»»ææææææžžž¬¬¬ææææææææææææææææææØØØ(((æææÚÚÚ666qqqæææææææææããã EEEæææäää%%%)))………ÉÉÉ333ÆÆÆææææææVVVæææææædddæææœœœ¨¨¨æææææææææææææææsssæææææææææÉÉÉææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææYYYÅÅÅæææææææææææææææææææææÛÛÛ333æææGGG+++ææææææææææææ†††¿¿¿ŠŠŠ»»»ææææææžžž¬¬¬ææææææææææææææææææsss¾¾¾/// âââææææææææææææææææææááá FFFæææžžž›››[[[!!!fffÒÒÒ VVVææææææVVVæææææædddæææ”””···æææææææææææææææsssÛÛÛææææææÉÉÉææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ""",,,æææææææææææææææææææææææææææTTTàààGGGÓÓÓæææææææææPPPÝÝÝ )))ÉÉÉÉÉÉÉÉɨ¨¨žžžææææææ˜˜˜³³³æææææææææææææææÛÛÛCCCæææšššæææææææææææææææÝÝÝVVV„„„ååå+++!!!äää½½½xxxæææcccÆÆÆæææVVVæææææædddæææ¾¾¾oooæææææææææáááæææsssÀÀÀæææææævvvÕÕÕææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææHHHæææææææææææææææææææææææææææqqqÍÍÍGGG888¾¾¾ÐÐÐwww[[[æææwwwsssÖÖÖ¼¼¼'''ááá444ÅÅÅÍÍÍ>>>ÒÒÒæææææææææææææææzzz®®®æææäää %%%äääææææææÔÔÔsssFFFááážžž‰‰‰ææææææ:::ÓÓÓæææÊÊÊWWWæææVVVæææËËËEEEžžžÆÆÆIIIxxxÄÄÄ«««AAAæææsssKKKÍÍÍÆÆÆ&&&æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ666æææææææææææææææææææææææææææ]]]ÞÞÞGGG***eeeDDDÜÜÜæææáááSSS´´´æææMMMgggæææææææææææææææÛÛÛ111æææææææææŠŠŠ———æææ ///———åååååå+++ÞÞÞææææææUUUæææææææææPPPËËËVVVæææÚÚÚOOOæææsssWWW†††æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææSSSÔÔÔæææææææææææææææææææææâââ,,,æææÒÒÒÏÏÏæææÆÆÆ   ½½½æææææææææææææææÆÆÆ¡¡¡¬¬¬ßßßææææææÛÛÛÉÉÉáááÆÆÆŸŸŸ¼¼¼ææææææææææææææææææàààÉÉÉ×××æææææææææâââÉÉÉÔÔÔ­­­,,,¶¶¶æææææææææäääÉÉÉÒÒÒæææææææææãããÆÆÆæææææææææÛÛÛÉÉÉÛÛÛÔÔÔËËËæææÛÛÛWWWÉÉÉÙÙÙææææææËËË¢¢¢ªªªÜÜÜæææsssæææ¼¼¼ŸŸŸÆÆÆææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ°°°[[[æææææææææææææææææææææ‹‹‹æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææiiiÄÄÄæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææædddæææææææææææææææææææææææææææsssæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ___iiißßßæææææææææäää………;;;âââææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææævvv¬¬¬ææææææËËËåååæææææææææææææææææææææææææææææææææææææææ¶¶¶———æææææædddæææææææææææææææææææææææææææsssæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææáááZZZ]]]wwweee""">>>ØØØææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÊÊÊ aaaooo ÇÇÇæææææææææææææææææææææææææææææææææææææææ$$$ÃÃÃæææÞÞÞØØØæææææææææææææææææææææææææææsssæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææªªªFFF :::–––åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ½½½<<<333µµµææææææææææææææææææææææææææææææææææææææææææ•••kkkâââææææææææææææææææææææææææææææææææææææsssææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÞÞÞææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââáááæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææsssææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ———GGGææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææáááÊÊÊææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒšššccc=== ---OOO}}}···ãããææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææŒŒŒVVVææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå³³³jjj444BBByyyÂÂÂææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÛÛÛˆˆˆ777aaa···æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââ ÆÆÆæææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå•••'''222   ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØppp;;;«««æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææWWWææææææææææææææææææææææææææææææææææææææææææææææææææææææÉÉÉ777===ÍÍÍææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææåååLLLÍÍÍææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææäää$$$ËËËææææææææææææææææææææææææææææææææææææææææææææææææ®®®°°°ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÖÖÖFFFœœœæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ———]]]æææææææææææææææææææææææææææææææææææææææææææææ¯¯¯¬¬¬ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÁÁÁmmmåååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå%%%ËËËæææææææææææææææææææææææææææææææææææææææÊÊÊÆÆÆææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ´´´WWWãããæææææææææææææææææææææææææææææææææææææææææææææææææææææææææžžžbbbææææææææææææææææææææææææææææææææææææååå888333åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¿¿¿ 222999)))aaaææææææææææææææææææææææææææææææææææææææææææææææææææææææååå+++ÏÏÏæææææææææææææææææææææææææææææææææ”””444&&&æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÔÔÔjjj®®®àààæææææææææææææææËËË???~~~æææææææææææææææææææææææææææææææææææææææææææææææææææ¡¡¡dddææææææææææææææææææææææææææææææäää$$$kkkËËËæææææææææÖÖÖvvv###åååæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææåååAAAâââæææææææææææææææææææææææææææææææææÆÆÆRRR°°°ææææææææææææææææææææææææææææææææææææææææææææææææ222ÔÔÔæææææææææææææææææææææææææææ¬¬¬¶¶¶æææææææææææææææææææææ¸¸¸±±±æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææˆˆˆ]]]ÛÛÛæææææææææææææææææææææææææææææææææææææææææææææ«««ßßßææææææææææææææææææææææææææææææææææææææææææ¥¥¥kkkæææææææææææææææææææææææææææ```­­­æææææææææææææææææææææææææææ¡¡¡kkkææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒ111sssææææææææææææææææææææææææææææææææææææææææææ777 ÔÔÔææææææææææææææææææææææææ%%%LLLæææææææææææææææææææææææææææææææææ999777ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææiiišššææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÜÜÜ222 ÔÔÔææææææææææææææææææææææææææææææææææææ¬¬¬mmmæææææææææææææææææææææßßß™™™æææææææææææææææææææææææææææææææææŒŒŒæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÔÔÔ }}}ææææææææææææËØÃæææææææææææææææææææææææææææææææææææææææææææææææææææÓÓÓoooææææææææææææææææææææææææææææææææææææ:::ØØØææææææææææææææææææ¿¿¿¿¿¿æææææææææææææææææææææææææææææææææ¶¶¶æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ@@@åååæææææææææ¤ÅPš"ææææææææææææææææææææææææææææææææææææææææææææææææææææææ®®®âââææææææææææææææææææææææææææææææ³³³sssææææææææææææææææææÚÚÚ˜˜˜hhh777 ÉÉÉæææææææææææææææææææææææææææææææææÄÄÄæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ---ÆÆÆææææææäåㇶj6K˜æææææææææææææææææææææææææææææææææææææææææææææææææææææææææWWW£££ææææææææææææææææææææææææææææææ@@@ØØØæææææææææææææææææææææææææææããã½½½]]],,,ËËËæææææææææææææææææææææææææææææææææ©©©ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÌÌÌ]]]ææææææÜáÙj¨E66K˜æææææææææææææææææææææææææææææææææææææææææææææææææææææææææËËËYYYæææææææææææææææææææææææææææ¶¶¶zzzææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææYYYææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÀÀÀæææÏÚÈSœ&6668ŽK˜K˜K˜K˜K˜K˜K˜K˜K˜K˜K˜¶Î§ææææææææææææææææææææææææJJJ æææææææææææææææææææææææææææGGG XXXÛÛÛææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¯¯¯EEEææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ\\\***æææºÐ¬C”6666666666666666¯ÊžææææææææææææææææææææææææšššÒÒÒæææææææææææææææææææææººº‰‰‰ÃÃÃzzzæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ§§§ €€€ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ999hhhÑÛÊ= 66666666666666666¯ÊžææææææææææææææææææææææææÖÖÖ®®®æææææææææææææææææææææMMMÞÞÞæææJJJÞÞÞææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÏÏÏ[[[ÍÍÍææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ–––æææ»Ð­D”6666666666666666¯ÊžÏÚÈÕÝÏæææææææææææææææææææææ ŽŽŽææææææææææææææææææÀÀÀwwwææææææµµµææææææææææææææææææææææææææææææææææææææææææææææææææææææÃÃÃ```PPPæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ ¶¶¶ææææææÐÛÉV*666@’޹s޹s޹s޹s޹s޹s޹s޹s޹s޹s޹sÊØÂºÐ¬I–ÃÔ¸ææææææææææææææææææAAA€€€ææææææææææææææææææNNN ×××æææææææææ:::ÞÞÞææææææææææææææææææææææææææææææææææææææææææää䟟Ÿ>>> ËËËæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÅÅÅæææææææææÞâÜq«M66K˜ææææææææææææææææææææææææææææææææææææºÐ¬6<ªÈ˜æææææææææææææææNNNsssæææææææææææææææÆÆÆfffææææææææææææ¤¤¤………ææææææææææææææææææææææææææææææææææææÞÞÞ………”””ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÆÆÆææææææææææææåæå‘»w7K˜ææææææææææææææææææææææææææææææææææææºÐ¬666޹såæåæææææææææNNNsssæææææææææææææææVVVËËËææææææææææææååå)))áááæææææææææææææææææææææææææææãã㊊Šzzzæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ ···ææææææææææææææææææ°Ë U)æææm©G666666666666666oªKßãÝææææææBBB€€€ææææææææææææÈÈÈSSSææææææææææææææææææ•••ˆˆˆææææææææææææææææææææææææÂÂÂ222‡‡‡ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ›››æææææææææææææææææææææÔÝÏæææm©G6666666666666666Xž,ÓÜÍæææ###ææææææææææææ]]]½½½ææææææææææææææææææââââââææææææææææææææææææššš )))···æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ<<<pppæææææææææææææææææææææææææææm©G66666666666666666u­RÝÝݲ²²æææææææææËËËBBBææææææææææææææææææææææææ………æææææææææææææææ”””‚‚‚áááææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææaaa888æææææææææææææææææææææææææææm©G6666666666666666ƒ´eäåã§§§×××æææææææææaaa¬¬¬ææææææææææææææææææææææææÞÞÞ âââæææææææææ¶¶¶ ÛÛÛææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ™™™ÏÏÏææææææææææææææææææææææææ¸Ïª¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Ä¤Äˆ·k666:¤Åææææææ\\\'''æææææææææÏÏÏ000æææææææææææææææææææææææææææææætttææææææâââ%%%NNN¨¨¨åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÓÓÓuuuæææææææææææææææææææææææææææææææææææææææææææææææææææææææææºÐ¬66G•ÀÓ´ææææææØØØ eeeææææææææædddšššææææææææææææææææææææææææææææææÕÕÕ %%%äääæææ•••ÕÕÕææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ<<<ØØØææææææææææææææææææææææææææææææææææææææææææææææææææææææºÐ¬6[ 1ÕÝÏæææææææææuuu²²²ææææææÛÛÛ'''333äääæææææææææææææææææææææææææææææææææooo§§§æææ@@@ŠŠŠâââææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææcccææææææææææææææææææææææææææææææææææææææææææææææææææææææºÐ¬w®UáäàæææææææææÊÊÊ åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææãããÄÄÄææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææààদ¦æææææææææææææææææææææææææææææææææææææææææææææææææææàãÞææææææææææææááá444‡‡‡æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÈÈÈ   ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ ½½½ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææåååVVVÞÞÞæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ»»»ãããææææææææææææææææææææææææææææææÛÛÛæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææààà!!!³³³ææææææææææææææææææææææææææææææææææææææææææææææææææææææáááUUU‘‘‘ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ½½½ÜÜÜæææææææææææææææææææææææææææááá%%%NNNÎÎÎææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ©©©ƒƒƒäääæææææææææææææææææææææææææææææææææææææææææææææÆÆÆ333999åååææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÒÒÒ‹‹‹æææææææææææææææææææææææææææwww |||áááæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææhhh111¨¨¨ææææææææææææææææææææææææææææææææææææÔÔÔmmmËËËææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææºººæææææææææææææææææææææ¡¡¡###¨¨¨ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææááá555'''yyy···âââæææææææææææææææÒÒÒšššOOO ¥¥¥æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææUUUtttÓÓÓæææææææææÕÕÕrrrLLLÙÙÙæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØ(((!!!222999)))ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¬¬¬###999''')))äääææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÏÏÏ)))‡‡‡ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ888°°°ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØ:::šššæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææÁÁÁdddææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææââânnn$$$½½½æææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ™™™<<<áááææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ®®®)))kkkÝÝÝæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ˜˜˜<<<ØØØææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææââ≉‰RRRÃÃÃææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææ¹¹¹'''dddáááæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææâââšššFFFqqqÉÉÉæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææââ∈ˆ @@@±±±ææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææØØØ¡¡¡iiiCCC 222TTT………¾¾¾åååæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææååå±±±mmm;;;AAAvvvÂÂÂæææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææææopenvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/Dialogs0000644000000000000000000000013212664357344023140 xustar0030 mtime=1456594660.249291174 30 atime=1456594661.701352216 30 ctime=1456594660.249291174 openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/0000775000175000017500000000000012664357344024705 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/PaxHeaders.69223/MyTroubleshootDialog.wxs0000644000000000000000000000013212631676263030075 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.495097949 30 ctime=1456594660.249291174 openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/MyTroubleshootDialog.wxs0000664000175000017500000000441012631676263031564 0ustar00jpettitjpettit00000000000000 1 !(wix.WixUICostingPopupOptOut) OR CostingComplete = 1 Installed AND NOT RESUME AND NOT Preselected AND NOT PATCH openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/PaxHeaders.69223/MyEndDialog.wxs0000644000000000000000000000013212631676263026112 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.495097949 30 ctime=1456594660.245291006 openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/MyEndDialog.wxs0000664000175000017500000000466212631676263027612 0ustar00jpettitjpettit00000000000000 openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/PaxHeaders.69223/BeginningDialog.wxs0000644000000000000000000000013212631676263026776 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.495097949 30 ctime=1456594660.245291006 openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/BeginningDialog.wxs0000664000175000017500000000515712631676263030476 0ustar00jpettitjpettit00000000000000 NOT Installed OR NOT PATCH Installed AND PATCH Installed AND PATCH NOT Installed OR NOT PATCH Installed AND PATCH 1 NOT Installed OR PATCH openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/PaxHeaders.69223/UserFinishDialog.wxs0000644000000000000000000000013212631676263027155 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.495097949 30 ctime=1456594660.249291174 openvswitch-2.5.0/windows/ovs-windows-installer/Dialogs/UserFinishDialog.wxs0000664000175000017500000000423712631676263030653 0ustar00jpettitjpettit00000000000000 1 openvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/UI.wxs0000644000000000000000000000013212631676263022711 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.495097949 30 ctime=1456594660.253291342 openvswitch-2.5.0/windows/ovs-windows-installer/UI.wxs0000664000175000017500000001002712631676263024401 0ustar00jpettitjpettit00000000000000 1 NOT Installed Installed AND PATCH 1 LicenseAccepted = "1" NOT Installed OR WixUI_InstallMode = "Change" Installed AND NOT PATCH Installed AND PATCH 1 1 1 1 1 1 1 1 Installed NOT Installed 1 1 openvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/CustomActions.wxs0000644000000000000000000000013212631676263025167 xustar0030 mtime=1449622707.610461818 30 atime=1456592667.491097785 30 ctime=1456594660.245291006 openvswitch-2.5.0/windows/ovs-windows-installer/CustomActions.wxs0000664000175000017500000000715312631676263026665 0ustar00jpettitjpettit00000000000000 openvswitch-2.5.0/windows/ovs-windows-installer/PaxHeaders.69223/ovs-windows-installer.wixproj0000644000000000000000000000013112631676263027546 xustar0030 mtime=1449622707.614461958 30 atime=1456592667.495097949 29 ctime=1456594660.25729151 openvswitch-2.5.0/windows/ovs-windows-installer/ovs-windows-installer.wixproj0000664000175000017500000001413612631676263031244 0ustar00jpettitjpettit00000000000000 Debug x86 3.8 259905a2-7434-4190-8a33-8fba67171dd6 2.0 OpenvSwitch Package $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets bin\$(Configuration)\ obj\$(Configuration)\ Debug bin\$(Configuration)\ obj\$(Configuration)\ BinariesPath=Binaries;SymbolsPath=Symbols; False False 1076; Debug bin\$(Platform)\$(Configuration)\ obj\$(Platform)\$(Configuration)\ BinariesPath=Binaries;SymbolsPath=Symbols; False False 1076; bin\$(Platform)\$(Configuration)\ obj\$(Platform)\$(Configuration)\ Debug bin\$(Platform)\$(Configuration)\ obj\$(Platform)\$(Configuration)\ BinariesPath=Binaries;SymbolsPath=Symbols; False False 1076; bin\$(Platform)\$(Configuration)\ obj\$(Platform)\$(Configuration)\ Debug bin\$(Platform)\$(Configuration)\ obj\$(Platform)\$(Configuration)\ BinariesPath=Binaries;SymbolsPath=Symbols; False False 1076; bin\$(Platform)\$(Configuration)\ obj\$(Platform)\$(Configuration)\ $(WixExtDir)\WixUtilExtension.dll WixUtilExtension $(WixExtDir)\WixUIExtension.dll WixUIExtension openvswitch-2.5.0/windows/PaxHeaders.69223/README.rst0000644000000000000000000000013212631676263017026 xustar0030 mtime=1449622707.606461677 30 atime=1456592667.491097785 30 ctime=1456594660.241290838 openvswitch-2.5.0/windows/README.rst0000664000175000017500000000253212631676263020520 0ustar00jpettitjpettit00000000000000Open vSwitch Windows installer ============================== This project generates a MSI installer for Open vSwitch on Windows, including CLI executables, services and the Hyper-V vswitch forwarding extension. Requirements ------------ Visual Studio 2013 community, professional, premium or ultimate edition ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Visual Studio Community 2013 is freely available at: https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx WiX Toolset 3.9 ^^^^^^^^^^^^^^^ Download and install from: http://wixtoolset.org/releases/v3.9/stable Microsoft_VC120_CRT_x86.msm ^^^^^^^^^^^^^^^^^^^^^^^^^^^ This Windows merge module is available with Visual Studio and contains the Visual C++ 2013 x86 runtime redistributables files. Copy the file in the *Redist* directory. Open vSwitch installer ---------------------- The installer will be generated under the following path: * windows\ovs-windows-installer\bin\Release\OpenvSwitch.msi Note: the kernel driver needs to be signed. Build instructions ------------------ Build the solution in the Visual Studio IDE or via command line: msbuild ovs-windows-installer.sln /p:Platform=x86 /p:Configuration=Release Silent installation ------------------- msiexec /i OpenvSwitch.msi ADDLOCAL=OpenvSwitchCLI,OpenvSwitchDriver /l*v log.txt openvswitch-2.5.0/windows/PaxHeaders.69223/automake.mk0000644000000000000000000000013212631676263017476 xustar0030 mtime=1449622707.606461677 30 atime=1456592426.481209631 30 ctime=1456594659.589263427 openvswitch-2.5.0/windows/automake.mk0000664000175000017500000000712612631676263021174 0ustar00jpettitjpettit00000000000000# Copyright 2015 Cloudbase Solutions Srl # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License.You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the # License for the specific language governing permissions and limitations # under the License. PTHREAD_TEMP_DIR=`echo "$(PTHREAD_LDFLAGS)" | sed 's|^.\(.*\).$:\1||'` windows_installer: all #Userspace files needed for the installer cp -f $(top_srcdir)/datapath-windows/misc/OVS.psm1 windows/ovs-windows-installer/Services/OVS.psm1 cp -f $(top_srcdir)/vswitchd/vswitch.ovsschema windows/ovs-windows-installer/Services/vswitch.ovsschema cp -f $(top_srcdir)/vswitchd/ovs-vswitchd.exe windows/ovs-windows-installer/Services/ovs-vswitchd.exe cp -f $(top_srcdir)/ovsdb/ovsdb-server.exe windows/ovs-windows-installer/Services/ovsdb-server.exe cp -f $(top_srcdir)/utilities/*.exe windows/ovs-windows-installer/Binaries/ cp -f $(top_srcdir)/utilities/*.pdb windows/ovs-windows-installer/Symbols/ cp -f $(top_srcdir)/ovsdb/ovsdb-client.exe windows/ovs-windows-installer/Binaries/ovsdb-client.exe cp -f $(top_srcdir)/ovsdb/ovsdb-tool.exe windows/ovs-windows-installer/Binaries/ovsdb-tool.exe cp -f $(top_srcdir)/ovsdb/ovsdb-client.pdb windows/ovs-windows-installer/Symbols/ cp -f $(top_srcdir)/ovsdb/ovsdb-tool.pdb windows/ovs-windows-installer/Symbols/ #Third party files needed by the installer cp -f $(PTHREAD_WIN32_DIR_DLL_WIN_FORM)/*.dll windows/ovs-windows-installer/Binaries/ cp -f "/c/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC120_CRT_x86.msm" windows/ovs-windows-installer/Redist/Microsoft_VC120_CRT_x86.msm #Forwarding extension files needed for the installer cp -f $(top_srcdir)/datapath-windows/x64/Win8$(VSTUDIO_CONFIG)/package/ovsext.cat windows/ovs-windows-installer/Driver/Win8/ovsext.cat cp -f $(top_srcdir)/datapath-windows/x64/Win8$(VSTUDIO_CONFIG)/package/ovsext.inf windows/ovs-windows-installer/Driver/Win8/ovsext.inf cp -f $(top_srcdir)/datapath-windows/x64/Win8$(VSTUDIO_CONFIG)/package/OVSExt.sys windows/ovs-windows-installer/Driver/Win8/OVSExt.sys cp -f $(top_srcdir)/datapath-windows/x64/Win8.1$(VSTUDIO_CONFIG)/package/ovsext.cat windows/ovs-windows-installer/Driver/Win8.1/ovsext.cat cp -f $(top_srcdir)/datapath-windows/x64/Win8.1$(VSTUDIO_CONFIG)/package/ovsext.inf windows/ovs-windows-installer/Driver/Win8.1/ovsext.inf cp -f $(top_srcdir)/datapath-windows/x64/Win8.1$(VSTUDIO_CONFIG)/package/ovsext.sys windows/ovs-windows-installer/Driver/Win8.1/ovsext.sys MSBuild.exe windows/ovs-windows-installer.sln /target:Build /property:Configuration="Release" EXTRA_DIST += \ windows/.gitignore \ windows/automake.mk \ windows/README.rst \ windows/ovs-windows-installer.sln \ windows/ovs-windows-installer/Actions/OVSActions.js \ windows/ovs-windows-installer/CustomActions.wxs \ windows/ovs-windows-installer/Dialogs/BeginningDialog.wxs \ windows/ovs-windows-installer/Dialogs/MyEndDialog.wxs \ windows/ovs-windows-installer/Dialogs/MyTroubleshootDialog.wxs \ windows/ovs-windows-installer/Dialogs/UserFinishDialog.wxs \ windows/ovs-windows-installer/License.rtf \ windows/ovs-windows-installer/Product.wxs \ windows/ovs-windows-installer/UI.wxs \ windows/ovs-windows-installer/images/bannrbmp.bmp \ windows/ovs-windows-installer/images/dlgbmp.bmp \ windows/ovs-windows-installer/ovs-windows-installer.wixproj openvswitch-2.5.0/windows/PaxHeaders.69223/.gitignore0000644000000000000000000000013212631676263017327 xustar0030 mtime=1449622707.606461677 30 atime=1456592371.334945146 30 ctime=1456594660.241290838 openvswitch-2.5.0/windows/.gitignore0000664000175000017500000000540412631676263021022 0ustar00jpettitjpettit00000000000000## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.sln.docstates ovs-windows-installer/Binaries.wxs ovs-windows-installer/Symbols.wxs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ x64/ build/ bld/ [Bb]in/ [Oo]bj/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* #NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opensdf *.sdf *.cachefile # Visual Studio profiler *.psess *.vsp *.vspx # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding addin-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch *.ncrunch* _NCrunch_* .*crunch*.local.xml # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # NuGet Packages Directory packages/* ## TODO: If the tool you use requires repositories.config uncomment the next line #!packages/repositories.config # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets # This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented) !packages/build/ # Windows Azure Build Output csx/ *.build.csdef # Windows Store app package directory AppPackages/ # Others sql/ *.Cache ClientBin/ [Ss]tyle[Cc]op.* ~$* *~ *.dbmdl *.dbproj.schemaview *.pfx *.publishsettings node_modules/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file to a newer # Visual Studio version. Backup files are not needed, because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ # ========================= # Windows detritus # ========================= # Windows image file caches Thumbs.db ehthumbs.db # Folder config file Desktop.ini # Recycle Bin used on file shares $RECYCLE.BIN/ openvswitch-2.5.0/PaxHeaders.69223/CodingStyle.md0000644000000000000000000000013212631676262016412 xustar0030 mtime=1449622706.874435954 30 atime=1456592667.279089093 30 ctime=1456594659.641265614 openvswitch-2.5.0/CodingStyle.md0000664000175000017500000004644212631676262020114 0ustar00jpettitjpettit00000000000000Open vSwitch Coding Style ========================= This file describes the coding style used in most C files in the Open vSwitch distribution. However, Linux kernel code datapath directory follows the Linux kernel's established coding conventions. For the Windows kernel datapath code, use the coding style described in datapath-windows/CodingStyle. The following GNU indent options approximate this style: -npro -bad -bap -bbb -br -blf -brs -cdw -ce -fca -cli0 -npcs -i4 -l79 \ -lc79 -nbfda -nut -saf -sai -saw -sbi4 -sc -sob -st -ncdb -pi4 -cs -bs \ -di1 -lp -il0 -hnl ## BASICS Limit lines to 79 characters. Use form feeds (control+L) to divide long source files into logical pieces. A form feed should appear as the only character on a line. Do not use tabs for indentation. Avoid trailing spaces on lines. ## NAMING - Use names that explain the purpose of a function or object. - Use underscores to separate words in an identifier: multi_word_name. - Use lowercase for most names. Use uppercase for macros, macro parameters, and members of enumerations. - Give arrays names that are plural. - Pick a unique name prefix (ending with an underscore) for each module, and apply that prefix to all of that module's externally visible names. Names of macro parameters, struct and union members, and parameters in function prototypes are not considered externally visible for this purpose. - Do not use names that begin with _. If you need a name for "internal use only", use __ as a suffix instead of a prefix. - Avoid negative names: "found" is a better name than "not_found". - In names, a "size" is a count of bytes, a "length" is a count of characters. A buffer has size, but a string has length. The length of a string does not include the null terminator, but the size of the buffer that contains the string does. ## COMMENTS Comments should be written as full sentences that start with a capital letter and end with a period. Put two spaces between sentences. Write block comments as shown below. You may put the /* and */ on the same line as comment text if you prefer. /* * We redirect stderr to /dev/null because we often want to remove all * traffic control configuration on a port so its in a known state. If * this done when there is no such configuration, tc complains, so we just * always ignore it. */ Each function and each variable declared outside a function, and each struct, union, and typedef declaration should be preceded by a comment. See FUNCTION DEFINITIONS below for function comment guidelines. Each struct and union member should each have an inline comment that explains its meaning. structs and unions with many members should be additionally divided into logical groups of members by block comments, e.g.: /* An event that will wake the following call to poll_block(). */ struct poll_waiter { /* Set when the waiter is created. */ struct ovs_list node; /* Element in global waiters list. */ int fd; /* File descriptor. */ short int events; /* Events to wait for (POLLIN, POLLOUT). */ poll_fd_func *function; /* Callback function, if any, or null. */ void *aux; /* Argument to callback function. */ struct backtrace *backtrace; /* Event that created waiter, or null. */ /* Set only when poll_block() is called. */ struct pollfd *pollfd; /* Pointer to element of the pollfds array (null if added from a callback). */ }; Use XXX or FIXME comments to mark code that needs work. Don't use `//` comments. Don't comment out or #if 0 out code. Just remove it. The code that was there will still be in version control history. ## FUNCTIONS Put the return type, function name, and the braces that surround the function's code on separate lines, all starting in column 0. Before each function definition, write a comment that describes the function's purpose, including each parameter, the return value, and side effects. References to argument names should be given in single-quotes, e.g. 'arg'. The comment should not include the function name, nor need it follow any formal structure. The comment does not need to describe how a function does its work, unless this information is needed to use the function correctly (this is often better done with comments *inside* the function). Simple static functions do not need a comment. Within a file, non-static functions should come first, in the order that they are declared in the header file, followed by static functions. Static functions should be in one or more separate pages (separated by form feed characters) in logical groups. A commonly useful way to divide groups is by "level", with high-level functions first, followed by groups of progressively lower-level functions. This makes it easy for the program's reader to see the top-down structure by reading from top to bottom. All function declarations and definitions should include a prototype. Empty parentheses, e.g. "int foo();", do not include a prototype (they state that the function's parameters are unknown); write "void" in parentheses instead, e.g. "int foo(void);". Prototypes for static functions should either all go at the top of the file, separated into groups by blank lines, or they should appear at the top of each page of functions. Don't comment individual prototypes, but a comment on each group of prototypes is often appropriate. In the absence of good reasons for another order, the following parameter order is preferred. One notable exception is that data parameters and their corresponding size parameters should be paired. 1. The primary object being manipulated, if any (equivalent to the "this" pointer in C++). 2. Input-only parameters. 3. Input/output parameters. 4. Output-only parameters. 5. Status parameter. Example: ``` /* Stores the features supported by 'netdev' into each of '*current', * '*advertised', '*supported', and '*peer' that are non-null. Each value * is a bitmap of "enum ofp_port_features" bits, in host byte order. * Returns 0 if successful, otherwise a positive errno value. On failure, * all of the passed-in values are set to 0. */ int netdev_get_features(struct netdev *netdev, uint32_t *current, uint32_t *advertised, uint32_t *supported, uint32_t *peer) { ... } ``` Functions that destroy an instance of a dynamically-allocated type should accept and ignore a null pointer argument. Code that calls such a function (including the C standard library function free()) should omit a null-pointer check. We find that this usually makes code easier to read. Functions in .c files should not normally be marked "inline", because it does not usually help code generation and it does suppress compilers warnings about unused functions. (Functions defined in .h usually should be marked inline.) ## FUNCTION PROTOTYPES Put the return type and function name on the same line in a function prototype: static const struct option_class *get_option_class(int code); Omit parameter names from function prototypes when the names do not give useful information, e.g.: int netdev_get_mtu(const struct netdev *, int *mtup); ## STATEMENTS Indent each level of code with 4 spaces. Use BSD-style brace placement: if (a()) { b(); d(); } Put a space between "if", "while", "for", etc. and the expressions that follow them. Enclose single statements in braces: if (a > b) { return a; } else { return b; } Use comments and blank lines to divide long functions into logical groups of statements. Avoid assignments inside "if" and "while" conditions. Do not put gratuitous parentheses around the expression in a return statement, that is, write "return 0;" and not "return(0);" Write only one statement per line. Indent "switch" statements like this: switch (conn->state) { case S_RECV: error = run_connection_input(conn); break; case S_PROCESS: error = 0; break; case S_SEND: error = run_connection_output(conn); break; default: OVS_NOT_REACHED(); } "switch" statements with very short, uniform cases may use an abbreviated style: switch (code) { case 200: return "OK"; case 201: return "Created"; case 202: return "Accepted"; case 204: return "No Content"; default: return "Unknown"; } Use "for (;;)" to write an infinite loop. In an if/else construct where one branch is the "normal" or "common" case and the other branch is the "uncommon" or "error" case, put the common case after the "if", not the "else". This is a form of documentation. It also places the most important code in sequential order without forcing the reader to visually skip past less important details. (Some compilers also assume that the "if" branch is the more common case, so this can be a real form of optimization as well.) ## RETURN VALUES For functions that return a success or failure indication, prefer one of the following return value conventions: * An "int" where 0 indicates success and a positive errno value indicates a reason for failure. * A "bool" where true indicates success and false indicates failure. ## MACROS Don't define an object-like macro if an enum can be used instead. Don't define a function-like macro if a "static inline" function can be used instead. If a macro's definition contains multiple statements, enclose them with "do { ... } while (0)" to allow them to work properly in all syntactic circumstances. Do use macros to eliminate the need to update different parts of a single file in parallel, e.g. a list of enums and an array that gives the name of each enum. For example: /* Logging importance levels. */ #define VLOG_LEVELS \ VLOG_LEVEL(EMER, LOG_ALERT) \ VLOG_LEVEL(ERR, LOG_ERR) \ VLOG_LEVEL(WARN, LOG_WARNING) \ VLOG_LEVEL(INFO, LOG_NOTICE) \ VLOG_LEVEL(DBG, LOG_DEBUG) enum vlog_level { #define VLOG_LEVEL(NAME, SYSLOG_LEVEL) VLL_##NAME, VLOG_LEVELS #undef VLOG_LEVEL VLL_N_LEVELS }; /* Name for each logging level. */ static const char *level_names[VLL_N_LEVELS] = { #define VLOG_LEVEL(NAME, SYSLOG_LEVEL) #NAME, VLOG_LEVELS #undef VLOG_LEVEL }; ## THREAD SAFETY ANNOTATIONS Use the macros in lib/compiler.h to annotate locking requirements. For example: static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; static struct ovs_rwlock rwlock = OVS_RWLOCK_INITIALIZER; void function_require_plain_mutex(void) OVS_REQUIRES(mutex); void function_require_rwlock(void) OVS_REQ_RDLOCK(rwlock); Pass lock objects, not their addresses, to the annotation macros. (Thus we have OVS_REQUIRES(mutex) above, not OVS_REQUIRES(&mutex).) ## SOURCE FILES Each source file should state its license in a comment at the very top, followed by a comment explaining the purpose of the code that is in that file. The comment should explain how the code in the file relates to code in other files. The goal is to allow a programmer to quickly figure out where a given module fits into the larger system. The first non-comment line in a .c source file should be: #include `#include` directives should appear in the following order: 1. `#include ` 2. The module's own headers, if any. Including this before any other header (besides ) ensures that the module's header file is self-contained (see HEADER FILES) below. 3. Standard C library headers and other system headers, preferably in alphabetical order. (Occasionally one encounters a set of system headers that must be included in a particular order, in which case that order must take precedence.) 4. Open vSwitch headers, in alphabetical order. Use "", not <>, to specify Open vSwitch header names. ## HEADER FILES Each header file should start with its license, as described under SOURCE FILES above, followed by a "header guard" to make the header file idempotent, like so: #ifndef NETDEV_H #define NETDEV_H 1 ... #endif /* netdev.h */ Header files should be self-contained; that is, they should #include whatever additional headers are required, without requiring the client to #include them for it. Don't define the members of a struct or union in a header file, unless client code is actually intended to access them directly or if the definition is otherwise actually needed (e.g. inline functions defined in the header need them). Similarly, don't #include a header file just for the declaration of a struct or union tag (e.g. just for "struct ;"). Just declare the tag yourself. This reduces the number of header file dependencies. ## TYPES Use typedefs sparingly. Code is clearer if the actual type is visible at the point of declaration. Do not, in general, declare a typedef for a struct, union, or enum. Do not declare a typedef for a pointer type, because this can be very confusing to the reader. A function type is a good use for a typedef because it can clarify code. The type should be a function type, not a pointer-to-function type. That way, the typedef name can be used to declare function prototypes. (It cannot be used for function definitions, because that is explicitly prohibited by C89 and C99.) You may assume that "char" is exactly 8 bits and that "int" and "long" are at least 32 bits. Don't assume that "long" is big enough to hold a pointer. If you need to cast a pointer to an integer, use "intptr_t" or "uintptr_t" from . Use the int_t and uint_t types from for exact-width integer types. Use the PRId, PRIu, and PRIx macros from for formatting them with printf() and related functions. For compatibility with antique printf() implementations: - Instead of "%zu", use "%"PRIuSIZE. - Instead of "%td", use "%"PRIdPTR. - Instead of "%ju", use "%"PRIuMAX. Other variants exist for different radixes. For example, use "%"PRIxSIZE instead of "%zx" or "%x" instead of "%hhx". Also, instead of "%hhd", use "%d". Be cautious substituting "%u", "%x", and "%o" for the corresponding versions with "hh": cast the argument to unsigned char if necessary, because printf("%hhu", -1) prints 255 but printf("%u", -1) prints 4294967295. Use bit-fields sparingly. Do not use bit-fields for layout of network protocol fields or in other circumstances where the exact format is important. Declare bit-fields to be signed or unsigned integer types or _Bool (aka bool). Do *not* declare bit-fields of type "int": C99 allows these to be either signed or unsigned according to the compiler's whim. (A 1-bit bit-field of type "int" may have a range of -1...0!) Try to order structure members such that they pack well on a system with 2-byte "short", 4-byte "int", and 4- or 8-byte "long" and pointer types. Prefer clear organization over size optimization unless you are convinced there is a size or speed benefit. Pointer declarators bind to the variable name, not the type name. Write "int *x", not "int* x" and definitely not "int * x". ## EXPRESSIONS Put one space on each side of infix binary and ternary operators: * / % + - << >> < <= > >= == != & ^ | && || ?: = += -= *= /= %= &= ^= |= <<= >>= Avoid comma operators. Do not put any white space around postfix, prefix, or grouping operators: () [] -> . ! ~ ++ -- + - * & Exception 1: Put a space after (but not before) the "sizeof" keyword. Exception 2: Put a space between the () used in a cast and the expression whose type is cast: (void *) 0. Break long lines before the ternary operators ? and :, rather than after them, e.g. return (out_port != VIGP_CONTROL_PATH ? alpheus_output_port(dp, skb, out_port) : alpheus_output_control(dp, skb, fwd_save_skb(skb), VIGR_ACTION)); Do not parenthesize the operands of && and || unless operator precedence makes it necessary, or unless the operands are themselves expressions that use && and ||. Thus: if (!isdigit((unsigned char)s[0]) || !isdigit((unsigned char)s[1]) || !isdigit((unsigned char)s[2])) { printf("string %s does not start with 3-digit code\n", s); } but if (rule && (!best || rule->priority > best->priority)) { best = rule; } Do parenthesize a subexpression that must be split across more than one line, e.g.: *idxp = ((l1_idx << PORT_ARRAY_L1_SHIFT) | (l2_idx << PORT_ARRAY_L2_SHIFT) | (l3_idx << PORT_ARRAY_L3_SHIFT)); Try to avoid casts. Don't cast the return value of malloc(). The "sizeof" operator is unique among C operators in that it accepts two very different kinds of operands: an expression or a type. In general, prefer to specify an expression, e.g. "int *x = xmalloc(sizeof *x);". When the operand of sizeof is an expression, there is no need to parenthesize that operand, and please don't. Use the ARRAY_SIZE macro from lib/util.h to calculate the number of elements in an array. When using a relational operator like "<" or "==", put an expression or variable argument on the left and a constant argument on the right, e.g. "x == 0", *not* "0 == x". ## BLANK LINES Put one blank line between top-level definitions of functions and global variables. ## C DIALECT Most C99 features are OK because they are widely implemented: * Flexible array members (e.g. struct { int foo[]; }). * "static inline" functions (but no other forms of "inline", for which GCC and C99 have differing interpretations). * "long long" * and . * bool and , but don't assume that bool or _Bool can only take on the values 0 or 1, because this behavior can't be simulated on C89 compilers. Also, don't assume that a conversion to bool or _Bool follows C99 semantics. I.e. use "(bool)(some_value != 0)" rather than "(bool)some_value". The latter might produce unexpected results on non-C99 environments. For example, if bool is implemented as a typedef of char and some_value = 0x10000000. * Designated initializers (e.g. "struct foo foo = {.a = 1};" and "int a[] = {[2] = 5};"). * Mixing of declarations and code within a block. Please use this judiciously; keep declarations nicely grouped together in the beginning of a block if possible. * Use of declarations in iteration statements (e.g. "for (int i = 0; i < 10; i++)"). * Use of a trailing comma in an enum declaration (e.g. "enum { x = 1, };"). As a matter of style, avoid // comments. Avoid using GCC or Clang extensions unless you also add a fallback for other compilers. You can, however, use C99 features or GCC extensions also supported by Clang in code that compiles only on GNU/Linux (such as lib/netdev-linux.c), because GCC is the system compiler there. ## PYTHON When introducing new Python code, try to follow Python's [PEP 8](http://www.python.org/dev/peps/pep-0008/) style. Consider running the `pep8` or `flake8` tool against your code to find issues. openvswitch-2.5.0/PaxHeaders.69223/INSTALL.SELinux.md0000644000000000000000000000013212663320001016600 xustar0030 mtime=1456316417.426932767 30 atime=1456592356.374330686 30 ctime=1456594659.653266117 openvswitch-2.5.0/INSTALL.SELinux.md0000664000175000017500000001524012663320001020272 0ustar00jpettitjpettit00000000000000Running Open vSwitch under SELinux ================================== Security-Enhanced Linux (SELinux) is a Linux kernel security module that limits "the malicious things" that certain processes, including OVS, can do to the system in case they get compromised. In our case SELinux basically serves as the "second line of defense" that limits the things that OVS processes are allowed to do. The "first line of defense" is proper input validation that eliminates code paths that could be used by attacker to do any sort of "escape attacks" (e.g. file name escape, shell escape, command line argument escape, buffer escape). Since developers don't always implement proper input validation, then SELinux Access Control's goal is to confine damage of such attacks, if they turned out to be possible. Besides Type Enforcement there are other SELinux features, but they are out of scope for this document. Currently there are two SELinux policies for Open vSwitch: 1. the one that ships with your Linux distribution (i.e. selinux-policy-targeted package); And 2. the one that ships with OVS (i.e. openvswitch-selinux-policy package). Limitations ----------- If Open vSwitch is directly started from command line, then it will run under "unconfined_t" SELinux domain that basically lets daemon to do whatever it likes. This is very important for developers to understand, because they might introduced code in OVS that invokes new system calls that SELinux policy did not anticipate. This means that their feature may have worked out just fine for them. However, if someone else would try to run the same code when Open vSwitch is started through systemctl, then Open vSwitch would get Permission Denied errors. Currently the only distributions that enforce SELinux on OVS by default are RHEL, CentOS and Fedora. While Ubuntu and Debian also have some SELinux support, they run Open vSwitch under the unrestricted "unconfined" domain. Also, it seems that Ubuntu is leaning towards Apparmor that works slightly differently than SELinux. SELinux and Open vSwitch are moving targets. What this means is that, if you solely rely on your Linux distribution's SELinux policy, then this policy might not have correctly anticipated that a newer Open vSwitch version needs extra white list rules. However, if you solely rely on SELinux policy that ships with Open vSwitch, then Open vSwitch developers might not have correctly anticipated the feature set that your SELinux implementation supports. Installation ------------ Refer to [INSTALL.Fedora.md] for instructions on how to build all Open vSwitch rpm packages. Once the package is built, install it on your Linux distribution with: # yum install openvswitch-selinux-policy-2.4.1-1.el7.centos.noarch.rpm And, then restart Open vSwitch: # systemctl restart openvswitch Troubleshooting --------------- When SELinux was implemented some of the standard system utilities acquired "-Z" flag (e.g. "ps -Z", "ls -Z"). For example, to find out under which SELinux security domain process runs, use: # ps -AZ | grep ovs-vswitchd system_u:system_r:openvswitch_t:s0 854 ? ovs-vswitchd To find out the SELinux label of file or directory, use: # ls -Z /etc/openvswitch/conf.db system_u:object_r:openvswitch_rw_t:s0 /etc/openvswitch/conf.db If, for example, SELinux policy for Open vSwitch is too strict, then you might see in Open vSwitch log files "Permission Denied" errors: # cat /var/log/openvswitch/ovs-vswitchd.log vlog|INFO|opened log file /var/log/openvswitch/ovs-vswitchd.log ovs_numa|INFO|Discovered 2 CPU cores on NUMA node 0 ovs_numa|INFO|Discovered 1 NUMA nodes and 2 CPU cores reconnect|INFO|unix:/var/run/openvswitch/db.sock: connecting... reconnect|INFO|unix:/var/run/openvswitch/db.sock: connected netlink_socket|ERR|fcntl: Permission denied dpif_netlink|ERR|Generic Netlink family 'ovs_datapath' does not exist. The Open vSwitch kernel module is probably not loaded. dpif|WARN|failed to enumerate system datapaths: Permission denied dpif|WARN|failed to create datapath ovs-system: Permission denied However, not all "Permission denied" errors are caused by SELinux. So, before blaming too strict SELinux policy, make sure that indeed SELinux was the one that denied OVS access to certain resources, for example, run: # grep "openvswitch_t" /var/log/audit/audit.log | tail type=AVC msg=audit(1453235431.640:114671): avc: denied { getopt } for pid=4583 comm="ovs-vswitchd" scontext=system_u:system_r:openvswitch_t:s0 tcontext=system_u:system_r:openvswitch_t:s0 tclass=netlink_generic_socket permissive=0 If SELinux denied OVS access to certain resources, then make sure that you have installed our SELinux policy package that "loosens" up distribution's SELinux policy: # rpm -qa | grep openvswitch-selinux openvswitch-selinux-policy-2.4.1-1.el7.centos.noarch And, then verify that this module was indeed loaded: # semodule -l | grep openvswitch openvswitch-custom 1.0 openvswitch 1.1.1 If you still see Permission denied errors, then take a look into selinux/openvswitch.te file in the OVS source tree and try to add white list rules. This is really simple, just run SELinux audit2allow tool: # grep "openvswitch_t" /var/log/audit/audit.log | audit2allow -M ovslocal See "Contributing SELinux policy patches" section, if you think that other Open vSwitch users would benefit from your SELinux policy changes. Contributing SELinux policy patches ----------------------------------- Here are few things to consider before proposing SELinux policy patches to Open vSwitch developer mailing list: 1. The SELinux policy that resides in Open vSwitch source tree amends SELinux policy that ships with your distributions. Implications of this are that it is assumed that the distribution's Open vSwitch SELinux module must be already loaded to satisfy dependencies. 2. The SELinux policy that resides in Open vSwitch source tree must work on all currently relevant Linux distributions. Implications of this are that you should use only those SELinux policy features that are supported by the lowest SELinux version out there. Typically this means that you should test your SELinux policy changes on the oldest RHEL or CentOS version that this OVS version supports. Check INSTALL.Fedora.md file to find out this. 3. The SELinux policy is enforced only when state transition to openvswitch_t domain happens. Implications of this are that perhaps instead of loosening SELinux policy you can do certain things at the time rpm package is installed. Reporting Bugs -------------- Please report problems to bugs@openvswitch.org. [INSTALL.md]:INSTALL.md openvswitch-2.5.0/PaxHeaders.69223/boot.sh0000644000000000000000000000013211674446641015145 xustar0030 mtime=1324502433.538026265 30 atime=1456592417.796853072 30 ctime=1456594659.685267463 openvswitch-2.5.0/boot.sh0000775000175000017500000000005011674446641016633 0ustar00jpettitjpettit00000000000000#! /bin/sh autoreconf --install --force openvswitch-2.5.0/PaxHeaders.69223/OPENFLOW-1.1+.md0000644000000000000000000000013212664352753015771 xustar0030 mtime=1456592363.422620179 30 atime=1456592368.170815194 30 ctime=1456594659.661266455 openvswitch-2.5.0/OPENFLOW-1.1+.md0000664000175000017500000002503312664352753017464 0ustar00jpettitjpettit00000000000000OpenFlow 1.1+ support in Open vSwitch ===================================== Open vSwitch support for OpenFlow 1.1 and beyond is a work in progress. This file describes the work still to be done. The Plan -------- OpenFlow version support is not a build-time option. A single build of Open vSwitch must be able to handle all supported versions of OpenFlow. Ideally, even at runtime it should be able to support all protocol versions at the same time on different OpenFlow bridges (and perhaps even on the same bridge). At the same time, it would be a shame to litter the core of the OVS code with lots of ugly code concerned with the details of various OpenFlow protocol versions. The primary approach to compatibility is to abstract most of the details of the differences from the core code, by adding a protocol layer that translates between OF1.x and a slightly higher-level abstract representation. The core of this approach is the many struct ofputil_* structures in lib/ofp-util.h. As a consequence of this approach, OVS cannot use OpenFlow protocol definitions that closely resemble those in the OpenFlow specification, because openflow.h in different versions of the OpenFlow specification defines the same identifier with different values. Instead, openflow-common.h contains definitions that are common to all the specifications and separate protocol version-specific headers contain protocol-specific definitions renamed so as not to conflict, e.g. OFPAT10_ENQUEUE and OFPAT11_ENQUEUE for the OpenFlow 1.0 and 1.1 values for OFPAT_ENQUEUE. Generally, in cases of conflict, the protocol layer will define a more abstract OFPUTIL_* or struct ofputil_*. Here are the current approaches in a few tricky areas: * Port numbering. OpenFlow 1.0 has 16-bit port numbers and later OpenFlow versions have 32-bit port numbers. For now, OVS support for later protocol versions requires all port numbers to fall into the 16-bit range, translating the reserved OFPP_* port numbers. * Actions. OpenFlow 1.0 and later versions have very different ideas of actions. OVS reconciles by translating all the versions' actions (and instructions) to and from a common internal representation. OpenFlow 1.1 ------------ The list of remaining work items for OpenFlow 1.1 is below. It is probably incomplete. * Match and set double-tagged VLANs (QinQ). This requires kernel work for reasonable performance. [optional for OF1.1+] * VLANs tagged with 88a8 Ethertype. This requires kernel work for reasonable performance. [required for OF1.1+] OpenFlow 1.2 ------------ OpenFlow 1.2 support requires OpenFlow 1.1 as a prerequisite. All the additional work specific to Openflow 1.2 are complete. (This is based on the change log at the end of the OF1.2 spec. I didn't compare the specs carefully yet.) OpenFlow 1.3 ------------ OpenFlow 1.3 support requires OpenFlow 1.2 as a prerequisite, plus the following additional work. (This is based on the change log at the end of the OF1.3 spec, reusing most of the section titles directly. I didn't compare the specs carefully yet.) * Add support for multipart requests. Currently we always report OFPBRC_MULTIPART_BUFFER_OVERFLOW. [optional for OF1.3+] * IPv6 extension header handling support. Fully implementing this requires kernel support. This likely will take some careful and probably time-consuming design work. The actual coding, once that is all done, is probably 2 or 3 days work. [optional for OF1.3+] * Per-flow meters. OpenFlow protocol support is now implemented. Support for the special OFPM_SLOWPATH and OFPM_CONTROLLER meters is missing. Support for the software switch is under review. [optional for OF1.3+] * Auxiliary connections. An implementation in generic code might be a week's worth of work. The value of an implementation in generic code is questionable, though, since much of the benefit of axuiliary connections is supposed to be to take advantage of hardware support. (We could make the kernel module somehow send packets across the auxiliary connections directly, for some kind of "hardware" support, if we judged it useful enough.) [optional for OF1.3+] * Provider Backbone Bridge tagging. I don't plan to implement this (but we'd accept an implementation). [optional for OF1.3+] * On-demand flow counters. I think this might be a real optimization in some cases for the software switch. [optional for OF1.3+] OpenFlow 1.4 & ONF Extensions for 1.3.X Pack1 --------------------------------------------- The following features are both defined as a set of ONF Extensions for 1.3 and integrated in 1.4. When defined as an ONF Extension for 1.3, the feature is using the Experimenter mechanism with the ONF Experimenter ID. When defined integrated in 1.4, the feature use the standard OpenFlow structures (for example defined in openflow-1.4.h). The two definitions for each feature are independant and can exist in parallel in OVS. * Flow entry notifications This seems to be modelled after OVS's NXST_FLOW_MONITOR. (Simon Horman is working on this.) [EXT-187] [optional for OF1.4+] * Role Status Already implemented as a 1.4 feature. [EXT-191] [required for OF1.4+] * Flow entry eviction OVS has flow eviction functionality. table_mod OFPTC_EVICTION, flow_mod 'importance', and table_desc ofp_table_mod_prop_eviction need to be implemented. [EXT-192-e] [optional for OF1.4+] * Vacancy events [EXT-192-v] [optional for OF1.4+] * Bundle Transactional modification. OpenFlow 1.4 requires to support flow_mods and port_mods in a bundle if bundle is supported. (Not related to OVS's 'ofbundle' stuff.) Implemented as an OpenFlow 1.4 feature. Only flow_mods and port_mods are supported in a bundle. If the bundle includes port mods, it may not specify the OFPBF_ATOMIC flag. Nevertheless, port mods and flow mods in a bundle are always applied in order and consecutive flow mods between port mods are made available to lookups atomically. [EXT-230] [optional for OF1.4+] * Table synchronisation Probably not so useful to the software switch. [EXT-232] [optional for OF1.4+] * Group and Meter change notifications [EXT-235] [optional for OF1.4+] * Bad flow entry priority error Probably not so useful to the software switch. [EXT-236] [optional for OF1.4+] * Set async config error [EXT-237] [optional for OF1.4+] * PBB UCA header field See comment on Provider Backbone Bridge in section about OpenFlow 1.3. [EXT-256] [optional for OF1.4+] * Multipart timeout error [EXT-264] [required for OF1.4+] OpenFlow 1.4 only ----------------- Those features are those only available in OpenFlow 1.4, other OpenFlow 1.4 features are listed in the previous section. * More extensible wire protocol Many on-wire structures got TLVs. Already implemented: port desc properties, port mod properties, port stats properties, table mod properties, queue stats, unified property errors. Remaining required: set-async, queue desc Remaining optional: table desc, table-status [EXT-262] [required for OF1.4+] * More descriptive reasons for packet-in Distinguish OFPR_APPLY_ACTION, OFPR_ACTION_SET, OFPR_GROUP, OFPR_PACKET_OUT. NO_MATCH was renamed to OFPR_TABLE_MISS. (OFPR_ACTION_SET and OFPR_GROUP are now supported) [EXT-136] [required for OF1.4+] * Optical port properties [EXT-154] [optional for OF1.4+] OpenFlow 1.5 & ONF Extensions for 1.3.X Pack2 --------------------------------------------- The following features are both defined as a set of ONF Extensions for 1.3 and integrated in 1.5. Note that this list is not definitive as those are not yet published. When defined as an ONF Extension for 1.3, the feature is using the Experimenter mechanism with the ONF Experimenter ID. When defined integrated in 1.5, the feature use the standard OpenFlow structures (for example defined in openflow-1.5.h). The two definitions for each feature are independant and can exist in parallel in OVS. * Time scheduled bundles [EXT-340] [optional for OF1.5+] OpenFlow 1.5 only ----------------- Those features are those only available in OpenFlow 1.5, other OpenFlow 1.5 features are listed in the previous section. Note that this list is not definitive as OpenFlow 1.5 is not yet published. * Egress Tables [EXT-306] [optional for OF1.5+] * Packet Type aware pipeline Prototype for OVS was done during specification. [EXT-112] [optional for OF1.5+] * Extensible Flow Entry Statistics [EXT-334] [required for OF1.5+] * Flow Entry Statistics Trigger [EXT-335] [optional for OF1.5+] * Controller connection status Prototype for OVS was done during specification. [EXT-454] [optional for OF1.5+] * Meter action [EXT-379] [required for OF1.5+ if metering is supported] * Enable setting all pipeline fields in packet-out Prototype for OVS was done during specification. [EXT-427] [required for OF1.5+] * Port properties for pipeline fields Prototype for OVS was done during specification. [EXT-388] [optional for OF1.5+] * Port property for recirculation Prototype for OVS was done during specification. [EXT-399] [optional for OF1.5+] General ----- * ovs-ofctl(8) often lists as Nicira extensions features that later OpenFlow versions support in standard ways. How to contribute ----------------- If you plan to contribute code for a feature, please let everyone know on ovs-dev before you start work. This will help avoid duplicating work. Please consider the following: * Testing. Please test your code. * Unit tests. Please consider writing some. The tests directory has many examples that you can use as a starting point. * ovs-ofctl. If you add a feature that is useful for some ovs-ofctl command then you should add support for it there. * Documentation. If you add a user-visible feature, then you should document it in the appropriate manpage and mention it in NEWS as well. * Coding style (see the [CodingStyle.md] file at the top of the source tree). * The patch submission guidelines (see [CONTRIBUTING.md]). I recommend using "git send-email", which automatically follows a lot of those guidelines. Bug Reporting ------------- Please report problems to bugs@openvswitch.org. [CONTRIBUTING.md]:CONTRIBUTING.md [CodingStyle.md]:CodingStyle.md openvswitch-2.5.0/PaxHeaders.69223/Documentation0000644000000000000000000000013212664357343016402 xustar0030 mtime=1456594659.753270322 30 atime=1456594661.701352216 30 ctime=1456594659.753270322 openvswitch-2.5.0/Documentation/0000775000175000017500000000000012664357343020147 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/Documentation/PaxHeaders.69223/group-selection-method-property.txt0000644000000000000000000000013212631676262025475 xustar0030 mtime=1449622706.878436095 30 atime=1456592667.283089256 30 ctime=1456594659.753270322 openvswitch-2.5.0/Documentation/group-selection-method-property.txt0000664000175000017500000001142712631676262027172 0ustar00jpettitjpettit00000000000000Proposal for Group Selection Method Property Version: 0.0.3 Author: Simon Horman , et al. Initial Public Revision: September 2014 Contents ======== 1. Introduction 2. How it Works 3. Experimenter Id 4. Experimenter Messages 5. History 1. Introduction =============== This text describes a Netronome Extension to (draft) OpenFlow 1.5 that allows a controller to provide more information on the selection method for select groups. This proposal is in the form of an enhanced select group type. This may subsequently be proposed as an extension or update to the OpenFlow specification. 2. How it works =============== A new Netronome group experimenter property is defined which provides compatibility with the group mod message defined in draft Open Flow 1.5 (also known as ONF EXT-350) and allows parameters for the selection method of select groups to be passed by the controller. In particular it allows controllers to: * Specify the fields used for bucket selection by the select group. * Designate the selection method used. * Provide a non-field parameter to the selection method. 3. Experimenter ID ================== The Experimenter ID of this extension is: NTR_VENDOR_ID = 0x0000154d 4. Group Experimenter Property ============================== The following group property experimenter type defined by this extension. enum ntr_group_mod_subtype { NTRT_SELECTION_METHOD = 1, }; Modifications to the group table from the controller may be done with a OFPT_GROUP_MOD message described (draft) Open Flow 1.5. Group Entry Message. Of relevance here is that (draft) Open Flow 1.5 group messages have properties. This proposal is defined in terms of an implementation of struct ofp_group_prop_experimenter which is described in (draft) Open Flow 1.5. The implementation is: struct ntr_group_prop_selection_method { ovs_be16 type; /* OFPGPT_EXPERIMENTER. */ ovs_be16 length; /* Length in bytes of this property. */ ovs_be32 experimenter; /* NTR_VENDOR_ID. */ ovs_be32 exp_type; /* NTRT_SELECTION_METHOD. */ ovs_be32 pad; char selection_method[NTR_MAX_SELECTION_METHOD_LEN]; /* Null-terminated */ ovs_be64 selection_method_param; /* Non-Field parameter for * bucket selection. */ /* Followed by: * - Exactly (length - 40) (possibly 0) bytes containing OXM TLVs, then * - Exactly ((length + 7)/8*8 - length) (between 0 and 7) bytes of * all-zero bytes * In summary, ntr_group_prop_selection_method is padded as needed, * to make its overall size a multiple of 8, to preserve alignment * in structures using it. */ /* uint8_t field_array[0]; */ /* Zero or more fields encoded as * OXM TLVs where the has_mask bit must * be zero and the value it specifies is * a mask to apply to packet fields and * then input them to the selection * method of a select group. */ /* uint8_t pad2[0]; */ }; OFP_ASSERT(sizeof(struct ntr_group_mod) == 40); This property may only be used with group mod messages whose: * command is OFPGC_ADD or OFPGC_MODIFY; and * type is OFPGT_SELECT The type field is the OFPGPT_EXPERIMENTER which is defined in EXT-350 as 0xffff. The experimenter field is the Experimenter ID (see 3). The exp_type field is NTRT_SELECTION_METHOD. The group selection_method is a null-terminated string which if non-zero length specifies a selection method known to an underlying layer of the switch. The value of NTR_MAX_SELECTION_METHOD_LEN is 16. The group selection_method may be zero-length to request compatibility with Open Flow 1.4. The selection_method_param provides a non-field parameter for the group selection_method. It must be all-zeros unless the group selection_method is non-zero length. The selection_method_param may for example be used as an initial value for the hash of a hash group selection method. The fields field is an ofp_match structure which includes the fields which should be used as inputs to bucket selection. ofp_match is described in Open Flow 1.4 section 7.2.2 Flow Match Structures. Fields must not be specified unless the group selection_method is non-zero length. The pre-requisites for fields specified must be satisfied in the match for any flow that uses the group. Masking is allowed but not required for fields whose TLVs allow masking. The fields may for example be used as the fields that are hashed by a hash group selection method. 5. History ========== This proposal has been developed independently of any similar work in this area. No such work is known. openvswitch-2.5.0/Documentation/PaxHeaders.69223/automake.mk0000644000000000000000000000013212664352753020616 xustar0030 mtime=1456592363.422620179 30 atime=1456592368.170815194 30 ctime=1456594659.565262417 openvswitch-2.5.0/Documentation/automake.mk0000664000175000017500000000010312664352753022300 0ustar00jpettitjpettit00000000000000EXTRA_DIST += \ Documentation/group-selection-method-property.txt openvswitch-2.5.0/PaxHeaders.69223/SECURITY.md0000644000000000000000000000013112631676262015434 xustar0029 mtime=1449622706.91443736 30 atime=1456592667.291089585 30 ctime=1456594659.669266791 openvswitch-2.5.0/SECURITY.md0000664000175000017500000001465612631676262017141 0ustar00jpettitjpettit00000000000000Security Process ================ This is a proposed security vulnerability reporting and handling process for Open vSwitch. It is based on the OpenStack vulnerability management process described at https://wiki.openstack.org/wiki/Vulnerability_Management. The OVS security team coordinates vulnerability management using the ovs-security mailing list. Membership in the security team and subscription to its mailing list consists of a small number of trustworthy people, as determined by rough consensus of the Open vSwitch committers on the ovs-committers mailing list. The Open vSwitch security team should include Open vSwitch committers, to ensure prompt and accurate vulnerability assessments and patch review. We encourage everyone involved in the security process to GPG-sign their emails. We additionally encourage GPG-encrypting one-on-one conversations as part of the security process. What is a vulnerability? ------------------------ All vulnerabilities are bugs, but not every bug is a vulnerability. Vulnerabilities compromise one or more of: * Confidentiality (personal or corporate confidential data). * Integrity (trustworthiness and correctness). * Availability (uptime and service). Here are some examples of vulnerabilities to which one would expect to apply this process: * A crafted packet that causes a kernel or userspace crash (Availability). * A flow translation bug that misforwards traffic in a way likely to hop over security boundaries (Integrity). * An OpenFlow protocol bug that allows a controller to read arbitrary files from the file system (Confidentiality). * Misuse of the OpenSSL library that allows bypassing certificate checks (Integrity). * A bug (memory corruption, overflow, ...) that allows one to modify the behaviour of OVS through external configuration interfaces such as OVSDB (Integrity). * Privileged information is exposed to unprivileged users (Confidentiality). If in doubt, please do use the vulnerability management process. At worst, the response will be to report the bug through the usual channels. Step 1: Reception ----------------- To report an Open vSwitch vulnerability, send an email to the ovs-security mailing list (see "Contact" at the end of this document). A security team member should reply to the reporter acknowledging that the report has been received. Please consider reporting the information mentioned in REPORTING-BUGS.md, where relevant. Reporters may ask for a GPG key while initiating contact with the security team to deliver more sensitive reports. The Linux kernel has its own vulnerability management process: https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/SecurityBugs Handling of vulnerabilities that affect both the Open vSwitch tree and the upstream Linux kernel should be reported through both processes. Please send your report as a single email to both the kernel and OVS security teams to allow those teams to most easily coordinate among themselves. Step 2: Assessment ------------------ The security team should discuss the vulnerability. The reporter should be included in the discussion (via "CC") to an appropriate degree. The assessment should determine which Open vSwitch versions are affected (e.g. every version, only the latest release, only unreleased versions), the privilege required to take advantage of the vulnerability (e.g. any network user, any local L2 network user, any local system user, connected OpenFlow controllers), the severity of the vulnerability, and how the vulnerability may be mitigated (e.g. by disabling a feature). The treatment of the vulnerability could end here if the team determines that it is not a realistic vulnerability. Step 3a: Document ---------------- The security team develops a security advisory document. The document credits the reporter and describes the vulnerability, including all of the relevant information from the assessment in step 2. The security team may, at its discretion, include the reporter (via "CC") in developing the security advisory document, but in any case should accept feedback from the reporter before finalizing the document. When the document is final, the security team should obtain a CVE for the vulnerability from a CNA (https://cve.mitre.org/cve/cna.html). Step 3b: Fix ------------ Steps 3a and 3b may proceed in parallel. The security team develops and obtains (private) reviews for patches that fix the vulnerability. If necessary, the security team pulls in additional developers, who must agree to maintain confidentiality. Step 4: Embargoed Disclosure ---------------------------- The security advisory and patches are sent to downstream stakeholders, with an embargo date and time set from the time sent. Downstream stakeholders are expected not to deploy or disclose patches until the embargo is passed. A disclosure date is negotiated by the security team working with the bug submitter as well as vendors. However, the Open vSwitch security team holds the final say when setting a disclosure date. The timeframe for disclosure is from immediate (esp. if it's already publicly known) to a few weeks. As a basic default policy, we expect report date to disclosure date to be 3~5 business days. Operating system vendors are obvious downstream stakeholders. It may not be necessary to be too choosy about who to include: any major Open vSwitch user who is interested and can be considered trustworthy enough could be included. To become a downstream stakeholder, email the ovs-security mailing list. If the vulnerability is already public, skip this step. Step 5: Public Disclosure ------------------------- When the embargo expires, push the (reviewed) patches to appropriate branches, post the patches to the ovs-dev mailing list (noting that they have already been reviewed and applied), post the security advisory to appropriate mailing lists (ovs-announce, ovs-discuss), and post the security advisory on the Open vSwitch webpage. When the patch is applied to LTS (long-term support) branches, a new version should be released. The security advisory should be GPG-signed by a security team member with a key that is in a public web of trust. Contact ======= Report security vulnerabilities to the ovs-security mailing list: security@openvswitch.org Report problems with this document to the ovs-bugs mailing list: bugs@openvswitch.org Visit http://openvswitch.org/ to learn more about Open vSwitch. openvswitch-2.5.0/PaxHeaders.69223/INSTALL.md0000644000000000000000000000013212664352753015276 xustar0030 mtime=1456592363.422620179 30 atime=1456592368.170815194 30 ctime=1456594659.645265781 openvswitch-2.5.0/INSTALL.md0000664000175000017500000006664712664352753017011 0ustar00jpettitjpettit00000000000000How to Install Open vSwitch on Linux, FreeBSD and NetBSD ======================================================== This document describes how to build and install Open vSwitch on a generic Linux, FreeBSD, or NetBSD host. For specifics around installation on a specific platform, please see one of these files: - [INSTALL.Debian.md] - [INSTALL.Fedora.md] - [INSTALL.RHEL.md] - [INSTALL.XenServer.md] - [INSTALL.NetBSD.md] - [INSTALL.Windows.md] - [INSTALL.DPDK.md] Build Requirements ------------------ To compile the userspace programs in the Open vSwitch distribution, you will need the following software: - GNU make. - A C compiler, such as: * GCC 4.x. * Clang. Clang 3.4 and later provide useful static semantic analysis and thread-safety checks. For Ubuntu, there are nightly built packages available on clang's website. * MSVC 2013. See [INSTALL.Windows] for additional Windows build instructions. While OVS may be compatible with other compilers, optimal support for atomic operations may be missing, making OVS very slow (see lib/ovs-atomic.h). - libssl, from OpenSSL, is optional but recommended if you plan to connect the Open vSwitch to an OpenFlow controller. libssl is required to establish confidentiality and authenticity in the connections from an Open vSwitch to an OpenFlow controller. If libssl is installed, then Open vSwitch will automatically build with support for it. - libcap-ng, written by Steve Grubb, is optional but recommended. It is required to run OVS daemons as a non-root user with dropped root privileges. If libcap-ng is installed, then Open vSwitch will automatically build with support for it. - Python 2.7. On Linux, you may choose to compile the kernel module that comes with the Open vSwitch distribution or to use the kernel module built into the Linux kernel (version 3.3 or later). See the [FAQ.md] question "What features are not available in the Open vSwitch kernel datapath that ships as part of the upstream Linux kernel?" for more information on this trade-off. You may also use the userspace-only implementation, at some cost in features and performance (see [INSTALL.userspace.md] for details). To compile the kernel module on Linux, you must also install the following: - A supported Linux kernel version. Please refer to [README.md] for a list of supported versions. The Open vSwitch datapath requires bridging support (CONFIG_BRIDGE) to be built as a kernel module. (This is common in kernels provided by Linux distributions.) The bridge module must not be loaded or in use. If the bridge module is running (check with "lsmod | grep bridge"), you must remove it ("rmmod bridge") before starting the datapath. For optional support of ingress policing, you must enable kernel configuration options NET_CLS_BASIC, NET_SCH_INGRESS, and NET_ACT_POLICE, either built-in or as modules. (NET_CLS_POLICE is obsolete and not needed.) To use GRE tunneling on Linux 2.6.37 or newer, kernel support for GRE demultiplexing (CONFIG_NET_IPGRE_DEMUX) must be compiled in or available as a module. Also, on kernels before 3.11, the ip_gre module, for GRE tunnels over IP (NET_IPGRE), must not be loaded or compiled in. To configure HTB or HFSC quality of service with Open vSwitch, you must enable the respective configuration options. To use Open vSwitch support for TAP devices, you must enable CONFIG_TUN. - To build a kernel module, you need the same version of GCC that was used to build that kernel. - A kernel build directory corresponding to the Linux kernel image the module is to run on. Under Debian and Ubuntu, for example, each linux-image package containing a kernel binary has a corresponding linux-headers package with the required build infrastructure. If you are working from a Git tree or snapshot (instead of from a distribution tarball), or if you modify the Open vSwitch build system or the database schema, you will also need the following software: - Autoconf version 2.63 or later. - Automake version 1.10 or later. - libtool version 2.4 or later. (Older versions might work too.) To run the unit tests, you also need: - Perl. Version 5.10.1 is known to work. Earlier versions should also work. The ovs-vswitchd.conf.db(5) manpage will include an E-R diagram, in formats other than plain text, only if you have the following: - "dot" from graphviz (http://www.graphviz.org/). - Perl. Version 5.10.1 is known to work. Earlier versions should also work. If you are going to extensively modify Open vSwitch, please consider installing the following to obtain better warnings: - "sparse" version 0.4.4 or later (http://www.kernel.org/pub/software/devel/sparse/dist/). - GNU make. - clang, version 3.4 or later Also, you may find the ovs-dev script found in utilities/ovs-dev.py useful. Installation Requirements ------------------------- The machine on which Open vSwitch is to be installed must have the following software: - libc compatible with the libc used for build. - libssl compatible with the libssl used for build, if OpenSSL was used for the build. - On Linux, the same kernel version configured as part of the build. - For optional support of ingress policing on Linux, the "tc" program from iproute2 (part of all major distributions and available at http://www.linux-foundation.org/en/Net:Iproute2). On Linux you should ensure that /dev/urandom exists. To support TAP devices, you must also ensure that /dev/net/tun exists. Building and Installing Open vSwitch for Linux, FreeBSD or NetBSD ================================================================= Once you have installed all the prerequisites listed above in the Base Prerequisites section, follow the procedures below to bootstrap, to configure and to build the code. Bootstrapping the Sources ------------------------- This step is not needed if you have downloaded a released tarball. If you pulled the sources directly from an Open vSwitch Git tree or got a Git tree snapshot, then run boot.sh in the top source directory to build the "configure" script. `% ./boot.sh` Configuring the Sources ----------------------- Configure the package by running the configure script. You can usually invoke configure without any arguments. For example: `% ./configure` By default all files are installed under /usr/local. If you want to install into, e.g., /usr and /var instead of /usr/local and /usr/local/var, add options as shown here: `% ./configure --prefix=/usr --localstatedir=/var` By default, static libraries are built and linked against. If you want to use shared libraries instead: % ./configure --enable-shared To use a specific C compiler for compiling Open vSwitch user programs, also specify it on the configure command line, like so: `% ./configure CC=gcc-4.2` To use 'clang' compiler: `% ./configure CC=clang` To supply special flags to the C compiler, specify them as CFLAGS on the configure command line. If you want the default CFLAGS, which include "-g" to build debug symbols and "-O2" to enable optimizations, you must include them yourself. For example, to build with the default CFLAGS plus "-mssse3", you might run configure as follows: `% ./configure CFLAGS="-g -O2 -mssse3"` Note that these CFLAGS are not applied when building the Linux kernel module. Custom CFLAGS for the kernel module are supplied using the EXTRA_CFLAGS variable when running make. So, for example: `% make EXTRA_CFLAGS="-Wno-error=date-time" To build the Linux kernel module, so that you can run the kernel-based switch, pass the location of the kernel build directory on --with-linux. For example, to build for a running instance of Linux: `% ./configure --with-linux=/lib/modules/`uname -r`/build` If --with-linux requests building for an unsupported version of Linux, then "configure" will fail with an error message. Please refer to the [FAQ.md] for advice in that case. If you wish to build the kernel module for an architecture other than the architecture of the machine used for the build, you may specify the kernel architecture string using the KARCH variable when invoking the configure script. For example, to build for MIPS with Linux: `% ./configure --with-linux=/path/to/linux KARCH=mips` If you plan to do much Open vSwitch development, you might want to add --enable-Werror, which adds the -Werror option to the compiler command line, turning warnings into errors. That makes it impossible to miss warnings generated by the build. To build with gcov code coverage support, add --enable-coverage, e.g.: `% ./configure --enable-coverage` The configure script accepts a number of other options and honors additional environment variables. For a full list, invoke configure with the --help option. You can also run configure from a separate build directory. This is helpful if you want to build Open vSwitch in more than one way from a single source directory, e.g. to try out both GCC and Clang builds, or to build kernel modules for more than one Linux version. Here is an example: `% mkdir _gcc && (cd _gcc && ../configure CC=gcc)` `% mkdir _clang && (cd _clang && ../configure CC=clang)` Building the Sources -------------------- 1. Run GNU make in the build directory, e.g.: `% make` or if GNU make is installed as "gmake": `% gmake` If you used a separate build directory, run make or gmake from that directory, e.g.: `% make -C _gcc` `% make -C _clang` For improved warnings if you installed "sparse" (see "Prerequisites"), add C=1 to the command line. Some versions of Clang and ccache are not completely compatible. If you see unusual warnings when you use both together, consider disabling ccache for use with Clang. 2. Consider running the testsuite. Refer to "Running the Testsuite" below, for instructions. 3. Become root by running "su" or another program. 4. Run "make install" to install the executables and manpages into the running system, by default under /usr/local. 5. If you built kernel modules, you may install and load them, e.g.: `% make modules_install` `% /sbin/modprobe openvswitch` To verify that the modules have been loaded, run "/sbin/lsmod" and check that openvswitch is listed. If the `modprobe` operation fails, look at the last few kernel log messages (e.g. with `dmesg | tail`): - The message "openvswitch: exports duplicate symbol br_should_route_hook (owned by bridge)" means that the bridge module is loaded. Run `/sbin/rmmod bridge` to remove it. If `/sbin/rmmod bridge` fails with "ERROR: Module bridge does not exist in /proc/modules", then the bridge is compiled into the kernel, rather than as a module. Open vSwitch does not support this configuration (see "Build Requirements", above). - The message "openvswitch: exports duplicate symbol dp_ioctl_hook (owned by ofdatapath)" means that the ofdatapath module from the OpenFlow reference implementation is loaded. Run `/sbin/rmmod ofdatapath` to remove it. (You might have to delete any existing datapaths beforehand, using the "dpctl" program included with the OpenFlow reference implementation. "ovs-dpctl" will not work.) - Otherwise, the most likely problem is that Open vSwitch was built for a kernel different from the one into which you are trying to load it. Run `modinfo` on openvswitch.ko and on a module built for the running kernel, e.g.: ``` % /sbin/modinfo openvswitch.ko % /sbin/modinfo /lib/modules/`uname -r`/kernel/net/bridge/bridge.ko ``` Compare the "vermagic" lines output by the two commands. If they differ, then Open vSwitch was built for the wrong kernel. - If you decide to report a bug or ask a question related to module loading, please include the output from the `dmesg` and `modinfo` commands mentioned above. There is an optional module parameter to openvswitch.ko called vlan_tso that enables TCP segmentation offload over VLANs on NICs that support it. Many drivers do not expose support for TSO on VLANs in a way that Open vSwitch can use but there is no way to detect whether this is the case. If you know that your particular driver can handle it (for example by testing sending large TCP packets over VLANs) then passing in a value of 1 may improve performance. Modules built for Linux kernels 2.6.37 and later, as well as specially patched versions of earlier kernels, do not need this and do not have this parameter. If you do not understand what this means or do not know if your driver will work, do not set this. 6. Initialize the configuration database using ovsdb-tool, e.g.: `% mkdir -p /usr/local/etc/openvswitch` `% ovsdb-tool create /usr/local/etc/openvswitch/conf.db vswitchd/vswitch.ovsschema` Startup ======= Before starting ovs-vswitchd itself, you need to start its configuration database, ovsdb-server. Each machine on which Open vSwitch is installed should run its own copy of ovsdb-server. Configure it to use the database you created during installation (as explained above), to listen on a Unix domain socket, to connect to any managers specified in the database itself, and to use the SSL configuration in the database: % ovsdb-server --remote=punix:/usr/local/var/run/openvswitch/db.sock \ --remote=db:Open_vSwitch,Open_vSwitch,manager_options \ --private-key=db:Open_vSwitch,SSL,private_key \ --certificate=db:Open_vSwitch,SSL,certificate \ --bootstrap-ca-cert=db:Open_vSwitch,SSL,ca_cert \ --pidfile --detach (If you built Open vSwitch without SSL support, then omit --private-key, --certificate, and --bootstrap-ca-cert.) Then initialize the database using ovs-vsctl. This is only necessary the first time after you create the database with ovsdb-tool (but running it at any time is harmless): % ovs-vsctl --no-wait init Then start the main Open vSwitch daemon, telling it to connect to the same Unix domain socket: % ovs-vswitchd --pidfile --detach Now you may use ovs-vsctl to set up bridges and other Open vSwitch features. For example, to create a bridge named br0 and add ports eth0 and vif1.0 to it: % ovs-vsctl add-br br0 % ovs-vsctl add-port br0 eth0 % ovs-vsctl add-port br0 vif1.0 Please refer to ovs-vsctl(8) for more details. Upgrading ========= When you upgrade Open vSwitch from one version to another, you should also upgrade the database schema: 1. Stop the Open vSwitch daemons, e.g.: ``` % kill `cd /usr/local/var/run/openvswitch && cat ovsdb-server.pid ovs-vswitchd.pid` ``` 2. Install the new Open vSwitch release. 3. Upgrade the database, in one of the following two ways: - If there is no important data in your database, then you may delete the database file and recreate it with ovsdb-tool, following the instructions under "Building and Installing Open vSwitch for Linux, FreeBSD or NetBSD". - If you want to preserve the contents of your database, back it up first, then use "ovsdb-tool convert" to upgrade it, e.g.: `% ovsdb-tool convert /usr/local/etc/openvswitch/conf.db vswitchd/vswitch.ovsschema` 4. Start the Open vSwitch daemons as described under "Building and Installing Open vSwitch for Linux, FreeBSD or NetBSD" above. Hot Upgrading ============= Upgrading Open vSwitch from one version to the next version with minimum disruption of traffic going through the system that is using that Open vSwitch needs some considerations: 1. If the upgrade only involves upgrading the userspace utilities and daemons of Open vSwitch, make sure that the new userspace version is compatible with the previously loaded kernel module. 2. An upgrade of userspace daemons means that they have to be restarted. Restarting the daemons means that the OpenFlow flows in the ovs-vswitchd daemon will be lost. One way to restore the flows is to let the controller re-populate it. Another way is to save the previous flows using a utility like ovs-ofctl and then re-add them after the restart. Restoring the old flows is accurate only if the new Open vSwitch interfaces retain the old 'ofport' values. 3. When the new userspace daemons get restarted, they automatically flush the old flows setup in the kernel. This can be expensive if there are hundreds of new flows that are entering the kernel but userspace daemons are busy setting up new userspace flows from either the controller or an utility like ovs-ofctl. Open vSwitch database provides an option to solve this problem through the other_config:flow-restore-wait column of the Open_vSwitch table. Refer to the ovs-vswitchd.conf.db(5) manpage for details. 4. If the upgrade also involves upgrading the kernel module, the old kernel module needs to be unloaded and the new kernel module should be loaded. This means that the kernel network devices belonging to Open vSwitch is recreated and the kernel flows are lost. The downtime of the traffic can be reduced if the userspace daemons are restarted immediately and the userspace flows are restored as soon as possible. The ovs-ctl utility's "restart" function only restarts the userspace daemons, makes sure that the 'ofport' values remain consistent across restarts, restores userspace flows using the ovs-ofctl utility and also uses the other_config:flow-restore-wait column to keep the traffic downtime to the minimum. The ovs-ctl utility's "force-reload-kmod" function does all of the above, but also replaces the old kernel module with the new one. Open vSwitch startup scripts for Debian, XenServer and RHEL use ovs-ctl's functions and it is recommended that these functions be used for other software platforms too. Testsuites ========== This section describe Open vSwitch's built-in support for various test suites. You must bootstrap, configure and build Open vSwitch (steps are in "Building and Installing Open vSwitch for Linux, FreeBSD or NetBSD" above) before you run the tests described here. You do not need to install Open vSwitch or to build or load the kernel module to run these test suites. You do not need supervisor privilege to run these test suites. Self-Tests ---------- Open vSwitch includes a suite of self-tests. Before you submit patches upstream, we advise that you run the tests and ensure that they pass. If you add new features to Open vSwitch, then adding tests for those features will ensure your features don't break as developers modify other areas of Open vSwitch. Refer to "Testsuites" above for prerequisites. To run all the unit tests in Open vSwitch, one at a time: `make check` This takes under 5 minutes on a modern desktop system. To run all the unit tests in Open vSwitch, up to 8 in parallel: `make check TESTSUITEFLAGS=-j8` This takes under a minute on a modern 4-core desktop system. To see a list of all the available tests, run: `make check TESTSUITEFLAGS=--list` To run only a subset of tests, e.g. test 123 and tests 477 through 484: `make check TESTSUITEFLAGS='123 477-484'` (Tests do not have inter-dependencies, so you may run any subset.) To run tests matching a keyword, e.g. "ovsdb": `make check TESTSUITEFLAGS='-k ovsdb'` To see a complete list of test options: `make check TESTSUITEFLAGS=--help` The results of a testing run are reported in tests/testsuite.log. Please report test failures as bugs and include the testsuite.log in your report. If you have "valgrind" installed, then you can also run the testsuite under valgrind by using "make check-valgrind" in place of "make check". All the same options are available via TESTSUITEFLAGS. When you do this, the "valgrind" results for test `` are reported in files named `tests/testsuite.dir//valgrind.*`. You may find that the valgrind results are easier to interpret if you put "-q" in ~/.valgrindrc, since that reduces the amount of output. Sometimes a few tests may fail on some runs but not others. This is usually a bug in the testsuite, not a bug in Open vSwitch itself. If you find that a test fails intermittently, please report it, since the developers may not have noticed. OFTest ------ OFTest is an OpenFlow protocol testing suite. Open vSwitch includes a Makefile target to run OFTest with Open vSwitch in "dummy mode". In this mode of testing, no packets travel across physical or virtual networks. Instead, Unix domain sockets stand in as simulated networks. This simulation is imperfect, but it is much easier to set up, does not require extra physical or virtual hardware, and does not require supervisor privileges. To run OFTest with Open vSwitch, first read and follow the instructions under "Testsuites" above. Second, obtain a copy of OFTest and install its prerequisites. You need a copy of OFTest that includes commit 406614846c5 (make ovs-dummy platform work again). This commit was merged into the OFTest repository on Feb 1, 2013, so any copy of OFTest more recent than that should work. Testing OVS in dummy mode does not require root privilege, so you may ignore that requirement. Optionally, add the top-level OFTest directory (containing the "oft" program) to your $PATH. This slightly simplifies running OFTest later. To run OFTest in dummy mode, run the following command from your Open vSwitch build directory: `make check-oftest OFT=` where `` is the absolute path to the "oft" program in OFTest. If you added "oft" to your $PATH, you may omit the OFT variable assignment: `make check-oftest` By default, "check-oftest" passes "oft" just enough options to enable dummy mode. You can use OFTFLAGS to pass additional options. For example, to run just the basic.Echo test instead of all tests (the default) and enable verbose logging: `make check-oftest OFT= OFTFLAGS='--verbose -T basic.Echo'` If you use OFTest that does not include commit 4d1f3eb2c792 (oft: change default port to 6653), merged into the OFTest repository in October 2013, then you need to add an option to use the IETF-assigned controller port: `make check-oftest OFT= OFTFLAGS='--port=6653'` Please interpret OFTest results cautiously. Open vSwitch can fail a given test in OFTest for many reasons, including bugs in Open vSwitch, bugs in OFTest, bugs in the "dummy mode" integration, and differing interpretations of the OpenFlow standard and other standards. Open vSwitch has not been validated against OFTest. Please do report test failures that you believe to represent bugs in Open vSwitch. Include the precise versions of Open vSwitch and OFTest in your bug report, plus any other information needed to reproduce the problem. Ryu --- Ryu is an OpenFlow controller written in Python that includes an extensive OpenFlow testsuite. Open vSwitch includes a Makefile target to run Ryu in "dummy mode". See "OFTest" above for an explanation of dummy mode. To run Ryu tests with Open vSwitch, first read and follow the instructions under "Testsuites" above. Second, obtain a copy of Ryu, install its prerequisites, and build it. You do not need to install Ryu (some of the tests do not get installed, so it does not help). To run Ryu tests, run the following command from your Open vSwitch build directory: `make check-ryu RYUDIR=` where `` is the absolute path to the root of the Ryu source distribution. The default `` is `$srcdir/../ryu` where $srcdir is your Open vSwitch source directory, so if this default is correct then you make simply run `make check-ryu`. Open vSwitch has not been validated against Ryu. Please do report test failures that you believe to represent bugs in Open vSwitch. Include the precise versions of Open vSwitch and Ryu in your bug report, plus any other information needed to reproduce the problem. Vagrant ------- Requires: Vagrant (version 1.7.0 or later) and a compatible hypervisor You must bootstrap and configure the sources (steps are in "Building and Installing Open vSwitch for Linux, FreeBSD or NetBSD" above) before you run the steps described here. A Vagrantfile is provided allowing to compile and provision the source tree as found locally in a virtual machine using the following commands: vagrant up vagrant ssh This will bring up w Fedora 20 VM by default, alternatively the `Vagrantfile` can be modified to use a different distribution box as base. Also, the VM can be reprovisioned at any time: vagrant provision OVS out-of-tree compilation environment can be set up with: ./boot.sh vagrant provision --provision-with configure_ovs,build_ovs This will set up an out-of-tree build environment in /home/vagrant/build. The source code can be found in /vagrant. Out-of-tree build is preferred to work around limitations of the sync file systems. To recompile and reinstall OVS using RPM: ./boot.sh vagrant provision --provision-with configure_ovs,install_rpm Two provisioners are included to run system tests with the OVS kernel module or with a userspace datapath. This tests are different from the self-tests mentioned above. To run them: ./boot.sh vagrant provision --provision-with configure_ovs,test_ovs_kmod,test_ovs_system_userspace Continuous Integration with Travis-CI ------------------------------------- A .travis.yml file is provided to automatically build Open vSwitch with various build configurations and run the testsuite using travis-ci. Builds will be performed with gcc, sparse and clang with the -Werror compiler flag included, therefore the build will fail if a new warning has been introduced. The CI build is triggered via git push (regardless of the specific branch) or pull request against any Open vSwitch GitHub repository that is linked to travis-ci. Instructions to setup travis-ci for your GitHub repository: 1. Go to http://travis-ci.org/ and sign in using your GitHub ID. 2. Go to the "Repositories" tab and enable the ovs repository. You may disable builds for pushes or pull requests. 3. In order to avoid forks sending build failures to the upstream mailing list, the notification email recipient is encrypted. If you want to receive email notification for build failures, replace the the encrypted string: 3.1) Install the travis-ci CLI (Requires ruby >=2.0): gem install travis 3.2) In your Open vSwitch repository: travis encrypt mylist@mydomain.org 3.3) Add/replace the notifications section in .travis.yml and fill in the secure string as returned by travis encrypt: notifications: email: recipients: - secure: "....." (You may remove/omit the notifications section to fall back to default notification behaviour which is to send an email directly to the author and committer of the failing commit. Note that the email is only sent if the author/committer have commit rights for the particular GitHub repository). 4. Pushing a commit to the repository which breaks the build or the testsuite will now trigger a email sent to mylist@mydomain.org Bug Reporting ============= Please report problems to bugs@openvswitch.org. [README.md]:README.md [INSTALL.Debian.md]:INSTALL.Debian.md [INSTALL.Fedora.md]:INSTALL.Fedora.md [INSTALL.RHEL.md]:INSTALL.RHEL.md [INSTALL.XenServer.md]:INSTALL.XenServer.md [INSTALL.NetBSD.md]:INSTALL.NetBSD.md [INSTALL.DPDK.md]:INSTALL.DPDK.md [INSTALL.userspace.md]:INSTALL.userspace.md [FAQ.md]:FAQ.md openvswitch-2.5.0/PaxHeaders.69223/debian0000644000000000000000000000013212664357344015014 xustar0030 mtime=1456594660.025281758 30 atime=1456594661.701352216 30 ctime=1456594660.025281758 openvswitch-2.5.0/debian/0000775000175000017500000000000012664357344016561 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/debian/PaxHeaders.69223/python-openvswitch.install0000644000000000000000000000013112631676263022346 xustar0030 mtime=1449622707.114444389 30 atime=1456592667.339091552 29 ctime=1456594660.02128159 openvswitch-2.5.0/debian/python-openvswitch.install0000664000175000017500000000010212631676263024030 0ustar00jpettitjpettit00000000000000usr/share/openvswitch/python/ovs usr/lib/python2.7/dist-packages/ openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.init0000644000000000000000000000013212631676263023406 xustar0030 mtime=1449622707.106444108 30 atime=1456592667.335091389 30 ctime=1456594660.005280915 openvswitch-2.5.0/debian/openvswitch-testcontroller.init0000775000175000017500000002120112631676263025075 0ustar00jpettitjpettit00000000000000#!/bin/sh # # Copyright (c) 2011, 2014 Nicira, Inc. # Copyright (c) 2007, 2009 Javier Fernandez-Sanguino # # This is free software; you may redistribute it and/or modify # it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2, # or (at your option) any later version. # # This is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License with # the Debian operating system, in /usr/share/common-licenses/GPL; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, # Suite 330, Boston, MA 02111-1307 USA # ### BEGIN INIT INFO # Provides: openvswitch-testcontroller # Required-Start: $network $local_fs $remote_fs # Required-Stop: $remote_fs # Should-Start: $named # Should-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Simple OpenFlow controller for testing # Description: This controller enables OpenFlow switches that connect to # it to act as MAC-learning Ethernet switches. ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/bin/ovs-testcontroller # Introduce the server's location here NAME=ovs-testcontroller # Introduce the short server's name here DESC=ovs-testcontroller # Introduce a short description here LOGDIR=/var/log/openvswitch # Log directory to use PIDFILE=/var/run/openvswitch/$NAME.pid test -x $DAEMON || exit 0 . /lib/lsb/init-functions # Default options, these can be overriden by the information # at /etc/default/openvswitch-testcontroller DAEMON_OPTS="" # Additional options given to the server DODTIME=10 # Time to wait for the server to die, in seconds # If this value is set too low you might not # let some servers to die gracefully and # 'restart' will not work LOGFILE=$LOGDIR/$NAME.log # Server logfile #DAEMONUSER= # User to run the daemons as. If this value # is set start-stop-daemon will chuid the server # Include defaults if available default=/etc/default/openvswitch-testcontroller if [ -f $default ] ; then . $default fi # Check that the user exists (if we set a user) # Does the user exist? if [ -n "$DAEMONUSER" ] ; then if getent passwd | grep -q "^$DAEMONUSER:"; then # Obtain the uid and gid DAEMONUID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $3}'` DAEMONGID=`getent passwd |grep "^$DAEMONUSER:" | awk -F : '{print $4}'` else log_failure_msg "The user $DAEMONUSER, required to run $NAME does not exist." exit 1 fi fi set -e running_pid() { # Check if a given process pid's cmdline matches a given name pid=$1 name=$2 [ -z "$pid" ] && return 1 [ ! -d /proc/$pid ] && return 1 cmd=`cat /proc/$pid/cmdline | tr "\000" "\n"|head -n 1 |cut -d : -f 1` # Is this the expected server [ "$cmd" != "$name" ] && return 1 return 0 } running() { # Check if the process is running looking at /proc # (works for all users) # No pidfile, probably no daemon present [ ! -f "$PIDFILE" ] && return 1 pid=`cat $PIDFILE` running_pid $pid $DAEMON || return 1 return 0 } start_server() { if [ -z "$LISTEN" ]; then echo "$default: No connection methods configured, controller disabled" >&2 exit 0 fi if [ ! -d /var/run/openvswitch ]; then install -d -m 755 -o root -g root /var/run/openvswitch fi SSL_OPTS= case $LISTEN in *ssl*) : ${PRIVKEY:=/etc/openvswitch-testcontroller/privkey.pem} : ${CERT:=/etc/openvswitch-testcontroller/cert.pem} : ${CACERT:=/etc/openvswitch-testcontroller/cacert.pem} if test ! -e "$PRIVKEY" || test ! -e "$CERT" || test ! -e "$CACERT"; then if test ! -e "$PRIVKEY"; then echo "$PRIVKEY: private key missing" >&2 fi if test ! -e "$CERT"; then echo "$CERT: certificate for private key missing" >&2 fi if test ! -e "$CACERT"; then echo "$CACERT: CA certificate missing" >&2 fi exit 1 fi SSL_OPTS="--private-key=$PRIVKEY --certificate=$CERT --ca-cert=$CACERT" ;; esac # Start the process using the wrapper if [ -z "$DAEMONUSER" ] ; then start-stop-daemon --start --pidfile $PIDFILE \ --exec $DAEMON -- --detach --pidfile=$PIDFILE \ $LISTEN $DAEMON_OPTS $SSL_OPTS errcode=$? else # if we are using a daemonuser then change the user id start-stop-daemon --start --quiet --pidfile $PIDFILE \ --chuid $DAEMONUSER --exec $DAEMON -- \ --detach --pidfile=$PIDFILE $LISTEN $DAEMON_OPTS \ $SSL_OPTS errcode=$? fi return $errcode } stop_server() { # Stop the process using the wrapper if [ -z "$DAEMONUSER" ] ; then start-stop-daemon --stop --quiet --pidfile $PIDFILE \ --exec $DAEMON errcode=$? else # if we are using a daemonuser then look for process that match start-stop-daemon --stop --quiet --pidfile $PIDFILE \ --user $DAEMONUSER --exec $DAEMON errcode=$? fi return $errcode } reload_server() { [ ! -f "$PIDFILE" ] && return 1 pid=`cat $PIDFILE` # This is the daemon's pid # Send a SIGHUP kill -1 $pid return $? } force_stop() { # Force the process to die killing it manually [ ! -e "$PIDFILE" ] && return if running ; then kill -15 $pid # Is it really dead? sleep "$DODTIME" if running ; then kill -9 $pid sleep "$DODTIME" if running ; then echo "Cannot kill $NAME (pid=$pid)!" exit 1 fi fi fi rm -f $PIDFILE } case "$1" in start) log_daemon_msg "Starting $DESC " "$NAME" # Check if it's running first if running ; then log_progress_msg "apparently already running" log_end_msg 0 exit 0 fi if start_server && running ; then # It's ok, the server started and is running log_end_msg 0 else # Either we could not start it or it is not running # after we did # NOTE: Some servers might die some time after they start, # this code does not try to detect this and might give # a false positive (use 'status' for that) log_end_msg 1 fi ;; stop) log_daemon_msg "Stopping $DESC" "$NAME" if running ; then # Only stop the server if we see it running stop_server log_end_msg $? else # If it's not running don't do anything log_progress_msg "apparently not running" log_end_msg 0 exit 0 fi ;; force-stop) # First try to stop gracefully the program $0 stop if running; then # If it's still running try to kill it more forcefully log_daemon_msg "Stopping (force) $DESC" "$NAME" force_stop log_end_msg $? fi ;; restart|force-reload) log_daemon_msg "Restarting $DESC" "$NAME" if running; then stop_server # Wait some sensible amount, some server need this. [ -n "$DODTIME" ] && sleep $DODTIME fi start_server running log_end_msg $? ;; status) log_daemon_msg "Checking status of $DESC" "$NAME" if running ; then log_progress_msg "running" log_end_msg 0 else log_progress_msg "apparently not running" log_end_msg 1 exit 1 fi ;; # Use this if the daemon cannot reload reload) log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon" log_warning_msg "cannot re-read the config file (use restart)." ;; *) N=/etc/init.d/openvswitch-testcontroller echo "Usage: $N {start|stop|force-stop|restart|force-reload|status}" >&2 exit 1 ;; esac exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/ovs-monitor-ipsec0000644000000000000000000000013212664352753020410 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.174815358 30 ctime=1456594660.017281422 openvswitch-2.5.0/debian/ovs-monitor-ipsec0000775000175000017500000004152712664352753022114 0ustar00jpettitjpettit00000000000000#! /usr/bin/env python # Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # A daemon to monitor attempts to create GRE-over-IPsec tunnels. # Uses racoon and setkey to support the configuration. Assumes that # OVS has complete control over IPsec configuration for the box. # xxx To-do: # - Doesn't actually check that Interface is connected to bridge # - If a certificate is badly formed, Racoon will refuse to start. We # should do a better job of verifying certificates are valid before # adding an interface to racoon.conf. import argparse import glob import os import subprocess import sys import ovs.dirs from ovs.db import error from ovs.db import types import ovs.util import ovs.daemon import ovs.db.idl import ovs.unixctl import ovs.unixctl.server import ovs.vlog vlog = ovs.vlog.Vlog("ovs-monitor-ipsec") root_prefix = '' # Prefix for absolute file names, for testing. SETKEY = "/usr/sbin/setkey" exiting = False def unixctl_exit(conn, unused_argv, unused_aux): global exiting exiting = True conn.reply(None) # Class to configure the racoon daemon, which handles IKE negotiation class Racoon: # Default locations for files conf_file = "/etc/racoon/racoon.conf" cert_dir = "/etc/racoon/certs" psk_file = "/etc/racoon/psk.txt" # Racoon configuration header we use for IKE conf_header = """# Configuration file generated by Open vSwitch # # Do not modify by hand! path pre_shared_key "%s"; path certificate "%s"; """ # Racoon configuration footer we use for IKE conf_footer = """sainfo anonymous { pfs_group 2; lifetime time 1 hour; encryption_algorithm aes; authentication_algorithm hmac_sha1, hmac_md5; compression_algorithm deflate; } """ # Certificate entry template. cert_entry = """remote %s { exchange_mode main; nat_traversal on; ike_frag on; certificate_type x509 "%s" "%s"; my_identifier asn1dn; peers_identifier asn1dn; peers_certfile x509 "%s"; verify_identifier on; proposal { encryption_algorithm aes; hash_algorithm sha1; authentication_method rsasig; dh_group 2; } } """ # Pre-shared key template. psk_entry = """remote %s { exchange_mode main; nat_traversal on; proposal { encryption_algorithm aes; hash_algorithm sha1; authentication_method pre_shared_key; dh_group 2; } } """ def __init__(self): self.psk_hosts = {} self.cert_hosts = {} if not os.path.isdir(root_prefix + self.cert_dir): os.mkdir(self.cert_dir) # Clean out stale peer certs from previous runs for ovs_cert in glob.glob("%s%s/ovs-*.pem" % (root_prefix, self.cert_dir)): try: os.remove(ovs_cert) except OSError: vlog.warn("couldn't remove %s" % ovs_cert) # Replace racoon's conf file with our template self.commit() def reload(self): exitcode = subprocess.call([root_prefix + "/etc/init.d/racoon", "reload"]) if exitcode != 0: # Racoon is finicky about its configuration file and will # refuse to start if it sees something it doesn't like # (e.g., a certificate file doesn't exist). Try restarting # the process before giving up. vlog.warn("attempting to restart racoon") exitcode = subprocess.call([root_prefix + "/etc/init.d/racoon", "restart"]) if exitcode != 0: vlog.warn("couldn't reload racoon") def commit(self): # Rewrite the Racoon configuration file conf_file = open(root_prefix + self.conf_file, 'w') conf_file.write(Racoon.conf_header % (self.psk_file, self.cert_dir)) for host, vals in self.cert_hosts.iteritems(): conf_file.write(Racoon.cert_entry % (host, vals["certificate"], vals["private_key"], vals["peer_cert_file"])) for host in self.psk_hosts: conf_file.write(Racoon.psk_entry % host) conf_file.write(Racoon.conf_footer) conf_file.close() # Rewrite the pre-shared keys file; it must only be readable by root. orig_umask = os.umask(0077) psk_file = open(root_prefix + Racoon.psk_file, 'w') os.umask(orig_umask) psk_file.write("# Generated by Open vSwitch...do not modify by hand!") psk_file.write("\n\n") for host, vals in self.psk_hosts.iteritems(): psk_file.write("%s %s\n" % (host, vals["psk"])) psk_file.close() self.reload() def _add_psk(self, host, psk): if host in self.cert_hosts: raise error.Error("host %s already defined for cert" % host) self.psk_hosts[host] = psk self.commit() def _verify_certs(self, vals): # Racoon will refuse to start if the certificate files don't # exist, so verify that they're there. if not os.path.isfile(root_prefix + vals["certificate"]): raise error.Error("'certificate' file does not exist: %s" % vals["certificate"]) elif not os.path.isfile(root_prefix + vals["private_key"]): raise error.Error("'private_key' file does not exist: %s" % vals["private_key"]) # Racoon won't start if a given certificate or private key isn't # valid. This is a weak test, but will detect the most flagrant # errors. if vals["peer_cert"].find("-----BEGIN CERTIFICATE-----") == -1: raise error.Error("'peer_cert' is not in valid PEM format") cert = open(root_prefix + vals["certificate"]).read() if cert.find("-----BEGIN CERTIFICATE-----") == -1: raise error.Error("'certificate' is not in valid PEM format") cert = open(root_prefix + vals["private_key"]).read() if cert.find("-----BEGIN RSA PRIVATE KEY-----") == -1: raise error.Error("'private_key' is not in valid PEM format") def _add_cert(self, host, vals): if host in self.psk_hosts: raise error.Error("host %s already defined for psk" % host) if vals["certificate"] == None: raise error.Error("'certificate' not defined for %s" % host) elif vals["private_key"] == None: # Assume the private key is stored in the same PEM file as # the certificate. We make a copy of "vals" so that we don't # modify the original "vals", which would cause the script # to constantly think that the configuration has changed # in the database. vals = vals.copy() vals["private_key"] = vals["certificate"] self._verify_certs(vals) # The peer's certificate comes to us in PEM format as a string. # Write that string to a file for Racoon to use. f = open(root_prefix + vals["peer_cert_file"], "w") f.write(vals["peer_cert"]) f.close() self.cert_hosts[host] = vals self.commit() def _del_cert(self, host): peer_cert_file = self.cert_hosts[host]["peer_cert_file"] del self.cert_hosts[host] self.commit() try: os.remove(root_prefix + peer_cert_file) except OSError: pass def add_entry(self, host, vals): if vals["peer_cert"]: self._add_cert(host, vals) elif vals["psk"]: self._add_psk(host, vals) def del_entry(self, host): if host in self.cert_hosts: self._del_cert(host) elif host in self.psk_hosts: del self.psk_hosts[host] self.commit() # Class to configure IPsec on a system using racoon for IKE and setkey # for maintaining the Security Association Database (SAD) and Security # Policy Database (SPD). Only policies for GRE are supported. class IPsec: def __init__(self): self.sad_flush() self.spd_flush() self.racoon = Racoon() self.entries = [] def call_setkey(self, cmds): try: p = subprocess.Popen([root_prefix + SETKEY, "-c"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) except: vlog.err("could not call %s%s" % (root_prefix, SETKEY)) sys.exit(1) # xxx It is safer to pass the string into the communicate() # xxx method, but it didn't work for slightly longer commands. # xxx An alternative may need to be found. p.stdin.write(cmds) return p.communicate()[0] def get_spi(self, local_ip, remote_ip, proto="esp"): # Run the setkey dump command to retrieve the SAD. Then, parse # the output looking for SPI buried in the output. Note that # multiple SAD entries can exist for the same "flow", since an # older entry could be in a "dying" state. spi_list = [] host_line = "%s %s" % (local_ip, remote_ip) results = self.call_setkey("dump ;\n").split("\n") for i in range(len(results)): if results[i].strip() == host_line: # The SPI is in the line following the host pair spi_line = results[i + 1] if (spi_line[1:4] == proto): spi = spi_line.split()[2] spi_list.append(spi.split('(')[1].rstrip(')')) return spi_list def sad_flush(self): self.call_setkey("flush;\n") def sad_del(self, local_ip, remote_ip): # To delete all SAD entries, we should be able to use setkey's # "deleteall" command. Unfortunately, it's fundamentally broken # on Linux and not documented as such. cmds = "" # Delete local_ip->remote_ip SAD entries spi_list = self.get_spi(local_ip, remote_ip) for spi in spi_list: cmds += "delete %s %s esp %s;\n" % (local_ip, remote_ip, spi) # Delete remote_ip->local_ip SAD entries spi_list = self.get_spi(remote_ip, local_ip) for spi in spi_list: cmds += "delete %s %s esp %s;\n" % (remote_ip, local_ip, spi) if cmds: self.call_setkey(cmds) def spd_flush(self): self.call_setkey("spdflush;\n") def spd_add(self, local_ip, remote_ip): cmds = ("spdadd %s %s gre -P out ipsec esp/transport//require;\n" % (local_ip, remote_ip)) cmds += ("spdadd %s %s gre -P in ipsec esp/transport//require;\n" % (remote_ip, local_ip)) self.call_setkey(cmds) def spd_del(self, local_ip, remote_ip): cmds = "spddelete %s %s gre -P out;\n" % (local_ip, remote_ip) cmds += "spddelete %s %s gre -P in;\n" % (remote_ip, local_ip) self.call_setkey(cmds) def add_entry(self, local_ip, remote_ip, vals): if remote_ip in self.entries: raise error.Error("host %s already configured for ipsec" % remote_ip) self.racoon.add_entry(remote_ip, vals) self.spd_add(local_ip, remote_ip) self.entries.append(remote_ip) def del_entry(self, local_ip, remote_ip): if remote_ip in self.entries: self.racoon.del_entry(remote_ip) self.spd_del(local_ip, remote_ip) self.sad_del(local_ip, remote_ip) self.entries.remove(remote_ip) def update_ipsec(ipsec, interfaces, new_interfaces): for name, vals in interfaces.iteritems(): if name not in new_interfaces: ipsec.del_entry(vals["local_ip"], vals["remote_ip"]) for name, vals in new_interfaces.iteritems(): orig_vals = interfaces.get(name) if orig_vals: # Configuration for this host already exists. Check if it's # changed. We use set difference, since we want to ignore # any local additions to "orig_vals" that we've made # (e.g. the "peer_cert_file" key). if set(vals.items()) - set(orig_vals.items()): ipsec.del_entry(vals["local_ip"], vals["remote_ip"]) else: continue try: ipsec.add_entry(vals["local_ip"], vals["remote_ip"], vals) except error.Error, msg: vlog.warn("skipping ipsec config for %s: %s" % (name, msg)) def get_ssl_cert(data): for ovs_rec in data["Open_vSwitch"].rows.itervalues(): if ovs_rec.ssl: ssl = ovs_rec.ssl[0] if ssl.certificate and ssl.private_key: return (ssl.certificate, ssl.private_key) return None def main(): parser = argparse.ArgumentParser() parser.add_argument("database", metavar="DATABASE", help="A socket on which ovsdb-server is listening.") parser.add_argument("--root-prefix", metavar="DIR", help="Use DIR as alternate root directory" " (for testing).") ovs.vlog.add_args(parser) ovs.daemon.add_args(parser) args = parser.parse_args() ovs.vlog.handle_args(args) ovs.daemon.handle_args(args) global root_prefix if args.root_prefix: root_prefix = args.root_prefix remote = args.database schema_helper = ovs.db.idl.SchemaHelper() schema_helper.register_columns("Interface", ["name", "type", "options"]) schema_helper.register_columns("Open_vSwitch", ["ssl"]) schema_helper.register_columns("SSL", ["certificate", "private_key"]) idl = ovs.db.idl.Idl(remote, schema_helper) ovs.daemon.daemonize() ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, None) error, unixctl_server = ovs.unixctl.server.UnixctlServer.create(None) if error: ovs.util.ovs_fatal(error, "could not create unixctl server", vlog) ipsec = IPsec() interfaces = {} seqno = idl.change_seqno # Sequence number when we last processed the db while True: unixctl_server.run() if exiting: break idl.run() if seqno == idl.change_seqno: poller = ovs.poller.Poller() unixctl_server.wait(poller) idl.wait(poller) poller.block() continue seqno = idl.change_seqno ssl_cert = get_ssl_cert(idl.tables) new_interfaces = {} for rec in idl.tables["Interface"].rows.itervalues(): if rec.type == "ipsec_gre": name = rec.name options = rec.options peer_cert_name = "ovs-%s.pem" % (options.get("remote_ip")) entry = { "remote_ip": options.get("remote_ip"), "local_ip": options.get("local_ip", "0.0.0.0/0"), "certificate": options.get("certificate"), "private_key": options.get("private_key"), "use_ssl_cert": options.get("use_ssl_cert"), "peer_cert": options.get("peer_cert"), "peer_cert_file": Racoon.cert_dir + "/" + peer_cert_name, "psk": options.get("psk")} if entry["peer_cert"] and entry["psk"]: vlog.warn("both 'peer_cert' and 'psk' defined for %s" % name) continue elif not entry["peer_cert"] and not entry["psk"]: vlog.warn("no 'peer_cert' or 'psk' defined for %s" % name) continue # The "use_ssl_cert" option is deprecated and will # likely go away in the near future. if entry["use_ssl_cert"] == "true": if not ssl_cert: vlog.warn("no valid SSL entry for %s" % name) continue entry["certificate"] = ssl_cert[0] entry["private_key"] = ssl_cert[1] new_interfaces[name] = entry if interfaces != new_interfaces: update_ipsec(ipsec, interfaces, new_interfaces) interfaces = new_interfaces unixctl_server.close() idl.close() if __name__ == '__main__': try: main() except SystemExit: # Let system.exit() calls complete normally raise except: vlog.exception("traceback") sys.exit(ovs.daemon.RESTART_EXIT_CODE) openvswitch-2.5.0/debian/PaxHeaders.69223/changelog0000644000000000000000000000013212664357124016737 xustar0030 mtime=1456594516.111228629 30 atime=1456594522.235486393 30 ctime=1456594659.961279067 openvswitch-2.5.0/debian/changelog0000664000175000017500000014234012664357124020433 0ustar00jpettitjpettit00000000000000openvswitch (2.5.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Dropped support for Python older than version 2.7. As a consequence, using Open vSwitch 2.5 or later on XenServer 6.5 or earlier (which have Python 2.4) requires first installing Python 2.7. - OpenFlow: * Group chaining (where one OpenFlow group triggers another) is now supported. * OpenFlow 1.4+ "importance" is now considered for flow eviction. * OpenFlow 1.4+ OFPTC_EVICTION is now implemented. * OpenFlow 1.4+ OFPTC_VACANCY_EVENTS is now implemented. * OpenFlow 1.4+ OFPMP_TABLE_DESC is now implemented. * Allow modifying the ICMPv4/ICMPv6 type and code fields. * OpenFlow 1.4+ OFPT_SET_ASYNC_CONFIG and OFPT_GET_ASYNC_CONFIG are now implemented. - ovs-ofctl: * New "out_group" keyword for OpenFlow 1.1+ matching on output group. - Tunnels: * Geneve tunnels can now match and set options and the OAM bit. * The nonstandard GRE64 tunnel extension has been dropped. - Support Multicast Listener Discovery (MLDv1 and MLDv2). - Add 'symmetric_l3l4' and 'symmetric_l3l4+udp' hash functions. - sFlow agent now reports tunnel and MPLS structures. - New 'check-system-userspace', 'check-kmod' and 'check-kernel' Makefile targets to run a new system testsuite. These tests can be run inside a Vagrant box. See INSTALL.md for details - Mark --syslog-target argument as deprecated. It will be removed in the next OVS release. - Added --user option to all daemons - Add support for connection tracking through the new "ct" action and "ct_state"/"ct_zone"/"ct_mark"/"ct_label" match fields. Only available on Linux kernels with the connection tracking module loaded. - Add experimental version of OVN. OVN, the Open Virtual Network, is a system to support virtual network abstraction. OVN complements the existing capabilities of OVS to add native support for virtual network abstractions, such as virtual L2 and L3 overlays and security groups. - RHEL packaging: * DPDK ports may now be created via network scripts (see README.RHEL). - DPDK: * Requires DPDK 2.2 * Added multiqueue support to vhost-user * Note: QEMU 2.5+ required for multiqueue support - SELinux: * Introduced SELinux policy package. -- Open vSwitch team Fri, 26 Feb 2016 17:23:21 -0700 openvswitch (2.4.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Flow table modifications are now atomic, meaning that each packet now sees a coherent version of the OpenFlow pipeline. For example, if a controller removes all flows with a single OpenFlow "flow_mod", no packet sees an intermediate version of the OpenFlow pipeline where only some of the flows have been deleted. - Added support for SFQ, FQ_CoDel and CoDel qdiscs. - Add bash command-line completion support for ovs-vsctl Please check utilities/ovs-command-compgen.INSTALL.md for how to use. - The MAC learning feature now includes per-port fairness to mitigate MAC flooding attacks. - New support for a "conjunctive match" OpenFlow extension, which allows constructing OpenFlow matches of the form "field1 in {a,b,c...} AND field2 in {d,e,f...}" and generalizations. For details, see documentation for the "conjunction" action in ovs-ofctl(8). - Add bash command-line completion support for ovs-appctl/ovs-dpctl/ ovs-ofctl/ovsdb-tool commands. Please check utilities/ovs-command-compgen.INSTALL.md for how to use. - The "learn" action supports a new flag "delete_learned" that causes the learned flows to be deleted when the flow with the "learn" action is deleted. - Basic support for the Geneve tunneling protocol. It is not yet possible to generate or match options. This is planned for a future release. The protocol is documented at http://tools.ietf.org/html/draft-gross-geneve-00 - The OVS database now reports controller rate limiting statistics. - sflow now exports information about LACP-based bonds, port names, and OpenFlow port numbers, as well as datapath performance counters. - ovs-dpctl functionality is now available for datapaths integrated into ovs-vswitchd, via ovs-appctl. Some existing ovs-appctl commands are now redundant and will be removed in a future release. See ovs-vswitchd(8) for details. - OpenFlow: * OpenFlow 1.4 bundles are now supported for flow mods and port mods. For flow mods, both 'atomic' and 'ordered' bundle flags are trivially supported, as all bundled messages are executed in the order they were added and all flow table modifications are now atomic to the datapath. Port mods may not appear in atomic bundles, as port status modifications are not atomic. * IPv6 flow label and neighbor discovery fields are now modifiable. * OpenFlow 1.5 extended registers are now supported. * The OpenFlow 1.5 actset_output field is now supported. * OpenFlow 1.5 Copy-Field action is now supported. * OpenFlow 1.5 masked Set-Field action is now supported. * OpenFlow 1.3+ table features requests are now supported (read-only). * Nicira extension "move" actions may now be included in action sets. * "resubmit" actions may now be included in action sets. The resubmit is executed last, and only if the action set has no "output" or "group" action. * OpenFlow 1.4+ flow "importance" is now maintained in the flow table. * A new Netronome extension to OpenFlow 1.5+ allows control over the fields hashed for OpenFlow select groups. See "selection_method" and related options in ovs-ofctl(8) for details. - ovs-ofctl has a new '--bundle' option that makes the flow mod commands ('add-flow', 'add-flows', 'mod-flows', 'del-flows', and 'replace-flows') use an OpenFlow 1.4 bundle to operate the modifications as a single atomic transaction. If any of the flow mods in a transaction fail, none of them are executed. All flow mods in a bundle appear to datapath lookups simultaneously. - ovs-ofctl 'add-flow' and 'add-flows' commands now accept arbitrary flow mods as an input by allowing the flow specification to start with an explicit 'add', 'modify', 'modify_strict', 'delete', or 'delete_strict' keyword. A missing keyword is treated as 'add', so this is fully backwards compatible. With the new '--bundle' option all the flow mods are executed as a single atomic transaction using an OpenFlow 1.4 bundle. - ovs-pki: Changed message digest algorithm from MD5 to SHA-1 because MD5 is no longer secure and some operating systems have started to disable it in OpenSSL. - ovsdb-server: New OVSDB protocol extension allows inequality tests on "optional scalar" columns. See ovsdb-server(1) for details. - ovs-vsctl now permits immutable columns in a new row to be modified in the same transaction that creates the row. - test-controller has been renamed ovs-testcontroller at request of users who find it useful for testing basic OpenFlow setups. It is still not a necessary or desirable part of most Open vSwitch deployments. - Support for travis-ci.org based continuous integration builds has been added. Build failures are reported to build@openvswitch.org. See INSTALL.md file for additional details. - Support for the Rapid Spanning Tree Protocol (IEEE 802.1D-2004). The implementation has been tested successfully against the Ixia Automated Network Validation Library (ANVL). - Stats are no longer updated on fake bond interface. - Keep active bond slave selection across OVS restart. - A simple wrapper script, 'ovs-docker', to integrate OVS with Docker containers. If and when there is a native integration of Open vSwitch with Docker, the wrapper script will be retired. - Added support for DPDK Tunneling. VXLAN, GRE, and Geneve are supported protocols. This is generic tunneling mechanism for userspace datapath. - Support for multicast snooping (IGMPv1, IGMPv2 and IGMPv3) - Support for Linux kernels up to 4.0.x - The documentation now use the term 'destination' to mean one of syslog, console or file for vlog logging instead of the previously used term 'facility'. - Support for VXLAN Group Policy extension - Initial support for the IETF Auto-Attach SPBM draft standard. This contains rudimentary support for the LLDP protocol as needed for Auto-Attach. - The default OpenFlow and OVSDB ports are now the IANA-assigned numbers. OpenFlow is 6653 and OVSDB is 6640. - Support for DPDK vHost. - Support for outer UDP checksums in Geneve and VXLAN. - The kernel vports with dependencies are no longer part of the overall openvswitch.ko but built and loaded automatically as individual kernel modules (vport-*.ko). - Support for STT tunneling. - Support to configure method (--syslog-method argument) that determines how daemons will talk with syslog. - Support for "ovs-appctl vlog/list-pattern" command that lets to query logging message format for each destination. - GRE64 and ipsec_gre64 tunnel protocol is deprecated and will be removed from OVS v2.5 release. * The openvswitch-testcontroller package is new. It reintroduces the simple OpenFlow controller that was packaged with Open vSwitch prior to version 2.1, at request of users who find it useful for testing basic OpenFlow setups. It is still not a necessary or desirable part of most Open vSwitch deployments. -- Open vSwitch team Thu, 20 Aug 2015 17:23:43 -0700 openvswitch (2.3.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - OpenFlow 1.1, 1.2, and 1.3 are now enabled by default in ovs-vswitchd. - Linux kernel datapath now has an exact match cache optimizing the flow matching process. - Datapath flows now have partially wildcarded tranport port field matches. This reduces userspace upcalls, but increases the number of different masks in the datapath. The kernel datapath exact match cache removes the overhead of matching the incoming packets with the larger number of masks, but when paired with an older kernel module, some workloads may perform worse with the new userspace. -- Open vSwitch team Thu, 14 Aug 2014 11:03:32 -0700 openvswitch (2.2.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Internal ports are no longer brought up by default, because it should be an administrator task to bring up devices as they are configured properly. - ovs-vsctl now reports when ovs-vswitchd fails to create a new port or bridge. - The "ovsdbmonitor" graphical tool has been removed, because it was poorly maintained and not widely used. - New "check-ryu" Makefile target for running Ryu tests for OpenFlow controllers against Open vSwitch. See INSTALL for details. - Added IPFIX support for SCTP flows and templates for ICMPv4/v6 flows. - Upon the receipt of a SIGHUP signal, ovs-vswitchd no longer reopens its log file (it will terminate instead). Please use 'ovs-appctl vlog/reopen' instead. - Support for Linux kernels up to 3.14. From Kernel 3.12 onwards OVS uses tunnel API for GRE and VXLAN. - Added DPDK support. - Added support for custom vlog patterns in Python -- Open vSwitch team Wed, 19 Mar 2014 16:08:38 -0700 openvswitch (2.1.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Address prefix tracking support for flow tables. New columns "prefixes" in OVS-DB table "Flow_Table" controls which packet header fields are used for address prefix tracking. Prefix tracking allows the classifier to skip rules with longer than necessary prefixes, resulting in better wildcarding for datapath flows. Default configuration is to not use any fields for prefix tracking. However, if any flow tables contain both exact matches and masked matches for IP address fields, OVS performance may be increased by using this feature. * As of now, the fields for which prefix lookup can be enabled are: 'tun_id', 'tun_src', 'tun_dst', 'nw_src', 'nw_dst' (or aliases 'ip_src' and 'ip_dst'), 'ipv6_src', and 'ipv6_dst'. (Using this feature for 'tun_id' would only make sense if the tunnel IDs have prefix structure similar to IP addresses.) * There is a maximum number of fields that can be enabled for any one flow table. Currently this limit is 3. * Examples: $ ovs-vsctl set Bridge br0 flow_tables:0=@N1 -- \ --id=@N1 create Flow_Table name=table0 $ ovs-vsctl set Bridge br0 flow_tables:1=@N1 -- \ --id=@N1 create Flow_Table name=table1 $ ovs-vsctl set Flow_Table table0 prefixes=ip_dst,ip_src $ ovs-vsctl set Flow_Table table1 prefixes=[] - TCP flags matching: OVS now supports matching of TCP flags. This has an adverse performance impact when using OVS userspace 1.10 or older (no megaflows support) together with the new OVS kernel module. It is recommended that the kernel and userspace modules both are upgraded at the same time. - The default OpenFlow and OVSDB ports will change to IANA-assigned numbers in a future release. Consider updating your installations to specify port numbers instead of using the defaults. - OpenFlow: * The OpenFlow 1.1+ "Write-Actions" instruction is now supported. * OVS limits the OpenFlow port numbers it assigns to port 32767 and below, leaving port numbers above that range free for assignment by the controller. * ovs-vswitchd now honors changes to the "ofport_request" column in the Interface table by changing the port's OpenFlow port number. - ovs-vswitchd.conf.db.5 man page will contain graphviz/dot diagram only if graphviz package was installed at the build time. - Support for Linux kernels up to 3.11 - ovs-dpctl: The "show" command also displays mega flow mask stats. - ovs-ofctl: * New command "ofp-parse-pcap" to dump OpenFlow from PCAP files. - ovs-controller has been renamed test-controller. It is no longer packaged or installed by default, because too many users assumed incorrectly that ovs-controller was a necessary or desirable part of an Open vSwitch deployment. - Added vlog option to export to a UDP syslog sink. - ovsdb-client: * The "monitor" command can now monitor all tables in a database, instead of being limited to a single table. - The flow-eviction-threshold has been replaced by the flow-limit which is a hard limit on the number of flows in the datapath. It defaults to 200,000 flows. OVS automatically adjusts this number depending on network conditions. * The openvswitch-controller package has been removed, because too many users assumed incorrectly that ovs-controller was a necessary or desirable part of an Open vSwitch deployment. -- Open vSwitch team Wed, 19 Mar 2014 16:08:38 -0700 openvswitch (2.0.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - The ovs-vswitchd process is no longer single-threaded. Multiple threads are now used to handle flow set up and asynchronous logging. - OpenFlow: * Experimental support for OpenFlow 1.1 (in addition to 1.2 and 1.3, which had experimental support in 1.10). * New support for matching outer source and destination IP address of tunneled packets, for tunnel ports configured with the newly added "remote_ip=flow" and "local_ip=flow" options. * Support for matching on metadata 'pkt_mark' for interacting with other system components. On Linux this corresponds to the skb mark. * Support matching, rewriting SCTP ports - The Interface table in the database has a new "ifindex" column to report the interface's OS-assigned ifindex. - New "check-oftest" Makefile target for running OFTest against Open vSwitch. See README-OFTest for details. - The flow eviction threshold has been moved to the Open_vSwitch table. - Database names are now mandatory when specifying ovsdb-server options through database paths (e.g. Private key option with the database name should look like "--private-key=db:Open_vSwitch,SSL,private_key"). - Added ovs-dev.py, a utility script helpful for Open vSwitch developers. - Support for Linux kernels up to 3.10 - ovs-ofctl: * New "ofp-parse" for printing OpenFlow messages read from a file. - Added configurable flow caching support to IPFIX exporter. - Dropped support for Linux pre-2.6.32. - Log file timestamps and ovsdb commit timestamps are now reported with millisecond resolution. (Previous versions only reported whole seconds.) -- Open vSwitch team Tue, 15 Oct 2013 15:03:42 -0700 openvswitch (1.11.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Support for megaflows, which allows wildcarding in the kernel (and any dpif implementation that supports wildcards). Depending on the flow table and switch configuration, flow set up rates are close to the Linux bridge. - The "tutorial" directory contains a new tutorial for some advanced Open vSwitch features. - Stable bond mode has been removed. - The autopath action has been removed. - New support for the data encapsulation format of the LISP tunnel protocol (RFC 6830). An external control plane or manual flow setup is required for EID-to-RLOC mapping. - OpenFlow: * The "dec_mpls_ttl" and "set_mpls_ttl" actions from OpenFlow 1.1 and later are now implemented. * New "stack" extension for use in actions, to push and pop from NXM fields. * The "load" and "set_field" actions can now modify the "in_port". (This allows one to enable output to a flow's input port by setting the in_port to some unused value, such as OFPP_NONE.) - ovs-dpctl: * New debugging commands "add-flow", "mod-flow", "del-flow". - In dpif-based bridges, cache action translations, which can improve flow set up performance by 80% with a complicated flow table. - New syslog format, prefixed with "ovs|", to be easier to filter. - RHEL: Removes the default firewall rule that allowed GRE traffic to pass through. Any users that relied on this automatic firewall hole will have to manually configure it. The ovs-ctl(8) manpage documents the "enable-protocol" command that can be used as an alternative. - New CFM demand mode which uses data traffic to indicate interface liveness. -- Open vSwitch team Wed, 28 Aug 2013 14:31:44 -0700 openvswitch (1.10.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Bridge compatibility support has been removed. Any uses that rely on ovs-brcompatd will have to stick with Open vSwitch 1.9.x or adapt to native Open vSwitch support (e.g. use ovs-vsctl instead of brctl). - The maximum size of the MAC learning table is now configurable. - With the Linux datapath, packets for new flows are now queued separately on a per-port basis, so it should no longer be possible for a large number of new flows arriving on one port to prevent new flows from being processed on other ports. - Many "ovs-vsctl" database commands now accept an --if-exists option. Please refer to the ovs-vsctl manpage for details. - OpenFlow: - Experimental support for newer versions of OpenFlow. See the "What versions of OpenFlow does Open vSwitch support?" question in the FAQ for more details. - The OpenFlow "dp_desc" may now be configured by setting the value of other-config:dp-desc in the Bridge table. - It is possible to request the OpenFlow port number with the "ofport_request" column in the Interface table. - Tunneling: - New support for the VXLAN tunnel protocol (see the IETF draft here: http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-03). - Tunneling requires the version of the kernel module paired with Open vSwitch 1.9.0 or later. - Inheritance of the Don't Fragment bit in IP tunnels (df_inherit) is no longer supported. - Path MTU discovery is no longer supported. - ovs-dpctl: - The "dump-flows" and "del-flows" no longer require an argument if only one datapath exists. - ovs-appctl: - New "vlog/disable-rate-limit" and "vlog/enable-rate-limit" commands available allow control over logging rate limits. - New "dpif/dump-dps", "dpif/show", and "dpif/dump-flows" command that mimic the equivalent ovs-dpctl commands. - The ofproto library is now responsible for assigning OpenFlow port numbers. An ofproto implementation should assign them when port_construct() is called. - All dpif-based bridges of a particular type share a common datapath called "ovs-", e.g. "ovs-system". The ovs-dpctl commands will now return information on that shared datapath. To get the equivalent bridge-specific information, use the new "ovs-appctl dpif/*" commands. - Backward-incompatible changes: - Earlier Open vSwitch versions treated ANY as a wildcard in flow syntax. OpenFlow 1.1 adds a port named ANY, which introduces a conflict. ANY was rarely used in flow syntax, so we chose to retire that meaning of ANY in favor of the OpenFlow 1.1 meaning. - Patch ports no longer require kernel support, so they now work with FreeBSD and the kernel module built into Linux 3.3 and later. -- Open vSwitch team Wed, 01 May 2013 14:28:21 -0700 openvswitch (1.9.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Datapath: - Support for ipv6 set action. - SKB mark matching and setting. - support for Linux kernels up to 3.8 - FreeBSD is now a supported platform, thanks to code contributions from Gaetano Catalli, Ed Maste, and Giuseppe Lettieri. - ovs-bugtool: New --ovs option to report only OVS related information. - New %t and %T log escapes to identify the subprogram within a cooperating group of processes or threads that emitted a log message. The default log patterns now include this information. - OpenFlow: - Allow bitwise masking for SHA and THA fields in ARP, SLL and TLL fields in IPv6 neighbor discovery messages, and IPv6 flow label. - Adds support for writing to the metadata field for a flow. - Tunneling: - The tunneling code no longer assumes input and output keys are symmetric. If they are not, PMTUD needs to be disabled for tunneling to work. Note this only applies to flow-based keys. - New support for a nonstandard form of GRE that supports a 64-bit key. - Tunnel Path MTU Discovery default value was set to 'disabled'. This feature is deprecated and will be removed soon. - Tunnel header caching removed. - ovs-ofctl: - Commands and actions that accept port numbers now also accept keywords that represent those ports (such as LOCAL, NONE, and ALL). This is also the recommended way to specify these ports, for compatibility with OpenFlow 1.1 and later (which use the OpenFlow 1.0 numbers for these ports for different purposes). - ovs-dpctl: - Support requesting the port number with the "port_no" option in the "add-if" command. - ovs-pki: The "online PKI" features have been removed, along with the ovs-pki-cgi program that facilitated it, because of some alarmist insecurity claims. We do not believe that these claims are true, but because we do not know of any users for this feature it seems better on balance to remove it. (The ovs-pki-cgi program was not included in distribution packaging.) - ovsdb-server now enforces the immutability of immutable columns. This was not enforced in earlier versions due to an oversight. - The following features are now deprecated. They will be removed no earlier than February 2013. Please email dev@openvswitch.org with concerns. - Bridge compatibility. - Stable bond mode. - The autopath action. - Interface type "null". - Numeric values for reserved ports (see "ovs-ofctl" note above). - Tunnel Path MTU Discovery. - CAPWAP tunnel support. - The data in the RARP packets can now be matched in the same way as the data in ARP packets. -- Open vSwitch team Tue, 26 Feb 2013 11:23:19 -0700 openvswitch (1.8.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version *** Internal only release *** - New FAQ. Please send updates and additions! - Authors of controllers, please read the new section titled "Action Reproduction" in DESIGN, which describes an Open vSwitch change in behavior in corner cases that may affect some controllers. - ovs-l3ping: - A new test utility that can create L3 tunnel between two Open vSwitches and detect connectivity issues. - ovs-ofctl: - New --sort and --rsort options for "dump-flows" command. - "mod-port" command can now control all OpenFlow config flags. - OpenFlow: - Allow general bitwise masking for IPv4 and IPv6 addresses in IPv4, IPv6, and ARP packets. (Previously, only CIDR masks were allowed.) - Allow support for arbitrary Ethernet masks. (Previously, only the multicast bit in the destination address could be individually masked.) - New field OXM_OF_METADATA, to align with OpenFlow 1.1. - The OFPST_QUEUE request now reports an error if a specified port or queue does not exist, or for requests for a specific queue on all ports, if the specified queue does not exist on any port. (Previous versions generally reported an empty set of results.) - New "flow monitor" feature to allow controllers to be notified of flow table changes as they happen. - Additional protocols are not mirrored and dropped when forward-bpdu is false. For a full list, see the ovs-vswitchd.conf.db man page. - Open vSwitch now sends RARP packets in situations where it previously sent a custom protocol, making it consistent with behavior of QEMU and VMware. - All Open vSwitch programs and log files now show timestamps in UTC, instead the local timezone, by default. -- Open vSwitch team Mon, 16 Jul 2012 16:44:52 +0900 openvswitch (1.7.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - kernel modules are renamed. openvswitch_mod.ko is now openvswitch.ko and brcompat_mod.ko is now brcompat.ko. - Increased the number of NXM registers to 8. - Added ability to configure dscp setting for manager and controller connections. By default, these connections have a DSCP value of Internetwork Control (0xc0). - Added the granular link health statistics, 'cfm_health', to an interface. - OpenFlow: - Added support to mask nd_target for ICMPv6 neighbor discovery flows. - Added support for OpenFlow 1.3 port description (OFPMP_PORT_DESC) multipart messages. - ovs-ofctl: - Added the "dump-ports-desc" command to retrieve port information using the new port description multipart messages. - ovs-test: - Added support for spawning ovs-test server from the client. - Now ovs-test is able to automatically create test bridges and ports. - "ovs-dpctl dump-flows" now prints observed TCP flags in TCP flows. - Tripled flow setup performance. - The "coverage/log" command previously available through ovs-appctl has been replaced by "coverage/show". The new command replies with coverage counter values, instead of logging them. -- Open vSwitch team Mon, 30 Jul 2012 17:23:57 +0900 openvswitch (1.6.1-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Allow OFPP_CONTROLLER as the in_port for packet-out messages. -- Open vSwitch team Mon, 25 Jun 2012 13:52:17 +0900 openvswitch (1.6.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - bonding - LACP bonds no longer fall back to balance-slb when negotiations fail. Instead they drop traffic. - The default bond_mode changed from SLB to active-backup, to protect unsuspecting users from the significant risks of SLB bonds (which are documented in vswitchd/INTERNALS). - Load balancing can be disabled by setting the bond-rebalance-interval to zero. - OpenFlow: - Added support for bitwise matching on TCP and UDP ports. See ovs-ofctl(8) for more information. - NXM flow dumps now include times elapsed toward idle and hard timeouts. - Added an OpenFlow extension NXT_SET_ASYNC_CONFIG that allows controllers more precise control over which OpenFlow messages they receive asynchronously. - New "fin_timeout" action. - Added "fin_timeout" support to "learn" action. - The default MAC learning timeout has been increased from 60 seconds to 300 seconds. The MAC learning timeout is now configurable. - When QoS settings for an interface do not configure a default queue (queue 0), Open vSwitch now uses a default configuration for that queue, instead of dropping all packets as in previous versions. - Logging to console and file will have UTC timestamp as a default for all the daemons. An example of the default format is 2012-01-27T16:35:17Z. ovs-appctl can be used to change the default format as before. - New support for limiting the number of flows in an OpenFlow flow table, with configurable policy for evicting flows upon overflow. See the Flow_Table table in ovs-vswitch.conf.db(5) for more information. - New "enable-async-messages" column in the Controller table. If set to false, OpenFlow connections to the controller will initially have all asynchronous messages disabled, overriding normal OpenFlow behavior. - ofproto-provider interface: - "struct rule" has a new member "used" that ofproto implementations should maintain by updating with ofproto_rule_update_used(). - ovsdb-client: - The new option --timestamp causes the "monitor" command to print a timestamp with every update. - CFM module CCM broadcasts can now be tagged with an 802.1p priority. -- Open vSwitch team Fri, 24 Feb 2012 11:12:48 +0900 openvswitch (1.5.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - OpenFlow: - Added support for querying, modifying, and deleting flows based on flow cookie when using NXM. - Added new NXM_PACKET_IN format. - ovs-ofctl: - Added daemonization support to the monitor and snoop commands. - ovs-vsctl: - The "find" command supports new set relational operators {=}, {!=}, {<}, {>}, {<=}, and {>=}. - ovsdb-tool now uses the typical database and schema installation directories as defaults. -- Open vSwitch team Fri, 01 June 2012 13:06:00 +0900 openvswitch (1.4.0+git20120426-1) unstable; urgency=low * New upstream release fixing the following bugs: o Broken log rotation. o Use-after-free error when ports disappear. o Minor memory leaks. o Testsuite failures on big-endian architectures. -- Ben Pfaff Thu, 26 Apr 2012 13:46:55 -0700 openvswitch (1.4.0+git20120321-1) unstable; urgency=low * New upstream version including: o Features: - ovs-vsctl: Allow "fake bridges" to be created for VLAN 0. - vswitchd: Make the MAC entry aging time configurable. - mac-learning: Increase MAC learning timeout to 300 seconds. o Bug fixes: - netdev-linux: Fix use-after-free when netdev_dump_queues() deletes queues. - netlink-socket: Increase Netlink socket receive buffer size. - ofproto: Fix code that keeps track of MTU. - ovs-monitor-ipsec: Detect correctly IPSEC configuration changes - bond: Incorrectly reported an error in appctl. - socket-util: Unlink Unix domain sockets that bind but fail to connect. - bridge: Remove unwanted ports at time of ofproto creation. - dpif-linux: Make dpif_linux_port_query_by_name() query only one datapath. - ofproto-dpif: Cleanup STP on ports when disabled on their bridge. - configure: Try to extract kernel source directory from build Makefile. - vswitchd: Always configure a default queue for QoS. - ofproto-dpif: Don't output to in_port even if in_port is OFPP_LOCAL. - sflow_agent: Use snprintf() in place of sprintf(). o Packaging: - Move PKI directory to FHS-compliant location. Closes: #661090. Thanks to Andreas Beckmann for reporting this bug. - Use a different way to avoid failing install without kernel module. - Avoid unit test failure when doing "unofficial" builds. - Bump standards-version to 3.9.3. - Remove some useless files from the dkms package. - Clean .pyc files in "clean" target. - Remove po-debconf build dependency. - Build-depend on python-all to pull in all Python versions. - Add missing ${python:Depends} to openvswitch-test package. - Improve long descriptions so as to better describe the packages. - Bump debhelper compat level to 8 and make build-depends consistent. - Fix exit status of openvswitch-switch init script "status" command. - Use provided kernel source dir instead of host kernel version. - Do not run "make" if "configure" fails during DKMS build. - Look in /lib/modules instead of /usr/src for DKMS kernel sources. - Fix dependencies for openvswitch-datapath-dkms package. - Don't install Python modules for obsolete Python versions. - Add dependency on ${misc:Depends} to openvswitch-test o Documentation improvements: - ovsdb-doc: Use minus sign in negative numbers in nroff output. - ovsdb-doc: Convert '-' preceding a number as a minus sign, not a hyphen. - ovsdb-doc: Put NAME section into generated manpage. - Fix typo in manpage. - vswitchd: Document behavior of 802.1p priorities with VLAN splinters. - netdev: Fix typo in error message. - INSTALL.Linux: minor typo * Many thanks to Thomas Goirand for contributing many of the packaging fixes listed above. * This version fixes most of the lintian errors described in bug #663051, but a few remain, so this upload does not close that bug. I believe that this upload should be suitable for downgrading that bug's severity. -- Ben Pfaff Wed, 21 Mar 2012 10:00:28 -0700 openvswitch (1.4.0-2+nmu1) unstable; urgency=low * Non maintainer upload. * Removes all patches in debian/patches, because they are patching stuff inconditionally in debian/*, and this should be applied by default. * Uses the correct ${kernel_source_dir} in debian/dkms.conf.in, so that the kernel module builds as expected (Closes: #659685). -- Thomas Goirand Thu, 08 Mar 2012 08:46:24 +0000 openvswitch (1.4.0-2) unstable; urgency=low * Use explicit DKMS variable for kernel source directory - 0001-debian-Fix-dependencies-for-openvswitch-datapath-dkm.patch - 0002-debian-Look-in-lib-modules-instead-of-usr-src-for-DK.patch - 0001-debian-Use-provided-kernel-source-dir.patch - 0001-debian-Do-not-run-make-if-configure-fails-during-DKM.patch - (closes: #659685) * Don't install Python modules for obsolete Python versions - 0001-debian-Don-t-install-Python-modules-for-obsolete-Pyt.patch -- Simon Horman Tue, 14 Feb 2012 11:43:13 +0900 openvswitch (1.4.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Compatible with Open vSwitch kernel module included in Linux 3.3. - New "VLAN splinters" feature to work around buggy device drivers in old Linux versions. (This feature is deprecated. When broken device drivers are no longer in widespread use, we will delete this feature.) See ovs-vswitchd.conf.db(5) for more information. - OpenFlow: - Added ability to match on IPv6 flow label through NXM. - Added ability to match on ECN bits in IPv4 and IPv6 through NXM. - Added ability to match on TTL in IPv4 and IPv6 through NXM. - Added ability to modify ECN bits in IPv4. - Added ability to modify TTL in IPv4. - ovs-vswitchd: - Don't require the "normal" action to use mirrors. Traffic will now be properly mirrored for any flows, regardless of their actions. - Track packet and byte statistics sent on mirrors. - ovs-appctl: - New "fdb/flush" command to flush bridge's MAC learning table. - ovs-test: - A new distributed testing tool that allows one to diagnose performance and connectivity issues. This tool currently is not included in RH or Xen packages. - RHEL packaging now supports integration with Red Hat network scripts. - Debian: Depend on python (>= 2.7) | python-argparse instead of python-argparse to avoid pulling in python2.6 (closes: #653645) -- Open vSwitch team Mon, 30 Jan 2012 23:36:00 +0000 openvswitch (1.3.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - OpenFlow: - Added an OpenFlow extension which allows the "output" action to accept NXM fields. - Added an OpenFlow extension for flexible learning. - Bumped number of NXM registers from four to five. - ovs-appctl: - New "version" command to determine version of running daemon. - If no argument is provided for "cfm/show", displays detailed information about all interfaces with CFM enabled. - If no argument is provided for "lacp/show", displays detailed information about all ports with LACP enabled. - ovs-vswitchd: - The software switch now supports 255 OpenFlow tables, instead of just one. By default, only table 0 is consulted, but the new NXAST_RESUBMIT_TABLE action can look up in additional tables. Tables 128 and above are reserved for use by the switch itself; please use only tables 0 through 127. - Add support for 802.1D spanning tree (STP). - Fragment handling extensions: - New OFPC_FRAG_NX_MATCH fragment handling mode, in which L4 fields are made available for matching in fragments with offset 0. - New NXM_NX_IP_FRAG match field for matching IP fragments (usable via "ip_frag" in ovs-ofctl). - New ovs-ofctl "get-frags" and "set-frags" commands to get and set fragment handling policy. - CAPWAP tunneling now supports an extension to transport a 64-key. By default it remains compatible with the old version and other standards-based implementations. - Flow setups are now processed in a round-robin manner across ports to prevent any single client from monopolizing the CPU and conducting a denial of service attack. - Added support for native VLAN tagging. A new "vlan_mode" parameter can be set for "port". Possible values: "access", "trunk", "native-tagged" and "native-untagged". - test-openflowd has been removed. Please use ovs-vswitchd instead. -- Open vSwitch team Mon, 09 Dec 2011 23:36:00 +0000 openvswitch (1.2.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - New "ofproto" abstraction layer to ease porting to hardware switching ASICs. - Packaging for Red Hat Enterprise Linux 5.6 and 6.0. - Datapath support for Linux kernels up to 3.0. - OpenFlow: - New "bundle" and "bundle_load" action extensions. - Database: - Implement table unique constraints. - Support cooperative locking between callers. - ovs-dpctl: - New "-s" option for "show" command prints packet and byte counters for each port. - ovs-ofctl: - New "--readd" option for "replace-flows". - ovs-vsctl: - New "show" command to print an overview of configuration. - New "comment" command to add remark that explains intentions. - ovs-brcompatd has been rewritten to fix long-standing bugs. - ovs-openflowd has been renamed test-openflowd and moved into the tests directory. Its presence confused too many users. Please use ovs-vswitchd instead. - New ovs-benchmark utility to test flow setup performance. - A new log level "off" has been added. Configuring a log facility "off" prevents any messages from being logged to it. Previously, "emer" was effectively "off" because no messages were ever logged at level "emer". Now, errors that cause a process to exit are logged at "emer" level. - "configure" option --with-l26 has been renamed --with-linux, and --with-l26-source has been renamed --with-linux-source. The old names will be removed after the next release, so please update your scripts. - The "-2.6" suffix has been dropped from the datapath/linux-2.6 and datapath/linux-2.6/compat-2.6 directories. - Feature removals: - Dropped support for "tun_id_from_cookie" OpenFlow extension. Please use the extensible match extensions instead. - Removed the Maintenance_Point and Monitor tables in an effort to simplify 802.1ag configuration. - Performance and scalability improvements - Bug fixes -- Open vSwitch team Wed, 03 Aug 2011 14:43:00 +0000 openvswitch (1.1.1-1) unstable; urgency=low [ Open vSwitch team ] * Bug fixes. [ Simon Horman ] * docs: Suppress warning marcro DD not defined (upstream commit 58f870d0) * debian: Make openvswitch depend on Python (upstream commit aa41cb61) * debian: Don't begin openvswitch-pki description with article. (upstream commit bc6bb66) * Debian: Add ${misc:Depends} dependency to python-openvswitch * Debian: Update standards version from 3.9.1 to 3.9.2 * Debian: ${source:Version} dependency on python openvswitch * Debian: ${source:Version} dependency for python openvswitch * Switch to dpkg-source 3.0 (quilt) format - For local non-debian/ patches (above) -- Simon Horman Wed, 15 Jun 2011 10:46:15 +0900 openvswitch (1.1.0-1) unstable; urgency=low [ Open vSwitch team ] * New upstream version - Ability to define policies over IPv6 - LACP - 802.1ag CCM - Support for extensible match extensions to OpenFlow - QoS: - Support for HFSC qdisc. - Queue used by in-band control can now be configured. - Kernel: - Kernel<->userspace interface has been reworked and should be close to a stable ABI now. - "Port group" concept has been dropped. - GRE over IPSEC tunnels - Bonding: - New active backup bonding mode. - New L4 hashing support when LACP is enabled. - Source MAC hash now includes VLAN field also. - miimon support. - Greatly improved handling of large flow tables - ovs-dpctl: - "show" command now prints full vport configuration. - "dump-groups" command removed since kernel support for port groups was dropped. - ovs-vsctl: - New commands for working with the new Managers table. - "list" command enhanced with new formatting options and --columns option. - "get" command now accepts new --id option. - New "find" command. - ovs-ofctl: - New "queue-stats" command for printing queue stats. - New commands "replace-flows" and "diff-flows". - Commands to add and remove flows can now read from files. - New --flow-format option to enable or disable NXM. - New --more option to increase OpenFlow message verbosity. - Removed "tun-cookie" command, which is no longer useful. - ovs-controller enhancements for testing various features. - New ovs-vlan-test command for testing for Linux kernel driver VLAN bugs. New ovs-vlan-bug-workaround command for enabling and disabling a workaround for these driver bugs. - OpenFlow support: - "Resubmit" actions now update flow statistics. - New "register" extension for use in matching and actions, via NXM. - New "multipath" experimental action extension. - New support for matching multicast Ethernet frames, via NXM. - New extension for OpenFlow vendor error codes. - New extension to set the QoS output queue without actually sending to an output port. - Open vSwitch now reports a single flow table, instead of separate hash and wildcard tables. This better models the current implementation. - New experimental "note" action. - New "ofproto/trace" ovs-appctl command and associated utilities to ease debugging complex flow tables. - Database: - Schema documentation now includes an entity-relationship diagram. - The database is now garbage collected. In most tables, unreferenced rows will be deleted automatically. - Many tables now include statistics updated periodically by ovs-vswitchd or ovsdb-server. - Every table now has an "external-ids" column for use by OVS integrators. - There is no default controller anymore. Each bridge must have its controller individually specified. - The "fail-mode" is now a property of a Bridge instead of a Controller. - New versioning and checksum features. - New Managers table and manager_options column in Open_vSwitch table for specifying managers. The old "managers" column in the Open_vSwitch table has been removed. - Many "name" columns are now immutable. - Feature removals: - Dropped support for XenServer pre-5.6.100. - Dropped support for Linux pre-2.6.18. - Dropped controller discovery support. - Dropped "ovs-ofctl status" and the OpenFlow extension that it used. Statistics reporting in the database is a rough equivalent. - Dropped the "corekeeper" package (now separate, at http://openvswitch.org/cgi-bin/gitweb.cgi?p=corekeeper). - Performance and scalability improvements - Bug fixes [ Simon Horman ] * Add the following fixes from upstream branch-1.1 - 7f1aca9 dpif-linux: Avoid logging error on ENOENT in dpif_linux_is_internal_device(). - 8996f83 dpif-linux: Avoid segfault on netdev_get_stats() without kernel module. - 002d4a3 vswitch: Improve schema documentation. - 58bd294 cfm: Fix broken fault logic. - c042664 bridge: Run once before configuring CFM. * Switch to dpkg-source 3.0 (quilt) format -- Simon Horman Wed, 27 Apr 2011 17:11:10 +0900 openvswitch (1.1.0~pre2.g2.ea763e0e-1) unstable; urgency=low * Git snapshot, including - tests: Fix Y2011 bug in testsuite (closes: #609506) -- Simon Horman Wed, 12 Jan 2011 08:34:35 +0900 openvswitch (1.1.0~pre2.g1.bbe8d06e-1) unstable; urgency=low * Git snaptshot -- Simon Horman Thu, 06 Jan 2011 11:11:55 +0900 openvswitch (1.1.0~pre2-5) unstable; urgency=low * Open vSwitch only works on Linux so set the Architecture of binary packages to linux-any accordingly -- Simon Horman Tue, 23 Nov 2010 07:55:19 +0900 openvswitch (1.1.0~pre2-4) unstable; urgency=low * Add procps to Build-Depends (closes: #602891) -- Simon Horman Tue, 16 Nov 2010 06:46:17 +0900 openvswitch (1.1.0~pre2-3) unstable; urgency=low * Remove the corekeeper package as it isn't strongly related to Open vSwitch. It has subsequently been broken off into a separate source repository and may be uploaded as its own debian source package. http://openvswitch.org/cgi-bin/gitweb.cgi?p=corekeeper;a=summary (closes: #602946) * Avoid the use of long socket names. (closes: #602891, closes: #602911) -- Simon Horman Thu, 11 Nov 2010 06:35:05 +0900 openvswitch (1.1.0~pre2-2) unstable; urgency=low * Clarify licensing of files in xenserver/ -- Simon Horman Thu, 23 Sep 2010 10:56:18 +0900 openvswitch (1.1.0~pre2-1) unstable; urgency=low * New upstream version - Bug fixes -- Simon Horman Wed, 15 Sep 2010 18:28:59 +0900 openvswitch (1.1.0~pre1-1) unstable; urgency=low * New upstream version - OpenFlow 1.0 slicing (QoS) functionality - Python bindings for configuration database (no write support) - Performance and scalability improvements - Bug fixes -- Open vSwitch team Tue, 31 Aug 2010 23:20:00 +0000 openvswitch (1.0.1-1) unstable; urgency=low * New upstream version. -- Open vSwitch team Mon, 17 May 2010 10:36:00 +0000 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-datapath-source.dirs0000644000000000000000000000013211674446641023406 xustar0030 mtime=1324502433.550026265 30 atime=1456592667.335091389 30 ctime=1456594659.981279906 openvswitch-2.5.0/debian/openvswitch-datapath-source.dirs0000664000175000017500000000005411674446641025075 0ustar00jpettitjpettit00000000000000usr/src/modules/openvswitch-datapath/debian openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.README.Debian0000644000000000000000000000013212631676263024561 xustar0030 mtime=1449622707.102443967 30 atime=1456592667.335091389 30 ctime=1456594660.001280748 openvswitch-2.5.0/debian/openvswitch-testcontroller.README.Debian0000664000175000017500000000105012631676263026245 0ustar00jpettitjpettit00000000000000README.Debian for openvswitch-testcontroller -------------------------------------------- The controller in this package enables OpenFlow switches that connect to it to act as MAC-learning Ethernet switches. It can be used for initial testing of OpenFlow networks. It is not a necessary or desirable part of a production OpenFlow deployment. To (re)configure the controller, edit /etc/default/openvswitch-testcontroller and run "/etc/init.d/openvswitch-testcontroller restart". -- Ben Pfaff , Thu, 14 Aug 2014 10:49:34 -0700 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.postinst0000644000000000000000000000013112663320001024302 xustar0029 mtime=1456316417.49493277 30 atime=1456592667.335091389 30 ctime=1456594660.009281083 openvswitch-2.5.0/debian/openvswitch-testcontroller.postinst0000775000175000017500000000260512663320001026001 0ustar00jpettitjpettit00000000000000#!/bin/sh # postinst script for openvswitch-testcontroller # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `configure' # * `abort-upgrade' # * `abort-remove' `in-favour' # # * `abort-remove' # * `abort-deconfigure' `in-favour' # `removing' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in configure) cd /etc/openvswitch-testcontroller if ! test -e cacert.pem; then ln -s /var/lib/openvswitch/pki/switchca/cacert.pem cacert.pem fi if ! test -e privkey.pem || ! test -e cert.pem; then oldumask=$(umask) umask 077 ovs-pki req+sign tmp controller >/dev/null mv tmp-privkey.pem privkey.pem mv tmp-cert.pem cert.pem mv tmp-req.pem req.pem chmod go+r cert.pem req.pem umask $oldumask fi ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-vtep.dirs0000644000000000000000000000013212631676263021277 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.013281253 openvswitch-2.5.0/debian/openvswitch-vtep.dirs0000664000175000017500000000002712631676263022766 0ustar00jpettitjpettit00000000000000/usr/share/openvswitch openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-vtep.install0000644000000000000000000000013212631676263022004 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.017281422 openvswitch-2.5.0/debian/openvswitch-vtep.install0000664000175000017500000000014212631676263023471 0ustar00jpettitjpettit00000000000000usr/share/openvswitch/scripts/ovs-vtep usr/share/openvswitch/vtep.ovsschema vtep/vtep-ctl usr/bin openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-test.dirs0000644000000000000000000000013211776774137021310 xustar0030 mtime=1341913183.436755826 30 atime=1456592667.335091389 30 ctime=1456594660.001280748 openvswitch-2.5.0/debian/openvswitch-test.dirs0000664000175000017500000000003411776774137022775 0ustar00jpettitjpettit00000000000000usr/share/pyshared/ovstest/ openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-pki.postrm0000644000000000000000000000013112663320001021443 xustar0029 mtime=1456316417.49493277 30 atime=1456592667.335091389 30 ctime=1456594659.989280245 openvswitch-2.5.0/debian/openvswitch-pki.postrm0000775000175000017500000000177512663320001023151 0ustar00jpettitjpettit00000000000000#!/bin/sh # postrm script for openvswitch-pki # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `remove' # * `purge' # * `upgrade' # * `failed-upgrade' # * `abort-install' # * `abort-install' # * `abort-upgrade' # * `disappear' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in purge) rm -f /var/log/openvswitch/ovs-pki.log* || true ;; remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-datapath-source.install0000644000000000000000000000013212631676263024112 xustar0030 mtime=1449622707.094443686 30 atime=1456592667.343091717 30 ctime=1456594659.981279906 openvswitch-2.5.0/debian/openvswitch-datapath-source.install0000664000175000017500000000045212631676263025603 0ustar00jpettitjpettit00000000000000debian/*.modules.in usr/src/modules/openvswitch-datapath/debian debian/changelog usr/src/modules/openvswitch-datapath/debian debian/compat usr/src/modules/openvswitch-datapath/debian debian/control usr/src/modules/openvswitch-datapath/debian openvswitch.tar.gz usr/src/modules/openvswitch-datapath openvswitch-2.5.0/debian/PaxHeaders.69223/copyright0000644000000000000000000000013112664353433017016 xustar0029 mtime=1456592667.10708204 30 atime=1456592702.764543855 30 ctime=1456594659.965279236 openvswitch-2.5.0/debian/copyright0000664000175000017500000012424512664353433020517 0ustar00jpettitjpettit00000000000000The original sources for this package can be found at: http://openvswitch.org/ Upstream Authors (from AUTHORS): Aaron Conole aconole@redhat.com Aaron Rosen arosen@clemson.edu Alexander Duyck alexander.h.duyck@redhat.com Alexandru Copot alex.mihai.c@gmail.com Alexei Starovoitov ast@plumgrid.com Alexey I. Froloff raorn@raorn.name Alex Wang ee07b291@gmail.com Alfredo Finelli alf@computationes.de Alin Serdean aserdean@cloudbasesolutions.com Ambika Arora ambika.arora@tcs.com Amit Bose bose@noironetworks.com Andrew Evans aevans@nicira.com Andrew Kampjes a.kampjes@gmail.com Andrew Lambeth wal@nicira.com Andy Hill hillad@gmail.com Andy Southgate andy.southgate@citrix.com Andy Zhou azhou@ovn.org Ankur Sharma ankursharma@vmware.com Anoob Soman anoob.soman@citrix.com Ansis Atteka aatteka@nicira.com Anupam Chanda achanda@nicira.com Ariel Tubaltsev atubaltsev@vmware.com Arun Sharma arun.sharma@calsoftinc.com Aryan TaheriMonfared aryan.taherimonfared@uis.no Ashwin Swaminathan ashwinds@arista.com Babu Shanmugam bschanmu@redhat.com Ben Pfaff blp@ovn.org Bert Vermeulen bert@biot.com Billy O'Mahony billy.o.mahony@intel.com Brian Kruger bkruger+ovsdev@gmail.com Bruce Davie bsd@nicira.com Bryan Phillippe bp@toroki.com Casey Barker crbarker@google.com Christoph Jaeger cj@linux.com Chris Wright chrisw@sous-sol.org Chuck Short zulcss@ubuntu.com Ciara Loftus ciara.loftus@intel.com Cong Wang amwang@redhat.com Damien Millescamps damien.millescamps@6wind.com Dan Carpenter dan.carpenter@oracle.com Dan McGregor dan.mcgregor@usask.ca Dan Wendlandt dan@nicira.com Daniel Borkmann dborkman@redhat.com Daniel Hiltgen daniel@netkine.com Daniel Roman droman@nicira.com Daniele Di Proietto daniele.di.proietto@gmail.com Daniele Venturino daniele.venturino@m3s.it Danny Kukawka danny.kukawka@bisect.de Dave Tucker dave@dtucker.co.uk David Erickson derickso@stanford.edu David S. Miller davem@davemloft.net David Yang davidy@vmware.com Devendra Naga devendra.aaru@gmail.com Dmitry Krivenok krivenok.dmitry@gmail.com Dominic Curran dominic.curran@citrix.com Dongdong dongdong1@huawei.com Duffie Cooley dcooley@nicira.com Ed Maste emaste@freebsd.org Ed Swierk eswierk@skyportsystems.com Edouard Bourguignon madko@linuxed.net Aymerich Edward edward.aymerich@hpe.com Edward Tomasz Napierała trasz@freebsd.org Eitan Eliahu eliahue@vmware.com Eohyung Lee liquidnuker@gmail.com Eric Sesterhenn eric.sesterhenn@lsexperts.de Ethan J. Jackson ejj@eecs.berkeley.edu Flavio Leitner fbl@redhat.com Francesco Fusco ffusco@redhat.com FUJITA Tomonori fujita.tomonori@lab.ntt.co.jp Gaetano Catalli gaetano.catalli@gmail.com Gal Sagie gal.sagie@gmail.com Geoffrey Wossum gwossum@acm.org Gianluca Merlo gianluca.merlo@gmail.com Giuseppe Lettieri g.lettieri@iet.unipi.it Glen Gibb grg@stanford.edu Guolin Yang gyang@nicira.com Guru Chaitanya Perakam gperakam@Brocade.com Gurucharan Shetty guru@ovn.org Han Zhou zhouhan@gmail.com Henry Mai hmai@nicira.com Hao Zheng hzheng@nicira.com Helmut Schaa helmut.schaa@googlemail.com Hiteshi Kalra hiteshi.kalra@tcs.com Huanle Han hanxueluo@gmail.com Ian Campbell Ian.Campbell@citrix.com Ilya Maximets i.maximets@samsung.com Isaku Yamahata yamahata@valinux.co.jp James P. roampune@gmail.com James Page james.page@ubuntu.com Jan Vansteenkiste jan@vstone.eu Jarno Rajahalme jarno@ovn.org Jason Kölker jason@koelker.net Jasper Capel jasper@capel.tv Jean Tourrilhes jt@hpl.hp.com Jeremy Stribling strib@nicira.com Jeroen van Bemmel jvb127@gmail.com Jesse Gross jesse@kernel.org Jing Ai jinga@google.com Jiri Benc jbenc@redhat.com Joe Perches joe@perches.com Joe Stringer joe@ovn.org Jonathan Vestin jonavest@kau.se Jun Nakajima jun.nakajima@intel.com Justin Pettit jpettit@ovn.org Keith Amidon keith@nicira.com Ken Ajiro ajiro@mxw.nes.nec.co.jp Kenneth Duda kduda@arista.com Kentaro Ebisawa ebiken.g@gmail.com Kevin Lo kevlo@FreeBSD.org Kevin Traynor kevin.traynor@intel.com Kmindg G kmindg@gmail.com Krishna Kondaka kkondaka@vmware.com Kyle Mestery mestery@mestery.com Kyle Upton kupton@baymicrosystems.com Lars Kellogg-Stedman lars@redhat.com Leo Alterman lalterman@nicira.com Lilijun jerry.lilijun@huawei.com Linda Sun lsun@vmware.com Lior Neudorfer lior@guardicore.com Lorand Jakab lojakab@cisco.com Luca Giraudo lgiraudo@nicira.com Lucian Petrut lpetrut@cloudbasesolutions.com Luigi Rizzo rizzo@iet.unipi.it Luis E. P. l31g@hotmail.com Madhu Challa challa@noironetworks.com Mark D. Gray mark.d.gray@intel.com Mark Hamilton mhamilton@nicira.com Mark Kavanagh mark.b.kavanagh@intel.com Mark Maglana mmaglana@gmail.com Martin Casado casado@nicira.com Martino Fornasa mf@fornasa.it Maryam Tahhan maryam.tahhan@intel.com Mauricio Vásquez mauricio.vasquezbernal@studenti.polito.it Mehak Mahajan mmahajan@nicira.com Michal Weglicki michalx.weglicki@intel.com Mijo Safradin mijo@linux.vnet.ibm.com Minoru TAKAHASHI takahashi.minoru7@gmail.com Murphy McCauley murphy.mccauley@gmail.com Natasha Gude natasha@nicira.com Neil McKee neil.mckee@inmon.com Neil Zhu zhuj@centecnetworks.com Nithin Raju nithin@vmware.com Niti Rohilla niti.rohilla@tcs.com Numan Siddique nusiddiq@redhat.com Padmanabhan Krishnan kprad1@yahoo.com Panu Matilainen pmatilai@redhat.com Paraneetharan Chandrasekaran paraneetharanc@gmail.com Paul Fazzone pfazzone@nicira.com Paul Ingram paul@nicira.com Paul-Emmanuel Raoul skyper@skyplabs.net Pavithra Ramesh paramesh@vmware.com Philippe Jung phil.jung@free.fr Pim van den Berg pim@nethuis.nl pritesh pritesh.kothari@cisco.com Pravin B Shelar pshelar@nicira.com Raju Subramanian rsubramanian@nicira.com Rami Rosen ramirose@gmail.com Randall Sharo andall.sharo@navy.mil Ravi Kerur Ravi.Kerur@telekom.com Reid Price reid@nicira.com Remko Tronçon git@el-tramo.be Rich Lane rlane@bigswitch.com Rishi Bamba rishi.bamba@tcs.com Rob Adams readams@readams.net Robert Åkerblom-Andersson Robert.nr1@gmail.com Rob Hoes rob.hoes@citrix.com Romain Lenglet romain.lenglet@berabera.info Russell Bryant russell@ovn.org Ryan Wilson wryan@nicira.com Sairam Venugopal vsairam@vmware.com Sajjad Lateef slateef@nicira.com Saloni Jain saloni.jain@tcs.com Samuel Ghinet sghinet@cloudbasesolutions.com Sanjay Sane ssane@nicira.com Saurabh Mohan saurabh@cplanenetworks.com Saurabh Shah ssaurabh@nicira.com Scott Lowe scott.lowe@scottlowe.org Scott Mann sdmnix@gmail.com Selvamuthukumar smkumar@merunetworks.com Shad Ansari shad.ansari@hpe.com Shan Wei davidshan@tencent.com Shashwat Srivastava shashwat.srivastava@tcs.com Shih-Hao Li shli@nicira.com Shu Shen shu.shen@radisys.com Simon Horman horms@verge.net.au Simon Horman simon.horman@netronome.com Sorin Vinturis svinturis@cloudbasesolutions.com Steffen Gebert steffen.gebert@informatik.uni-wuerzburg.de Sten Spans sten@blinkenlights.nl Stephane A. Sezer sas@cd80.net Stephen Finucane stephen.finucane@intel.com SUGYO Kazushi sugyo.org@gmail.com Tadaaki Nagao nagao@stratosphere.co.jp Terry Wilson twilson@redhat.com Tetsuo NAKAGAWA nakagawa@mxc.nes.nec.co.jp Thadeu Lima de Souza Cascardo cascardo@redhat.com Thomas F. Herbert thomasfherbert@gmail.com Thomas Goirand zigo@debian.org Thomas Graf tgraf@noironetworks.com Thomas Lacroix thomas.lacroix@citrix.com Timo Puha timox.puha@intel.com Todd Deshane deshantm@gmail.com Tom Everman teverman@google.com Tsvi Slonim tsvi@toroki.com Tuan Nguyen tuan.nguyen@veriksystems.com Tyler Coumbes coumbes@gmail.com Valient Gough vgough@pobox.com Vivien Bernet-Rollande vbr@soprive.net Wang Sheng-Hui shhuiw@gmail.com Wei Li liw@dtdream.com Wei Yongjun yjwei@cn.fujitsu.com Wenyu Zhang wenyuz@vmware.com William Fulton William Tu u9012063@gmail.com YAMAMOTO Takashi yamamoto@midokura.com Yasuhito Takamiya yasuhito@gmail.com Yin Lin linyi@vmware.com Yu Zhiguo yuzg@cn.fujitsu.com ZhengLingyun konghuarukhr@163.com Zoltán Balogh zoltan.balogh@ericsson.com Zoltan Kiss zoltan.kiss@citrix.com Zhi Yong Wu zwu.kernel@gmail.com Zang MingJie zealot0630@gmail.com xushengping shengping.xu@huawei.com yinpeijun yinpeijun@huawei.com Upstream Copyright Holders: Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. Copyright (c) 2010 Jean Tourrilhes - HP-Labs. Copyright (c) 2008,2009,2010 Citrix Systems, Inc. and authors listed above. Copyright (c) 2011 Gaetano Catalli Copyright (C) 2000-2003 Geoffrey Wossum (gwossum@acm.org) Copyright (C) 2000 The NetBSD Foundation, Inc. Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. Copyright (c) 1982, 1986, 1990, 1993 The Regents of the University of California. Copyright (c) 2008, 2012 Vincent Bernat Copyright (c) 2014 Michael Chapman Copyright (c) 2014 WindRiver, Inc. Copyright (c) 2014 Avaya, Inc. License: * The following components are licensed under the GNU Lesser General Public License version 2.1 only with the exception clause below as a pre-amble. xenserver/etc_xensource_scripts_vif xenserver/opt_xensource_libexec_InterfaceReconfigure.py xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py xenserver/opt_xensource_libexec_interface-reconfigure xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py * These components are only distributed in the source package. They do not appear in any binary packages. On Debian systems, the complete text of the GNU Lesser General Public License version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1' The exception clause pre-amble reads: As a special exception to the GNU Lesser General Public License, you may link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Lesser General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. * The following components are licensed under the GNU Lesser General Public License version 2.1. utilities/bugtool/ovs-bugtool utilities/bugtool/ovs-bugtool-* utilities/bugtool/plugins/kernel-info/openvswitch.xml utilities/bugtool/plugins/network-status/openvswitch.xml utilities/bugtool/plugins/system-configuration.xml utilities/bugtool/plugins/system-configuration/openvswitch.xml On Debian systems, the complete text of the GNU Lesser General Public License version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1' * The following component is licensed under the GNU General Public License version 2. datapath/ On Debian systems, the complete text of the GNU General Public License version 2 can be found in `/usr/share/common-licenses/GPL-2' * The following file is licensed under the GNU General Public License version 2. build-aux/cccl * The following files are licensed under the 2-clause BSD license. lib/getopt_long.c include/windows/getopt.h * The following files are licensed under the 3-clause BSD-license include/windows/netinet/icmp6.h include/windows/netinet/ip6.h lib/strsep.c * The following components are dual-licensed under the GNU General Public License version 2 and the Apache License Version 2.0. datapath/linux/compat/include/linux/openvswitch.h On Debian systems, the complete text of the GNU General Public License version 2 can be found in `/usr/share/common-licenses/GPL-2'. On Debian systems, the complete text of the Apache License version 2.0 can be found in '/usr/share/common-licenses/Apache-2.0'. * The following components are licensed under the terms of either the Sun Industry Standard Source License 1.1 or the InMon sFlow License: lib/sflow.h lib/sflow_agent.c lib/sflow_api.h lib/sflow_poller.c lib/sflow_receiver.c lib/sflow_sampler.c These licenses are available, respectively, the following URLs: http://host-sflow.sourceforge.net/sissl.html http://www.inmon.com/technology/sflowlicense.txt The full text of each license is also appended to the end of this file. * The following components are licensed for use as desired without restriction: lib/crc32c.c * lib/ovs.tmac in the source distribution, and manpages in the binaries, includes troff macros from groff 1.21 that contain the following notice: .\" an-ext.tmac .\" .\" Written by Eric S. Raymond .\" Werner Lemberg .\" .\" Version 2007-Feb-02 .\" .\" Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc. .\" You may freely use, modify and/or distribute this file. * m4/absolute-header.m4, by Derek Price, and m4/include_next.m4, by Paul Eggert and Derek Price bear the following notices: Copyright (C) 2006-2013 Free Software Foundation, Inc. This file is free software; the Free Software Foundation gives unlimited permission to copy and/or distribute it, with or without modifications, as long as this notice is preserved. * The following files are licensed under the ISC-license lib/lldp/aa-structs.h lib/lldp/lldpd.c lib/lldp/lldpd.h lib/lldp/lldpd-structs.c lib/lldp/lldpd-structs.h lib/lldp/lldp.c lib/lldp/lldp-tlv.h lib/lldp/lldp-const.h * All other components of this package are licensed under The Apache License Version 2.0. On Debian systems, the complete text of the Apache License version 2.0 can be found in '/usr/share/common-licenses/Apache-2.0'. ---------------------------------------------------------------------- Retrieved from http://host-sflow.sourceforge.net/sissl.html, 2011-12-12: Sun Industry Standards Source License - Version 1.1 1.0 DEFINITIONS 1.1 "Commercial Use" means distribution or otherwise making the Original Code available to a third party. 1.2 "Contributor Version" means the combination of the Original Code, and the Modifications made by that particular Contributor. 1.3 "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.4 "Executable" means Original Code in any form other than Source Code. 1.5 "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.6 "Larger Work" means a work which combines Original Code or portions thereof with code not governed by the terms of this License. 1.7 "License" means this document. 1.8 "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9 "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. A Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10 "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code. 1.11 "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.12 "Source Code" means the preferred form of the Original Code for making modifications to it, including all modules it contains, plus any associated interface definition files, or scripts used to control compilation and installation of an Executable. 1.13 "Standards" means the standards identified in Exhibit B. 1.14 "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2.0 SOURCE CODE LICENSE 2.1 The Initial Developer Grant The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices, including but not limited to Modifications. 3.0 DISTRIBUTION OBLIGATIONS 3.1 Application of License. The Source Code version of Original Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. Your license for shipment of the Contributor Version is conditioned upon Your full compliance with this Section. The Modifications which You create must comply with all requirements set out by the Standards body in effect one hundred twenty (120) days before You ship the Contributor Version. In the event that the Modifications do not meet such requirements, You agree to publish either (i) any deviation from the Standards protocol resulting from implementation of Your Modifications and a reference implementation of Your Modifications or (ii) Your Modifications in Source Code form, and to make any such deviation and reference implementation or Modifications available to all third parties under the same terms as this license on a royalty free basis within thirty (30) days of Your first customer shipment of Your Modifications. 3.2 Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add Your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Initial Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Your version of the Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer for any liability incurred by the Initial Developer as a result of warranty, support, indemnity or liability terms You offer. 3.3 Distribution of Executable Versions. You may distribute Original Code in Executable and Source form only if the requirements of Sections 3.1 and 3.2 have been met for that Original Code, and if You include a notice stating that the Source Code version of the Original Code is available under the terms of this License. The notice must be conspicuously included in any notice in an Executable or Source versions, related documentation or collateral in which You describe recipients' rights relating to the Original Code. You may distribute the Executable and Source versions of Your version of the Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License. If You distribute the Executable and Source versions under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer. You hereby agree to indemnify the Initial Developer for any liability incurred by the Initial Developer as a result of any such terms You offer. 3.4 Larger Works. You may create a Larger Work by combining Original Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Original Code. 4.0 INABILITY TO COMPLY DUE TO STATUTE OR REGULATION If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Original Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.2 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5.0 APPLICATION OF THIS LICENSE This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Modifications as set out in Section 3.1. 6.0 VERSIONS OF THE LICENSE 6.1 New Versions. Sun may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2 Effect of New Versions. Once Original Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Original Code under the terms of any subsequent version of the License published by Sun. No one other than Sun has the right to modify the terms applicable to Original Code. 7.0 DISCLAIMER OF WARRANTY ORIGINAL CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE ORIGINAL CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ORIGINAL CODE IS WITH YOU. SHOULD ANY ORIGINAL CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY ORIGINAL CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8.0 TERMINATION 8.1 This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Original Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2 In the event of termination under Section 8.1 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9.0 LIMIT OF LIABILITY UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF ORIGINAL CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10.0 U.S. GOVERNMENT END USERS U.S. Government: If this Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions). 11.0 MISCELLANEOUS This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. EXHIBIT A - Sun Standards License "The contents of this file are subject to the Sun Standards License Version 1.1 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at _______________________________. Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is ______________________________________. The Initial Developer of the Original Code is: InMon Corp. Portions created by: _______________________________________ are Copyright (C): _______________________________________ All Rights Reserved. Contributor(s): _______________________________________ EXHIBIT B - Standards The Standard is defined as the following: sFlow Specification, located at [1]http://sflow.org/developers/specifications.php References 1. http://sflow.org/developers/specifications.php ---------------------------------------------------------------------- Retrieved from http://www.inmon.com/technology/sflowlicense.txt, 2011-12-12: LICENSE AGREEMENT PLEASE READ THIS LICENSE AGREEMENT ("AGREEMENT") CAREFULLY BEFORE REPRODUCING OR IN ANY WAY UTILIZING THE sFlow(R) SOFTWARE ("SOFTWARE") AND/OR ANY ACCOMPANYING DOCUMENTATION ("DOCUMENTATION") AND/OR THE RELATED SPECIFICATIONS ("SPECIFICATIONS"). YOUR REPRODUCTION OR USE OF THE SOFTWARE AND/OR THE DOCUMENTATION AND/OR THE SPECIFICATIONS CONSTITUTES YOUR ACCEPTANCE OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS AGREEMENT, YOU MAY NOT REPRODUCE OR IN ANY WAY UTILIZE THE SOFTWARE OR THE DOCUMENTATION OR THE SPECIFICATIONS. 1. Definitions. "Documentation" means the user manuals, training materials, and operating materials, if any, InMon provides to Licensee under this Agreement. "InMon" means InMon Corporation, its affiliates and subsidiaries. "Intellectual Property Rights" means any trade secrets, patents, including without limitation any patents covering the Software, copyrights, know-how, moral rights and similar rights of any type under the laws of any governmental authority, domestic or foreign, including all applications and registrations relating to any of the foregoing. "Licensee Hardware" means all computers, routers, or other equipment owned or controlled by or on behalf of Licensee. "Products" means any and all software applications, computers, routers, or other equipment manufactured by or on behalf of Licensee for the purpose of resale or lease to any other third party, or otherwise made available by Licensee free of charge. "Software" means the sFlow(R) software programs, in source or binary code format, that Licensee licenses from InMon under this Agreement and any bug fixes or error corrections which InMon may provide to Licensee. "Specifications" means the published specifications provided or otherwise made available by InMon at: http://www.sflow.org. "Trademark" means InMon's "sFlow(R)" trademark. 2. License Grant. 2.1 Software, Documentation and Specifications License Grant. InMon hereby grants to Licensee, under all of InMon's Intellectual Property Rights therein, a perpetual (subject to InMon's termination rights under Section 7 below), nonexclusive, royalty-free, worldwide, transferable, sublicensable license, to: (i) use and reproduce the Software, the Documentation, and the Specifications; (ii) modify the Software; (iii) implement the Specifications in the Products; (iv) install the Software, or software in which the Specifications have been implemented, on Licensee Hardware and Products, and (v) distribute any Products that include the Software, the Documentation, or software in which the Specifications have been implemented. 2.2 Trademark License. InMon hereby grants to Licensee a perpetual (subject to InMon's termination rights under Section 7 below), nonexclusive, royalty-free, worldwide, transferable, sublicensable license to use the Trademark on or in connection with the Software, the Documentation, the Specifications and any software that implements the Specifications. 2.3 Restrictions. Licensee agrees that it will not use the Software in a way inconsistent with the license granted in Section 2.1. Further, Licensee agrees that, in exercising its rights under the license granted to it in this Agreement, Licensee will: (i) strictly adhere to and fully comply with the Specifications; (ii) use the Trademark, and no other mark, to identify the Software, the Documentation, the Specifications and any Products that implement the Specifications; (iii) place, in a font or graphic design designated by InMon, the phrase "sFlow(R)" on any technical documentation, sales/marketing materials, catalogs, or other such materials relating to products it manufactures or markets which it has configured to be compatible with the Software or otherwise implement the Specifications; (iv) in connection with any Products shipped to or sold in other countries that include the Software or any software that implements the Specifications, comply with the patent and trademark laws and practice of such other country; and (v) not alter or impair any acknowledgment of copyright or trademark rights of InMon that may appear in or on the Software, the Documentation or the Specifications. In the event InMon determines that Licensee is not complying with its obligations under clauses (i)-(v) above, InMon shall notify Licensee of such non-compliance, and if Licensee fails to correct such non-compliance within three (3) months, InMon may immediately terminate this Agreement as provided under paragraph 7 below and pursue any and all actions and remedies as it deems necessary, including, but not limited to breach of contract. 3. Ownership. Except for the license expressly granted in Section 2, Inmon hereby retains all right, title, and interest in and to the Trademark and all its Intellectual Property Rights in the Software, the Documentation and the Specifications. Licensee obtains no rights hereunder in the Trademark, Software, Documentation or Specifications by implication, estoppel or otherwise. Licensee acknowledges that the Trademark, Software, Documentation and Specifications are being licensed and not sold under this Agreement, and that this Agreement does not transfer title in the Trademark, Software, Documentation or Specifications, or any copy thereof, to Licensee. 4. Support. Inmon shall have no obligation under this Agreement to (a) supply maintenance or support, bug fixes or error corrections to the Licensed Software, (b) supply future versions of the Licensed Software or (c) provide Licensed Software development tools to Licensee. 5. Warranty. INMON HEREBY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS, IMPLIED OR STATUTORY, WITH RESPECT TO THE TRADEMARK, THE SOFTWARE, THE DOCUMENTATION, THE SPECIFICATIONS. OR OTHERWISE, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. 6. Limitation of Liability. IN NO EVENT SHALL INMON OR ITS SUPPLIERS OR LICENSORS BE LIABLE FOR ANY CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT OR EXEMPLARY DAMAGES WHATSOEVER, WHETHER RELATED TO OR ARISING OUT OF THIS AGREEMENT, THE TRADEMARK, THE SOFTWARE, THE DOCUMENTATION, THE SPECIFICATIONS, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, LOSS OF DATA, COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES OR FOR ANY CLAIM OR DEMAND AGAINST LICENSEE BY ANY OTHER PARTY, OR OTHER PECUNIARY LOSS, EVEN IF INMON HAS BEEN ADVISED OF OR KNOWS OF THE POSSIBILITY OF SUCH DAMAGES. 7. Term and Termination. The term of this Agreement will begin on the Effective Date, which shall be deemed to be the date of delivery of the Software and/or Documentation and/or Specifications to Licensee, and shall continue indefinitely unless and until terminated by Licensee's giving written notice of termination to InMon, or by InMon pursuant to InMon's termination rights as set forth in Section 2.3 above. Upon any termination of this Agreement, Licensee shall cease exercising its license rights under this Agreement, including the right to distribute Products that incorporate the Software or Documentation or that implement the Specifications. The rights and obligations contained in Sections 1, 3, 5, 6, 7, and 8 shall survive any termination of this Agreement. 8. General Provisions. 8.1 Assignment. This Agreement shall be binding upon and inure to the benefit of the parties hereto and their permitted successors and permitted assigns. InMon will have the right to assign this Agreement without notice to Licensee. Licensee may assign or transfer (whether by merger, operation of law or in any other manner) any of its rights or delegate any of its obligations hereunder without the prior written consent of InMon, provided the assignee assumes in writing all of Licensee's obligations hereunder. 8.2 Notices. All notices permitted or required under this Agreement shall be in writing and shall be delivered in person or mailed by first class, registered or certified mail, postage prepaid, to the address of the party specified in this Agreement or such other address as either party may specify in writing. Such notice shall be deemed to have been given upon receipt. 8.3 Non-Waiver. No term or provision hereof shall be deemed waived, and no breach excused, unless such waiver or consent shall be in writing and signed by the party claimed to have waived or consented. Any consent or waiver, whether express or implied, shall not constitute a consent or waiver of, or excuse for any separate, different or subsequent breach. 8.4 Independent Contractor. The parties' relationship shall be solely that of independent contractors, and nothing contained in this Agreement shall be construed to make either party an agent, partner, representative or principal of the other for any purpose. 8.5 Choice of Law and Forum. This Agreement shall be governed by and construed under the laws of the State of California, without giving effect to such state's conflict of laws principles. The parties hereby submit to the personal jurisdiction of, and agree that any legal proceeding with respect to or arising under this Agreement shall be brought in, the United States District Court for the Northern District of California or the state courts of the State of California for the County of San Francisco. 8.6 U.S. Government Licenses. The Software and Documentation are considered a "commercial item" as that term is defined at 48 C.F.R 2.101, or "commercial computer software" and "commercial computer software documentation" as such terms are used in 48 C.F.R 12.212 of the Federal Acquisition Regulations and its successors, and 48 C.F.R. 227.7202 of the DoD FAR Supplement and its successors. 8.7 Severability. If any provision of this Agreement is held to be unenforceable under applicable law, then such provision shall be excluded from this Agreement and the balance of this Agreement shall be interpreted as if such provision were so excluded and shall be enforceable in accordance with its terms. The court in its discretion may substitute for the excluded provision an enforceable provision which in economic substance reasonably approximates the excluded provision. 8.8 Compliance With Law. Licensee shall comply with all applicable laws and regulations (including privacy laws and regulations) having application to or governing its use and/or operation of the Software and agrees to indemnify and hold InMon harmless from and against any claims, damages, losses or obligations suffered or incurred by InMon arising from its failure to so comply. 8.9 Entire Agreement; Amendment. This Agreement constitutes the final, complete and entire agreement between the parties with respect to the subject matter hereof, and supersedes any previous proposals, negotiations, agreements, or arrangements, whether verbal or written, made between the parties with respect to such subject matter. This Agreement shall control over any additional or conflicting terms in any of Licensee's purchase orders or other business forms. This Agreement may only be amended or modified by mutual agreement of authorized representatives of the parties in writing. InMon Corp. 580 California Street, 5th Floor, San Francisco, CA 94104 Phone: (415) 283-3260 URL: www.inmon.com Email: info@inmon.com openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.postrm0000644000000000000000000000013212631676263023767 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.013281253 openvswitch-2.5.0/debian/openvswitch-testcontroller.postrm0000775000175000017500000000220212631676263025456 0ustar00jpettitjpettit00000000000000#!/bin/sh # postrm script for openvswitch-testcontroller # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `remove' # * `purge' # * `upgrade' # * `failed-upgrade' # * `abort-install' # * `abort-install' # * `abort-upgrade' # * `disappear' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in purge) if cd /etc/openvswitch-testcontroller; then rm -f cacert.pem cert.pem privkey.pem req.pem rm -f tmp-privkey.pem tmp-cert.pem tmp-req.pem fi ;; remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/control0000644000000000000000000000013212664352753016473 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.174815358 30 ctime=1456594659.965279236 openvswitch-2.5.0/debian/control0000664000175000017500000002357112664352753020173 0ustar00jpettitjpettit00000000000000Source: openvswitch Section: net Priority: extra Maintainer: Open vSwitch developers Uploaders: Ben Pfaff , Simon Horman Build-Depends: graphviz, autoconf (>= 2.64), automake (>= 1.10) | automake1.10, bzip2, debhelper (>= 8), dh-autoreconf, libssl-dev, libtool, openssl, procps, python-all (>= 2.7), python-qt4, python-twisted-conch, python-zopeinterface Standards-Version: 3.9.3 Homepage: http://openvswitch.org/ Package: openvswitch-datapath-source Architecture: all Depends: bzip2, debhelper (>= 5.0.37), module-assistant, ${misc:Depends} Suggests: openvswitch-switch Description: Open vSwitch datapath module source - module-assistant version Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . This package provides the Open vSwitch datapath module source code that is needed by openvswitch-switch. The kernel module can be built from it using module-assistant or make-kpkg. README.Debian in this package provides further instructions. Package: openvswitch-datapath-dkms Architecture: all Depends: dkms (>= 1.95), libc6-dev, make, ${misc:Depends}, ${python:Depends} Description: Open vSwitch datapath module source - DKMS version Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . This package provides the Open vSwitch datapath module source code that is needed by openvswitch-switch. DKMS can built the kernel module from it. Package: openvswitch-common Architecture: linux-any Depends: openssl, python, python (>= 2.7) | python-argparse, ${misc:Depends}, ${shlibs:Depends} Suggests: ethtool Description: Open vSwitch common components Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . openvswitch-common provides components required by both openvswitch-switch and openvswitch-testcontroller. Package: openvswitch-switch Architecture: linux-any Suggests: openvswitch-datapath-module Depends: kmod | module-init-tools, netbase, openvswitch-common (= ${binary:Version}), procps, python-argparse, uuid-runtime, ${misc:Depends}, ${python:Depends}, ${shlibs:Depends} Description: Open vSwitch switch implementations Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . openvswitch-switch provides the userspace components and utilities for the Open vSwitch kernel-based switch. Package: openvswitch-ipsec Architecture: linux-any Depends: ipsec-tools (>=0.8~alpha20101208), openvswitch-common (= ${binary:Version}), openvswitch-switch (= ${binary:Version}), python, python-openvswitch (= ${source:Version}), racoon (>=0.8~alpha20101208), ${misc:Depends}, ${shlibs:Depends} Description: Open vSwitch GRE-over-IPsec support Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . The ovs-monitor-ipsec script provides support for encrypting GRE tunnels with IPsec. Package: openvswitch-pki Architecture: all Depends: openvswitch-common (<< ${source:Version}.1~), openvswitch-common (>= ${source:Version}), ${misc:Depends} Description: Open vSwitch public key infrastructure dependency package Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . openvswitch-pki provides PKI (public key infrastructure) support for Open vSwitch switches and controllers, reducing the risk of man-in-the-middle attacks on the Open vSwitch network infrastructure. Package: openvswitch-testcontroller Architecture: linux-any Depends: openvswitch-common (= ${binary:Version}), openvswitch-pki (= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} Description: Simple controller for testing OpenFlow setups This controller enables OpenFlow switches that connect to it to act as MAC-learning Ethernet switches. It can be used for initial testing of OpenFlow networks. It is not a necessary or desirable part of a production OpenFlow deployment. Package: openvswitch-dbg Section: debug Architecture: linux-any Depends: openvswitch-common (= ${binary:Version}), openvswitch-switch (= ${binary:Version}), ${misc:Depends}, ${shlibs:Depends} Conflicts: openvswitch-testcontroller (<< ${binary:Version}), openvswitch-testcontroller (>> ${binary:Version}) Description: Debug symbols for Open vSwitch packages Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . This package contains the debug symbols for all the other openvswitch-* packages. Install it to debug one of them or to examine a core dump produced by one of them. Package: python-openvswitch Architecture: all Section: python Depends: ${misc:Depends}, ${python:Depends} Description: Python bindings for Open vSwitch Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . This package contains the full Python bindings for Open vSwitch database. Package: openvswitch-test Architecture: all Depends: python (>= 2.7) | python-argparse, python-twisted-web, ${misc:Depends}, ${python:Depends} Description: Open vSwitch test package Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, IPFIX, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . This package contains utilities that are useful to diagnose performance and connectivity issues in Open vSwitch setup. Package: openvswitch-vtep Architecture: linux-any Depends: openvswitch-common (>= ${binary:Version}), openvswitch-switch (>= ${binary:Version}), python, python-openvswitch (>= ${source:Version}), ${misc:Depends}, ${shlibs:Depends} Description: Open vSwitch VTEP utilities Open vSwitch is a production quality, multilayer, software-based, Ethernet virtual switch. It is designed to enable massive network automation through programmatic extension, while still supporting standard management interfaces and protocols (e.g. NetFlow, sFlow, SPAN, RSPAN, CLI, LACP, 802.1ag). In addition, it is designed to support distribution across multiple physical servers similar to VMware's vNetwork distributed vswitch or Cisco's Nexus 1000V. . This package provides utilities that are useful to interact with a VTEP-configured database and a VTEP emulator. openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-common.docs0000644000000000000000000000013112631676263021577 xustar0030 mtime=1449622707.094443686 30 atime=1456592667.331091225 29 ctime=1456594659.97327957 openvswitch-2.5.0/debian/openvswitch-common.docs0000664000175000017500000000006212631676263023266 0ustar00jpettitjpettit00000000000000FAQ.md INSTALL.DPDK.md README-native-tunneling.md openvswitch-2.5.0/debian/PaxHeaders.69223/rules0000644000000000000000000000013112664352753016144 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.174815358 29 ctime=1456594660.02128159 openvswitch-2.5.0/debian/rules0000775000175000017500000000667412664352753017655 0ustar00jpettitjpettit00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # # Modified to make a template file for a multi-binary package with separated # build-arch and build-indep targets by Bill Allombert 2001 #export DH_VERBOSE=1 PACKAGE=openvswitch PACKAGE_DKMS=openvswitch-datapath-dkms DEB_UPSTREAM_VERSION=$(shell dpkg-parsechangelog | sed -rne 's,^Version: ([0-9]:)*([^-]+).*,\2,p') ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) PARALLEL = -j$(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) else PARALLEL = endif %: dh $@ --with autoreconf,python2 --parallel # use --as-needed only if supported by dh-autoreconf (to simplify backporting) DH_AS_NEEDED=$(shell dpkg --compare-versions $$(dpkg --status dh-autoreconf | grep Version | cut -d' ' -f2) ge 6 && echo --as-needed) override_dh_autoreconf: dh_autoreconf $(DH_AS_NEEDED) override_dh_auto_configure: dh_auto_configure -- --enable-ssl $(DATAPATH_CONFIGURE_OPTS) override_dh_auto_test: ifeq (,$(filter nocheck,$(DEB_BUILD_OPTIONS))) if $(MAKE) check TESTSUITEFLAGS='$(PARALLEL)' || \ $(MAKE) check TESTSUITEFLAGS='--recheck'; then :; \ else \ cat tests/testsuite.log; \ exit 1; \ fi endif override_dh_auto_build: dh_auto_build -- dist distdir=openvswitch override_dh_auto_clean: rm -f python/ovs/*.pyc python/ovs/db/*.pyc dh_auto_clean override_dh_install: dh_install # openvswitch-switch cp debian/openvswitch-switch.template debian/openvswitch-switch/usr/share/openvswitch/switch/default.template # openvswitch-datapath-source cp debian/rules.modules debian/openvswitch-datapath-source/usr/src/modules/openvswitch-datapath/debian/rules chmod 755 debian/openvswitch-datapath-source/usr/src/modules/openvswitch-datapath/debian/rules cd debian/openvswitch-datapath-source/usr/src && tar -c modules | bzip2 -9 > openvswitch-datapath.tar.bz2 && rm -rf modules # openvswitch-datapath-dkms # setup the dirs dh_installdirs -p$(PACKAGE_DKMS) usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION) # copy the source cd debian/$(PACKAGE_DKMS)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION) && tar xvzf $(CURDIR)/openvswitch.tar.gz && mv openvswitch/* openvswitch/.[a-z]* . && rmdir openvswitch # check we can get kernel module names $(MAKE) -C datapath print-build-modules # Prepare dkms.conf from the dkms.conf.in template sed "s/__VERSION__/$(DEB_UPSTREAM_VERSION)/g; s/__MODULES__/$(shell $(MAKE) -C datapath print-build-modules | grep -v make)/" debian/dkms.conf.in > debian/$(PACKAGE_DKMS)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/dkms.conf # We don't need the debian folder in there, just upstream sources... rm -rf debian/$(PACKAGE_DKMS)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/debian # We don't need the rhel stuff in there either rm -rf debian/$(PACKAGE_DKMS)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/rhel # And we should also clean useless license files, which are already # described in our debian/copyright anyway. rm -f debian/$(PACKAGE_DKMS)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/COPYING \ debian/$(PACKAGE_DKMS)/usr/src/$(PACKAGE)-$(DEB_UPSTREAM_VERSION)/xenserver/LICENSE override_dh_installinit: dh_installinit -R override_dh_strip: dh_strip --dbg-package=openvswitch-dbg openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.logrotate0000644000000000000000000000013212631676263022661 xustar0030 mtime=1449622707.102443967 30 atime=1456592667.335091389 30 ctime=1456594659.993280413 openvswitch-2.5.0/debian/openvswitch-switch.logrotate0000664000175000017500000000061412631676263024352 0ustar00jpettitjpettit00000000000000/var/log/openvswitch/*.log { daily compress create 640 root adm delaycompress missingok rotate 30 postrotate # Tell Open vSwitch daemons to reopen their log files if [ -d /var/run/openvswitch ]; then for pidfile in `cd /var/run/openvswitch && echo *.pid`; do ovs-appctl -t "${pidfile%%.pid}" vlog/reopen done fi endscript } openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-common.install0000644000000000000000000000013112664352753022316 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.174815358 29 ctime=1456594659.97327957 openvswitch-2.5.0/debian/openvswitch-common.install0000664000175000017500000000044512664352753024012 0ustar00jpettitjpettit00000000000000etc/bash_completion.d/ovs-appctl-bashcomp.bash usr/bin/ovs-appctl usr/bin/ovs-benchmark usr/bin/ovs-docker usr/bin/ovs-ofctl usr/bin/ovs-parse-backtrace usr/bin/ovs-pki usr/bin/ovsdb-client usr/sbin/ovs-bugtool usr/share/openvswitch/bugtool-plugins usr/share/openvswitch/scripts/ovs-bugtool-* openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-datapath-module-_KVERS_.postinst.modules.in0000644000000000000000000000013212631270735027550 xustar0030 mtime=1449488861.319997842 30 atime=1456592667.335091389 30 ctime=1456594659.977279738 openvswitch-2.5.0/debian/openvswitch-datapath-module-_KVERS_.postinst.modules.in0000775000175000017500000000132012631270735031237 0ustar00jpettitjpettit00000000000000#!/bin/sh # postinst script for #PACKAGE# # # see: dh_installdeb(1) set -e #DEBHELPER# # If the kernel module is already loaded, we have nothing to do here. # A force-reload-kmod should be run manually to use the new kernel module. if [ -e /sys/module/openvswitch ] || [ -e /sys/module/openvswitch_mod ]; then exit 0 fi # If the kernel module is not loaded, then it is likely because none # was installed before and therefore Open vSwitch couldn't be started. # Try to start it now. # # (Ideally we'd only want to do this if this package corresponds to the # running kernel, but I don't know a reliable way to check.) INIT=/etc/init.d/openvswitch-switch if test -x $INIT; then $INIT start || true fi exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.README.Debian0000644000000000000000000000013212631676263022777 xustar0030 mtime=1449622707.094443686 30 atime=1456592667.335091389 30 ctime=1456594659.989280245 openvswitch-2.5.0/debian/openvswitch-switch.README.Debian0000664000175000017500000001573612631676263024503 0ustar00jpettitjpettit00000000000000README.Debian for openvswitch-switch --------------------------------- To use the Linux kernel-based switch implementation, you will need an Open vSwitch kernel module. There are multiple ways to obtain one. In order of increasing manual effort, these are: * Use a Linux kernel 3.3 or later, which has an integrated Open vSwitch kernel module. The upstream Linux kernel module lacks a few features that are in the third-party module. For details, please see the FAQ, "What features are not available in the Open vSwitch kernel datapath that ships as part of the upstream Linux kernel?". * Install the "openvswitch-datapath-dkms" Debian package that you built earlier. This should automatically build and install the Open vSwitch kernel module for your running kernel. This option requires that you have a compiler and toolchain installed on the machine where you run Open vSwitch, which may be unacceptable in some production server environments. * Install the "openvswitch-datapath-source" Debian package, use "module-assistant" to build a Debian package of the Open vSwitch kernel module for your kernel, and then install that Debian package. You can install the kernel module Debian packages that you build this way on the same machine where you built it or on another machine or machines, which means that you don't necessarily have to have any build infrastructure on the machines where you use the kernel module. /usr/share/doc/openvswitch-datapath-source/README.Debian has details on the build process. * Build and install the kernel module by hand. Debian network scripts integration ---------------------------------- This package lets a user to optionally configure Open vSwitch bridges and ports from /etc/network/interfaces. Please refer to the interfaces(5) manpage for more details regarding /etc/network/interfaces. The stanzas that configure the OVS bridges should begin with "allow-ovs" followed by name of the bridge. Here is an example. allow-ovs br0 The stanzas that configure the OVS ports should begin with "allow-${bridge-name}" followed by name of the port. Here is an example. allow-br0 eth0 The following OVS specific "command" options are supported: - ovs_type: This can either be OVSBridge, OVSPort, OVSIntPort, OVSBond, OVSPatchPort or OVSTunnel depending on whether you configure a bridge, port, an internal port, a bond, a patch port or a tunnel. This is a required option. - ovs_ports: This option specifies all the ports that belong to a bridge. - ovs_bridge: This options specifies a bridge to which a port belongs. This is a required option for a port. - ovs_bonds: This option specifies the list of physical interfaces to be bonded together. - ovs_patch_peer: For "OVSPatchPort" interfaces, this field specifies the patch's peer on the other bridge. - ovs_tunnel_type: For "OVSTunnel" interfaces, the type of the tunnel. For example, "gre", "vxlan", etc. - ovs_tunnel_options: For "OVSTunnel" interfaces, this field should be used to specify the tunnel options like remote_ip, key, etc. - ovs_options: This option lets you add extra arguments to a ovs-vsctl command. See examples. - ovs_extra: This option lets you run additional ovs-vsctl commands, separated by "--" (double dash). Variables can be part of the "ovs_extra" option. You can provide all the standard environmental variables described in the interfaces(5) man page. You can also pass shell commands. More implementation specific details can be seen in the examples. Examples: -------- ex 1: A standalone bridge. allow-ovs br0 iface br0 inet static address 192.168.1.1 netmask 255.255.255.0 ovs_type OVSBridge ex 2: A bridge with one port. allow-ovs br0 iface br0 inet dhcp ovs_type OVSBridge ovs_ports eth0 allow-br0 eth0 iface eth0 inet manual ovs_bridge br0 ovs_type OVSPort ex 3: A bridge with multiple physical ports. allow-ovs br0 iface br0 inet dhcp ovs_type OVSBridge ovs_ports eth0 eth1 allow-br0 eth0 iface eth0 inet manual ovs_bridge br0 ovs_type OVSPort allow-br0 eth1 iface eth1 inet manual ovs_bridge br0 ovs_type OVSPort ex 4: A bridge with an OVS internal port. allow-ovs br1 iface br1 inet static address 192.168.1.1 netmask 255.255.255.0 ovs_type OVSBridge ovs_ports vlan100 allow-br1 vlan100 iface vlan100 inet manual ovs_bridge br1 ovs_type OVSIntPort ovs_options tag=100 ovs_extra set interface ${IFACE} external-ids:iface-id=$(hostname -s) ex 5: Bonding. allow-ovs br2 iface br2 inet static address 192.170.1.1 netmask 255.255.255.0 ovs_type OVSBridge ovs_ports bond0 allow-br2 bond0 iface bond0 inet manual ovs_bridge br2 ovs_type OVSBond ovs_bonds eth2 eth3 ovs_options bond_mode=balance-tcp lacp=active ex 6: Patch ports. allow-ovs br0 iface br0 inet manual ovs_type OVSBridge ovs_ports patch0 allow-br0 patch0 iface patch0 inet manual ovs_bridge br0 ovs_type OVSPatchPort ovs_patch_peer patch1 allow-ovs br1 iface br1 inet manual ovs_type OVSBridge ovs_ports patch1 allow-br1 patch1 iface patch1 inet manual ovs_bridge br1 ovs_type OVSPatchPort ovs_patch_peer patch0 ex 7: Tunnel. allow-ovs br1 iface br1 inet static address 192.168.1.1 netmask 255.255.255.0 ovs_type OVSBridge ovs_ports gre1 allow-br1 gre1 iface gre1 inet manual ovs_bridge br1 ovs_type OVSTunnel ovs_tunnel_type gre ovs_tunnel_options options:remote_ip=182.168.1.2 options:key=1 ex 8: Create and destroy bridges. ifup --allow=ovs $list_of_bridges ifdown --allow=ovs $list_of_bridges Notes on dependencies: --------------------- openvswitch-switch depends on $network, $named $remote_fs and $syslog to start. This creates some startup dependency issues. * Since openvswitch utilities are placed in /usr and /usr can be mounted through NFS, openvswitch has to start after it. But if a user uses openvswitch for all his networking needs and hence to mount NFS, there will be a deadlock. So, if /usr is mounted through NFS and openvswitch is used for all networking, the administrator should figure out a way to mount NFS before starting OVS. One way to do this is in initramfs. * Since openvswitch starts after $network, $remote_fs and $syslog, any startup script that depends on openvswitch but starts before it, needs to be changed to depend on openvswitch-switch too. * Ideally, an admin should not add openvswitch bridges in the 'auto' section of the 'interfaces' file. This is because, when ifupdown starts working on bridges listed in 'auto', openvswitch has not yet started. But, if the admin wants to go down this route and adds openvswitch bridges in the 'auto' section, openvswitch-switch will forcefully be started when ifupdown kicks in. In a case like this, the admin needs to make sure that /usr has already been mounted and that a remote $syslog (if used) is ready to receive openvswitch logs. openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-datapath-dkms.postinst0000644000000000000000000000013211776774137023775 xustar0030 mtime=1341913183.408755824 30 atime=1456592667.331091225 30 ctime=1456594659.977279738 openvswitch-2.5.0/debian/openvswitch-datapath-dkms.postinst0000664000175000017500000000070211776774137025464 0ustar00jpettitjpettit00000000000000#!/bin/sh set -e package=openvswitch-datapath-dkms name=openvswitch version=`dpkg-query -W -f='${Version}' "$package" \ |rev|cut -d- -f2-|rev|cut -d':' -f2|tr -d "\n"` isadded=`dkms status -m "$name" -v "$version"` if [ "x${isadded}" = "x" ] ; then dkms add -m "$name" -v "$version" fi if [ "$1" = 'configure' ] ; then dkms build -m "$name" -v "$version" && dkms install -m "$name" -v "$version" || true fi #DEBHELPER# openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.dirs0000644000000000000000000000013212130751561021607 xustar0030 mtime=1365496689.370878591 30 atime=1456592667.335091389 30 ctime=1456594659.989280245 openvswitch-2.5.0/debian/openvswitch-switch.dirs0000664000175000017500000000005712130751561023301 0ustar00jpettitjpettit00000000000000/etc/openvswitch /usr/share/openvswitch/switch openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-common.manpages0000644000000000000000000000013112664352753022443 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.174815358 29 ctime=1456594659.97327957 openvswitch-2.5.0/debian/openvswitch-common.manpages0000664000175000017500000000030312664352753024130 0ustar00jpettitjpettit00000000000000ovsdb/ovsdb-client.1 ovsdb/ovsdb-tool.1 utilities/bugtool/ovs-bugtool.8 utilities/ovs-appctl.8 utilities/ovs-benchmark.1 utilities/ovs-ofctl.8 utilities/ovs-parse-backtrace.8 utilities/ovs-pki.8 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-common.dirs0000644000000000000000000000013111674446641021611 xustar0030 mtime=1324502433.550026265 30 atime=1456592667.331091225 29 ctime=1456594659.97327957 openvswitch-2.5.0/debian/openvswitch-common.dirs0000664000175000017500000000002411674446641023276 0ustar00jpettitjpettit00000000000000var/log/openvswitch openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.install0000644000000000000000000000013212664352753022330 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.174815358 30 ctime=1456594659.993280413 openvswitch-2.5.0/debian/openvswitch-switch.install0000664000175000017500000000074112664352753024022 0ustar00jpettitjpettit00000000000000debian/ifupdown.sh usr/share/openvswitch/scripts etc/bash_completion.d/ovs-vsctl-bashcomp.bash usr/bin/ovs-dpctl usr/bin/ovs-dpctl-top usr/bin/ovs-pcap usr/bin/ovs-tcpundump usr/bin/ovs-vlan-test usr/bin/ovs-vsctl usr/bin/ovsdb-tool usr/sbin/ovs-vswitchd usr/sbin/ovsdb-server usr/share/openvswitch/scripts/ovs-check-dead-ifs usr/share/openvswitch/scripts/ovs-ctl usr/share/openvswitch/scripts/ovs-lib usr/share/openvswitch/scripts/ovs-save usr/share/openvswitch/vswitch.ovsschema openvswitch-2.5.0/debian/PaxHeaders.69223/rules.modules0000644000000000000000000000013112631676263017612 xustar0030 mtime=1449622707.114444389 30 atime=1456592667.339091552 29 ctime=1456594660.02128159 openvswitch-2.5.0/debian/rules.modules0000775000175000017500000000157712631676263021320 0ustar00jpettitjpettit00000000000000#! /usr/bin/make -f PACKAGE=openvswitch-datapath-module MA_DIR ?= /usr/share/modass -include $(MA_DIR)/include/generic.make -include $(MA_DIR)/include/common-rules.make DATAPATH_CONFIGURE_OPTS = kdist_clean: dh_testdir dh_testroot dh_clean rm -rf openvswitch .PHONY: kdist_config kdist_config: prep-deb-files .PHONY: binary-modules binary-modules: DSTDIR = $(CURDIR)/debian/$(PKGNAME)/lib/modules/$(KVERS)/updates binary-modules: prep-deb-files dh_testdir dh_testroot dh_clean -k tar xzf openvswitch.tar.gz cd openvswitch && ./configure --with-linux=$(KSRC) $(DATAPATH_CONFIGURE_OPTS) cd openvswitch && $(MAKE) -C datapath/linux install -d -m755 $(DSTDIR) install -m644 openvswitch/datapath/linux/*.ko $(DSTDIR)/ dh_installmodules dh_installdocs dh_installchangelogs dh_compress dh_fixperms dh_installdeb dh_gencontrol dh_md5sums dh_builddeb --destdir=$(DEB_DESTDIR) openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-vtep.manpages0000644000000000000000000000013212631676263022131 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.017281422 openvswitch-2.5.0/debian/openvswitch-vtep.manpages0000664000175000017500000000002012631676263023611 0ustar00jpettitjpettit00000000000000vtep/vtep-ctl.8 openvswitch-2.5.0/debian/PaxHeaders.69223/ifupdown.sh0000644000000000000000000000013212631676263017256 xustar0030 mtime=1449622707.094443686 30 atime=1456592667.331091225 30 ctime=1456594660.025281758 openvswitch-2.5.0/debian/ifupdown.sh0000775000175000017500000000673012631676263020757 0ustar00jpettitjpettit00000000000000#! /bin/sh # Copyright (c) 2012, 2013 Nicira, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # Have a look at /usr/share/doc/openvswitch-switch/README.Debian # for more information about configuring the /etc/network/interfaces. if [ -z "${IF_OVS_TYPE}" ]; then exit 0 fi ovs_vsctl() { ovs-vsctl --timeout=5 "$@" } if (ovs_vsctl --version) > /dev/null 2>&1; then :; else exit 0 fi if /etc/init.d/openvswitch-switch status > /dev/null 2>&1; then :; else /etc/init.d/openvswitch-switch start fi if [ "${MODE}" = "start" ]; then eval OVS_EXTRA=\"${IF_OVS_EXTRA}\" case "${IF_OVS_TYPE}" in OVSBridge) ovs_vsctl -- --may-exist add-br "${IFACE}" ${IF_OVS_OPTIONS}\ ${OVS_EXTRA+-- $OVS_EXTRA} if [ ! -z "${IF_OVS_PORTS}" ]; then ifup --allow="${IFACE}" ${IF_OVS_PORTS} fi ;; OVSPort) ovs_vsctl -- --may-exist add-port "${IF_OVS_BRIDGE}"\ "${IFACE}" ${IF_OVS_OPTIONS} \ ${OVS_EXTRA+-- $OVS_EXTRA} ifconfig "${IFACE}" up ;; OVSIntPort) ovs_vsctl -- --may-exist add-port "${IF_OVS_BRIDGE}"\ "${IFACE}" ${IF_OVS_OPTIONS} -- set Interface "${IFACE}"\ type=internal ${OVS_EXTRA+-- $OVS_EXTRA} ifconfig "${IFACE}" up ;; OVSBond) ovs_vsctl -- --fake-iface add-bond "${IF_OVS_BRIDGE}"\ "${IFACE}" ${IF_OVS_BONDS} ${IF_OVS_OPTIONS} \ ${OVS_EXTRA+-- $OVS_EXTRA} ifconfig "${IFACE}" up for slave in ${IF_OVS_BONDS} do ifconfig "${slave}" up done ;; OVSPatchPort) ovs_vsctl -- --may-exist add-port "${IF_OVS_BRIDGE}"\ "${IFACE}" ${IF_OVS_OPTIONS} -- set Interface "${IFACE}" \ type=patch options:peer="${IF_OVS_PATCH_PEER}" \ ${OVS_EXTRA+-- $OVS_EXTRA} ;; OVSTunnel) ovs_vsctl -- --may-exist add-port "${IF_OVS_BRIDGE}"\ "${IFACE}" ${IF_OVS_OPTIONS} -- set Interface "${IFACE}" \ type=${IF_OVS_TUNNEL_TYPE} ${IF_OVS_TUNNEL_OPTIONS} \ ${OVS_EXTRA+-- $OVS_EXTRA} ;; *) exit 0 ;; esac elif [ "${MODE}" = "stop" ]; then case "${IF_OVS_TYPE}" in OVSBridge) if [ ! -z "${IF_OVS_PORTS}" ]; then ifdown --allow="${IFACE}" ${IF_OVS_PORTS} fi ovs_vsctl -- --if-exists del-br "${IFACE}" ;; OVSPort|OVSIntPort|OVSBond|OVSPatchPort|OVSTunnel) ovs_vsctl -- --if-exists del-port "${IF_OVS_BRIDGE}" "${IFACE}" ;; *) exit 0 ;; esac fi exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/copyright.in0000644000000000000000000000013212631676263017427 xustar0030 mtime=1449622707.090443546 30 atime=1456592667.095081548 30 ctime=1456594659.969279403 openvswitch-2.5.0/debian/copyright.in0000664000175000017500000007761212631676263021134 0ustar00jpettitjpettit00000000000000The original sources for this package can be found at: http://openvswitch.org/ Upstream Authors (from AUTHORS): %AUTHORS% Upstream Copyright Holders: Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. Copyright (c) 2010 Jean Tourrilhes - HP-Labs. Copyright (c) 2008,2009,2010 Citrix Systems, Inc. and authors listed above. Copyright (c) 2011 Gaetano Catalli Copyright (C) 2000-2003 Geoffrey Wossum (gwossum@acm.org) Copyright (C) 2000 The NetBSD Foundation, Inc. Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. Copyright (c) 1982, 1986, 1990, 1993 The Regents of the University of California. Copyright (c) 2008, 2012 Vincent Bernat Copyright (c) 2014 Michael Chapman Copyright (c) 2014 WindRiver, Inc. Copyright (c) 2014 Avaya, Inc. License: * The following components are licensed under the GNU Lesser General Public License version 2.1 only with the exception clause below as a pre-amble. xenserver/etc_xensource_scripts_vif xenserver/opt_xensource_libexec_InterfaceReconfigure.py xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py xenserver/opt_xensource_libexec_interface-reconfigure xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py * These components are only distributed in the source package. They do not appear in any binary packages. On Debian systems, the complete text of the GNU Lesser General Public License version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1' The exception clause pre-amble reads: As a special exception to the GNU Lesser General Public License, you may link, statically or dynamically, a "work that uses the Library" with a publicly distributed version of the Library to produce an executable file containing portions of the Library, and distribute that executable file under terms of your choice, without any of the additional requirements listed in clause 6 of the GNU Lesser General Public License. By "a publicly distributed version of the Library", we mean either the unmodified Library as distributed, or a modified version of the Library that is distributed under the conditions defined in clause 3 of the GNU Library General Public License. This exception does not however invalidate any other reasons why the executable file might be covered by the GNU Lesser General Public License. * The following components are licensed under the GNU Lesser General Public License version 2.1. utilities/bugtool/ovs-bugtool utilities/bugtool/ovs-bugtool-* utilities/bugtool/plugins/kernel-info/openvswitch.xml utilities/bugtool/plugins/network-status/openvswitch.xml utilities/bugtool/plugins/system-configuration.xml utilities/bugtool/plugins/system-configuration/openvswitch.xml On Debian systems, the complete text of the GNU Lesser General Public License version 2.1 can be found in `/usr/share/common-licenses/LGPL-2.1' * The following component is licensed under the GNU General Public License version 2. datapath/ On Debian systems, the complete text of the GNU General Public License version 2 can be found in `/usr/share/common-licenses/GPL-2' * The following file is licensed under the GNU General Public License version 2. build-aux/cccl * The following files are licensed under the 2-clause BSD license. lib/getopt_long.c include/windows/getopt.h * The following files are licensed under the 3-clause BSD-license include/windows/netinet/icmp6.h include/windows/netinet/ip6.h lib/strsep.c * The following components are dual-licensed under the GNU General Public License version 2 and the Apache License Version 2.0. datapath/linux/compat/include/linux/openvswitch.h On Debian systems, the complete text of the GNU General Public License version 2 can be found in `/usr/share/common-licenses/GPL-2'. On Debian systems, the complete text of the Apache License version 2.0 can be found in '/usr/share/common-licenses/Apache-2.0'. * The following components are licensed under the terms of either the Sun Industry Standard Source License 1.1 or the InMon sFlow License: lib/sflow.h lib/sflow_agent.c lib/sflow_api.h lib/sflow_poller.c lib/sflow_receiver.c lib/sflow_sampler.c These licenses are available, respectively, the following URLs: http://host-sflow.sourceforge.net/sissl.html http://www.inmon.com/technology/sflowlicense.txt The full text of each license is also appended to the end of this file. * The following components are licensed for use as desired without restriction: lib/crc32c.c * lib/ovs.tmac in the source distribution, and manpages in the binaries, includes troff macros from groff 1.21 that contain the following notice: .\" an-ext.tmac .\" .\" Written by Eric S. Raymond .\" Werner Lemberg .\" .\" Version 2007-Feb-02 .\" .\" Copyright (C) 2007, 2009, 2011 Free Software Foundation, Inc. .\" You may freely use, modify and/or distribute this file. * m4/absolute-header.m4, by Derek Price, and m4/include_next.m4, by Paul Eggert and Derek Price bear the following notices: Copyright (C) 2006-2013 Free Software Foundation, Inc. This file is free software; the Free Software Foundation gives unlimited permission to copy and/or distribute it, with or without modifications, as long as this notice is preserved. * The following files are licensed under the ISC-license lib/lldp/aa-structs.h lib/lldp/lldpd.c lib/lldp/lldpd.h lib/lldp/lldpd-structs.c lib/lldp/lldpd-structs.h lib/lldp/lldp.c lib/lldp/lldp-tlv.h lib/lldp/lldp-const.h * All other components of this package are licensed under The Apache License Version 2.0. On Debian systems, the complete text of the Apache License version 2.0 can be found in '/usr/share/common-licenses/Apache-2.0'. ---------------------------------------------------------------------- Retrieved from http://host-sflow.sourceforge.net/sissl.html, 2011-12-12: Sun Industry Standards Source License - Version 1.1 1.0 DEFINITIONS 1.1 "Commercial Use" means distribution or otherwise making the Original Code available to a third party. 1.2 "Contributor Version" means the combination of the Original Code, and the Modifications made by that particular Contributor. 1.3 "Electronic Distribution Mechanism" means a mechanism generally accepted in the software development community for the electronic transfer of data. 1.4 "Executable" means Original Code in any form other than Source Code. 1.5 "Initial Developer" means the individual or entity identified as the Initial Developer in the Source Code notice required by Exhibit A. 1.6 "Larger Work" means a work which combines Original Code or portions thereof with code not governed by the terms of this License. 1.7 "License" means this document. 1.8 "Licensable" means having the right to grant, to the maximum extent possible, whether at the time of the initial grant or subsequently acquired, any and all of the rights conveyed herein. 1.9 "Modifications" means any addition to or deletion from the substance or structure of either the Original Code or any previous Modifications. A Modification is: A. Any addition to or deletion from the contents of a file containing Original Code or previous Modifications. B. Any new file that contains any part of the Original Code or previous Modifications. 1.10 "Original Code" means Source Code of computer software code which is described in the Source Code notice required by Exhibit A as Original Code. 1.11 "Patent Claims" means any patent claim(s), now owned or hereafter acquired, including without limitation, method, process, and apparatus claims, in any patent Licensable by grantor. 1.12 "Source Code" means the preferred form of the Original Code for making modifications to it, including all modules it contains, plus any associated interface definition files, or scripts used to control compilation and installation of an Executable. 1.13 "Standards" means the standards identified in Exhibit B. 1.14 "You" (or "Your") means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License or a future version of this License issued under Section 6.1. For legal entities, "You'' includes any entity which controls, is controlled by, or is under common control with You. For purposes of this definition, "control'' means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of more than fifty percent (50%) of the outstanding shares or beneficial ownership of such entity. 2.0 SOURCE CODE LICENSE 2.1 The Initial Developer Grant The Initial Developer hereby grants You a world-wide, royalty-free, non-exclusive license, subject to third party intellectual property claims: (a) under intellectual property rights (other than patent or trademark) Licensable by Initial Developer to use, reproduce, modify, display, perform, sublicense and distribute the Original Code (or portions thereof) with or without Modifications, and/or as part of a Larger Work; and (b) under Patents Claims infringed by the making, using or selling of Original Code, to make, have made, use, practice, sell, and offer for sale, and/or otherwise dispose of the Original Code (or portions thereof). (c) the licenses granted in this Section 2.1(a) and (b) are effective on the date Initial Developer first distributes Original Code under the terms of this License. (d) Notwithstanding Section 2.1(b) above, no patent license is granted: 1) for code that You delete from the Original Code; 2) separate from the Original Code; or 3) for infringements caused by: i) the modification of the Original Code or ii) the combination of the Original Code with other software or devices, including but not limited to Modifications. 3.0 DISTRIBUTION OBLIGATIONS 3.1 Application of License. The Source Code version of Original Code may be distributed only under the terms of this License or a future version of this License released under Section 6.1, and You must include a copy of this License with every copy of the Source Code You distribute. You may not offer or impose any terms on any Source Code version that alters or restricts the applicable version of this License or the recipients' rights hereunder. Your license for shipment of the Contributor Version is conditioned upon Your full compliance with this Section. The Modifications which You create must comply with all requirements set out by the Standards body in effect one hundred twenty (120) days before You ship the Contributor Version. In the event that the Modifications do not meet such requirements, You agree to publish either (i) any deviation from the Standards protocol resulting from implementation of Your Modifications and a reference implementation of Your Modifications or (ii) Your Modifications in Source Code form, and to make any such deviation and reference implementation or Modifications available to all third parties under the same terms as this license on a royalty free basis within thirty (30) days of Your first customer shipment of Your Modifications. 3.2 Required Notices. You must duplicate the notice in Exhibit A in each file of the Source Code. If it is not possible to put such notice in a particular Source Code file due to its structure, then You must include such notice in a location (such as a relevant directory) where a user would be likely to look for such a notice. If You created one or more Modification(s) You may add Your name as a Contributor to the notice described in Exhibit A. You must also duplicate this License in any documentation for the Source Code where You describe recipients' rights or ownership rights relating to Initial Code. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations to one or more recipients of Your version of the Code. However, You may do so only on Your own behalf, and not on behalf of the Initial Developer. You must make it absolutely clear than any such warranty, support, indemnity or liability obligation is offered by You alone, and You hereby agree to indemnify the Initial Developer for any liability incurred by the Initial Developer as a result of warranty, support, indemnity or liability terms You offer. 3.3 Distribution of Executable Versions. You may distribute Original Code in Executable and Source form only if the requirements of Sections 3.1 and 3.2 have been met for that Original Code, and if You include a notice stating that the Source Code version of the Original Code is available under the terms of this License. The notice must be conspicuously included in any notice in an Executable or Source versions, related documentation or collateral in which You describe recipients' rights relating to the Original Code. You may distribute the Executable and Source versions of Your version of the Code or ownership rights under a license of Your choice, which may contain terms different from this License, provided that You are in compliance with the terms of this License. If You distribute the Executable and Source versions under a different license You must make it absolutely clear that any terms which differ from this License are offered by You alone, not by the Initial Developer. You hereby agree to indemnify the Initial Developer for any liability incurred by the Initial Developer as a result of any such terms You offer. 3.4 Larger Works. You may create a Larger Work by combining Original Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In such a case, You must make sure the requirements of this License are fulfilled for the Original Code. 4.0 INABILITY TO COMPLY DUE TO STATUTE OR REGULATION If it is impossible for You to comply with any of the terms of this License with respect to some or all of the Original Code due to statute, judicial order, or regulation then You must: (a) comply with the terms of this License to the maximum extent possible; and (b) describe the limitations and the code they affect. Such description must be included in the LEGAL file described in Section 3.2 and must be included with all distributions of the Source Code. Except to the extent prohibited by statute or regulation, such description must be sufficiently detailed for a recipient of ordinary skill to be able to understand it. 5.0 APPLICATION OF THIS LICENSE This License applies to code to which the Initial Developer has attached the notice in Exhibit A and to related Modifications as set out in Section 3.1. 6.0 VERSIONS OF THE LICENSE 6.1 New Versions. Sun may publish revised and/or new versions of the License from time to time. Each version will be given a distinguishing version number. 6.2 Effect of New Versions. Once Original Code has been published under a particular version of the License, You may always continue to use it under the terms of that version. You may also choose to use such Original Code under the terms of any subsequent version of the License published by Sun. No one other than Sun has the right to modify the terms applicable to Original Code. 7.0 DISCLAIMER OF WARRANTY ORIGINAL CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE ORIGINAL CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE ORIGINAL CODE IS WITH YOU. SHOULD ANY ORIGINAL CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL DEVELOPER) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY ORIGINAL CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. 8.0 TERMINATION 8.1 This License and the rights granted hereunder will terminate automatically if You fail to comply with terms herein and fail to cure such breach within 30 days of becoming aware of the breach. All sublicenses to the Original Code which are properly granted shall survive any termination of this License. Provisions which, by their nature, must remain in effect beyond the termination of this License shall survive. 8.2 In the event of termination under Section 8.1 above, all end user license agreements (excluding distributors and resellers) which have been validly granted by You or any distributor hereunder prior to termination shall survive termination. 9.0 LIMIT OF LIABILITY UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF ORIGINAL CODE, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. 10.0 U.S. GOVERNMENT END USERS U.S. Government: If this Software is being acquired by or on behalf of the U.S. Government or by a U.S. Government prime contractor or subcontractor (at any tier), then the Government's rights in the Software and accompanying documentation shall be only as set forth in this license; this is in accordance with 48 C.F.R. 227.7201 through 227.7202-4 (for Department of Defense (DoD) acquisitions) and with 48 C.F.R. 2.101 and 12.212 (for non-DoD acquisitions). 11.0 MISCELLANEOUS This License represents the complete agreement concerning subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. This License shall be governed by California law provisions (except to the extent applicable law, if any, provides otherwise), excluding its conflict-of-law provisions. With respect to disputes in which at least one party is a citizen of, or an entity chartered or registered to do business in the United States of America, any litigation relating to this License shall be subject to the jurisdiction of the Federal Courts of the Northern District of California, with venue lying in Santa Clara County, California, with the losing party responsible for costs, including without limitation, court costs and reasonable attorneys' fees and expenses. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any law or regulation which provides that the language of a contract shall be construed against the drafter shall not apply to this License. EXHIBIT A - Sun Standards License "The contents of this file are subject to the Sun Standards License Version 1.1 (the "License"); You may not use this file except in compliance with the License. You may obtain a copy of the License at _______________________________. Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for the specific language governing rights and limitations under the License. The Original Code is ______________________________________. The Initial Developer of the Original Code is: InMon Corp. Portions created by: _______________________________________ are Copyright (C): _______________________________________ All Rights Reserved. Contributor(s): _______________________________________ EXHIBIT B - Standards The Standard is defined as the following: sFlow Specification, located at [1]http://sflow.org/developers/specifications.php References 1. http://sflow.org/developers/specifications.php ---------------------------------------------------------------------- Retrieved from http://www.inmon.com/technology/sflowlicense.txt, 2011-12-12: LICENSE AGREEMENT PLEASE READ THIS LICENSE AGREEMENT ("AGREEMENT") CAREFULLY BEFORE REPRODUCING OR IN ANY WAY UTILIZING THE sFlow(R) SOFTWARE ("SOFTWARE") AND/OR ANY ACCOMPANYING DOCUMENTATION ("DOCUMENTATION") AND/OR THE RELATED SPECIFICATIONS ("SPECIFICATIONS"). YOUR REPRODUCTION OR USE OF THE SOFTWARE AND/OR THE DOCUMENTATION AND/OR THE SPECIFICATIONS CONSTITUTES YOUR ACCEPTANCE OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE TO BE BOUND BY THE TERMS AND CONDITIONS OF THIS AGREEMENT, YOU MAY NOT REPRODUCE OR IN ANY WAY UTILIZE THE SOFTWARE OR THE DOCUMENTATION OR THE SPECIFICATIONS. 1. Definitions. "Documentation" means the user manuals, training materials, and operating materials, if any, InMon provides to Licensee under this Agreement. "InMon" means InMon Corporation, its affiliates and subsidiaries. "Intellectual Property Rights" means any trade secrets, patents, including without limitation any patents covering the Software, copyrights, know-how, moral rights and similar rights of any type under the laws of any governmental authority, domestic or foreign, including all applications and registrations relating to any of the foregoing. "Licensee Hardware" means all computers, routers, or other equipment owned or controlled by or on behalf of Licensee. "Products" means any and all software applications, computers, routers, or other equipment manufactured by or on behalf of Licensee for the purpose of resale or lease to any other third party, or otherwise made available by Licensee free of charge. "Software" means the sFlow(R) software programs, in source or binary code format, that Licensee licenses from InMon under this Agreement and any bug fixes or error corrections which InMon may provide to Licensee. "Specifications" means the published specifications provided or otherwise made available by InMon at: http://www.sflow.org. "Trademark" means InMon's "sFlow(R)" trademark. 2. License Grant. 2.1 Software, Documentation and Specifications License Grant. InMon hereby grants to Licensee, under all of InMon's Intellectual Property Rights therein, a perpetual (subject to InMon's termination rights under Section 7 below), nonexclusive, royalty-free, worldwide, transferable, sublicensable license, to: (i) use and reproduce the Software, the Documentation, and the Specifications; (ii) modify the Software; (iii) implement the Specifications in the Products; (iv) install the Software, or software in which the Specifications have been implemented, on Licensee Hardware and Products, and (v) distribute any Products that include the Software, the Documentation, or software in which the Specifications have been implemented. 2.2 Trademark License. InMon hereby grants to Licensee a perpetual (subject to InMon's termination rights under Section 7 below), nonexclusive, royalty-free, worldwide, transferable, sublicensable license to use the Trademark on or in connection with the Software, the Documentation, the Specifications and any software that implements the Specifications. 2.3 Restrictions. Licensee agrees that it will not use the Software in a way inconsistent with the license granted in Section 2.1. Further, Licensee agrees that, in exercising its rights under the license granted to it in this Agreement, Licensee will: (i) strictly adhere to and fully comply with the Specifications; (ii) use the Trademark, and no other mark, to identify the Software, the Documentation, the Specifications and any Products that implement the Specifications; (iii) place, in a font or graphic design designated by InMon, the phrase "sFlow(R)" on any technical documentation, sales/marketing materials, catalogs, or other such materials relating to products it manufactures or markets which it has configured to be compatible with the Software or otherwise implement the Specifications; (iv) in connection with any Products shipped to or sold in other countries that include the Software or any software that implements the Specifications, comply with the patent and trademark laws and practice of such other country; and (v) not alter or impair any acknowledgment of copyright or trademark rights of InMon that may appear in or on the Software, the Documentation or the Specifications. In the event InMon determines that Licensee is not complying with its obligations under clauses (i)-(v) above, InMon shall notify Licensee of such non-compliance, and if Licensee fails to correct such non-compliance within three (3) months, InMon may immediately terminate this Agreement as provided under paragraph 7 below and pursue any and all actions and remedies as it deems necessary, including, but not limited to breach of contract. 3. Ownership. Except for the license expressly granted in Section 2, Inmon hereby retains all right, title, and interest in and to the Trademark and all its Intellectual Property Rights in the Software, the Documentation and the Specifications. Licensee obtains no rights hereunder in the Trademark, Software, Documentation or Specifications by implication, estoppel or otherwise. Licensee acknowledges that the Trademark, Software, Documentation and Specifications are being licensed and not sold under this Agreement, and that this Agreement does not transfer title in the Trademark, Software, Documentation or Specifications, or any copy thereof, to Licensee. 4. Support. Inmon shall have no obligation under this Agreement to (a) supply maintenance or support, bug fixes or error corrections to the Licensed Software, (b) supply future versions of the Licensed Software or (c) provide Licensed Software development tools to Licensee. 5. Warranty. INMON HEREBY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS, IMPLIED OR STATUTORY, WITH RESPECT TO THE TRADEMARK, THE SOFTWARE, THE DOCUMENTATION, THE SPECIFICATIONS. OR OTHERWISE, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT OF ANY INTELLECTUAL PROPERTY RIGHTS. 6. Limitation of Liability. IN NO EVENT SHALL INMON OR ITS SUPPLIERS OR LICENSORS BE LIABLE FOR ANY CONSEQUENTIAL, INCIDENTAL, SPECIAL, INDIRECT OR EXEMPLARY DAMAGES WHATSOEVER, WHETHER RELATED TO OR ARISING OUT OF THIS AGREEMENT, THE TRADEMARK, THE SOFTWARE, THE DOCUMENTATION, THE SPECIFICATIONS, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS INTERRUPTION, LOSS OF DATA, COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES OR FOR ANY CLAIM OR DEMAND AGAINST LICENSEE BY ANY OTHER PARTY, OR OTHER PECUNIARY LOSS, EVEN IF INMON HAS BEEN ADVISED OF OR KNOWS OF THE POSSIBILITY OF SUCH DAMAGES. 7. Term and Termination. The term of this Agreement will begin on the Effective Date, which shall be deemed to be the date of delivery of the Software and/or Documentation and/or Specifications to Licensee, and shall continue indefinitely unless and until terminated by Licensee's giving written notice of termination to InMon, or by InMon pursuant to InMon's termination rights as set forth in Section 2.3 above. Upon any termination of this Agreement, Licensee shall cease exercising its license rights under this Agreement, including the right to distribute Products that incorporate the Software or Documentation or that implement the Specifications. The rights and obligations contained in Sections 1, 3, 5, 6, 7, and 8 shall survive any termination of this Agreement. 8. General Provisions. 8.1 Assignment. This Agreement shall be binding upon and inure to the benefit of the parties hereto and their permitted successors and permitted assigns. InMon will have the right to assign this Agreement without notice to Licensee. Licensee may assign or transfer (whether by merger, operation of law or in any other manner) any of its rights or delegate any of its obligations hereunder without the prior written consent of InMon, provided the assignee assumes in writing all of Licensee's obligations hereunder. 8.2 Notices. All notices permitted or required under this Agreement shall be in writing and shall be delivered in person or mailed by first class, registered or certified mail, postage prepaid, to the address of the party specified in this Agreement or such other address as either party may specify in writing. Such notice shall be deemed to have been given upon receipt. 8.3 Non-Waiver. No term or provision hereof shall be deemed waived, and no breach excused, unless such waiver or consent shall be in writing and signed by the party claimed to have waived or consented. Any consent or waiver, whether express or implied, shall not constitute a consent or waiver of, or excuse for any separate, different or subsequent breach. 8.4 Independent Contractor. The parties' relationship shall be solely that of independent contractors, and nothing contained in this Agreement shall be construed to make either party an agent, partner, representative or principal of the other for any purpose. 8.5 Choice of Law and Forum. This Agreement shall be governed by and construed under the laws of the State of California, without giving effect to such state's conflict of laws principles. The parties hereby submit to the personal jurisdiction of, and agree that any legal proceeding with respect to or arising under this Agreement shall be brought in, the United States District Court for the Northern District of California or the state courts of the State of California for the County of San Francisco. 8.6 U.S. Government Licenses. The Software and Documentation are considered a "commercial item" as that term is defined at 48 C.F.R 2.101, or "commercial computer software" and "commercial computer software documentation" as such terms are used in 48 C.F.R 12.212 of the Federal Acquisition Regulations and its successors, and 48 C.F.R. 227.7202 of the DoD FAR Supplement and its successors. 8.7 Severability. If any provision of this Agreement is held to be unenforceable under applicable law, then such provision shall be excluded from this Agreement and the balance of this Agreement shall be interpreted as if such provision were so excluded and shall be enforceable in accordance with its terms. The court in its discretion may substitute for the excluded provision an enforceable provision which in economic substance reasonably approximates the excluded provision. 8.8 Compliance With Law. Licensee shall comply with all applicable laws and regulations (including privacy laws and regulations) having application to or governing its use and/or operation of the Software and agrees to indemnify and hold InMon harmless from and against any claims, damages, losses or obligations suffered or incurred by InMon arising from its failure to so comply. 8.9 Entire Agreement; Amendment. This Agreement constitutes the final, complete and entire agreement between the parties with respect to the subject matter hereof, and supersedes any previous proposals, negotiations, agreements, or arrangements, whether verbal or written, made between the parties with respect to such subject matter. This Agreement shall control over any additional or conflicting terms in any of Licensee's purchase orders or other business forms. This Agreement may only be amended or modified by mutual agreement of authorized representatives of the parties in writing. InMon Corp. 580 California Street, 5th Floor, San Francisco, CA 94104 Phone: (415) 283-3260 URL: www.inmon.com Email: info@inmon.com openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-pki.dirs0000644000000000000000000000013212127012313021060 xustar0030 mtime=1364989131.698833469 30 atime=1456592667.335091389 30 ctime=1456594659.985280076 openvswitch-2.5.0/debian/openvswitch-pki.dirs0000664000175000017500000000002512127012313022545 0ustar00jpettitjpettit00000000000000/var/lib/openvswitch openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-vtep.default0000644000000000000000000000013212631676263021762 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.013281253 openvswitch-2.5.0/debian/openvswitch-vtep.default0000664000175000017500000000020212631676263023444 0ustar00jpettitjpettit00000000000000# This is a POSIX shell fragment -*- sh -*- # ENABLE_OVS_VTEP: Whether to start ovs-vtep. ENABLE_OVS_VTEP="false" openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-ipsec.init0000644000000000000000000000013212631676263021426 xustar0030 mtime=1449622707.094443686 30 atime=1456592667.343091717 30 ctime=1456594659.985280076 openvswitch-2.5.0/debian/openvswitch-ipsec.init0000775000175000017500000001360712631676263023130 0ustar00jpettitjpettit00000000000000#!/bin/sh # # Copyright (c) 2007, 2009 Javier Fernandez-Sanguino # # This is free software; you may redistribute it and/or modify # it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2, # or (at your option) any later version. # # This is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License with # the Debian operating system, in /usr/share/common-licenses/GPL; if # not, write to the Free Software Foundation, Inc., 59 Temple Place, # Suite 330, Boston, MA 02111-1307 USA # ### BEGIN INIT INFO # Provides: openvswitch-ipsec # Required-Start: $network $local_fs $remote_fs openvswitch-switch # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Open vSwitch GRE-over-IPsec daemon # Description: The ovs-monitor-ipsec script provides support for encrypting GRE # tunnels with IPsec. ### END INIT INFO PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/share/openvswitch/scripts/ovs-monitor-ipsec # Daemon's location NAME=ovs-monitor-ipsec # Introduce the short server's name here LOGDIR=/var/log/openvswitch # Log directory to use PIDFILE=/var/run/openvswitch/$NAME.pid test -x $DAEMON || exit 0 . /lib/lsb/init-functions DODTIME=10 # Time to wait for the server to die, in seconds # If this value is set too low you might not # let some servers to die gracefully and # 'restart' will not work set -e running_pid() { # Check if a given process pid's cmdline matches a given name pid=$1 name=$2 [ -z "$pid" ] && return 1 [ ! -d /proc/$pid ] && return 1 cmd=`cat /proc/$pid/cmdline | tr "\000" " "|cut -d " " -f 2` # Is this the expected server [ "$cmd" != "$name" ] && return 1 return 0 } running() { # Check if the process is running looking at /proc # (works for all users) # No pidfile, probably no daemon present [ ! -f "$PIDFILE" ] && return 1 pid=`cat $PIDFILE` running_pid $pid $DAEMON || return 1 return 0 } uninstall_mark_rule() { iptables -D INPUT -t mangle $1 -j MARK --set-mark 1/1 || return 0 } install_mark_rule() { if ( ! iptables -C INPUT -t mangle $1 -j MARK --set-mark 1/1 2> /dev/null); then iptables -A INPUT -t mangle $1 -j MARK --set-mark 1/1 fi } start_server() { if [ ! -d /var/run/openvswitch ]; then install -d -m 755 -o root -g root /var/run/openvswitch fi install_mark_rule "-p esp" install_mark_rule "-p udp --dport 4500" /usr/share/openvswitch/scripts/ovs-monitor-ipsec \ --pidfile=$PIDFILE --log-file --detach --monitor \ unix:/var/run/openvswitch/db.sock return 0 } stop_server() { if [ -e $PIDFILE ]; then kill `cat $PIDFILE` fi uninstall_mark_rule "-p esp" uninstall_mark_rule "-p udp --dport 4500" return 0 } force_stop() { # Force the process to die killing it manually [ ! -e "$PIDFILE" ] && return if running ; then kill -15 $pid # Is it really dead? sleep "$DODTIME" if running ; then kill -9 $pid sleep "$DODTIME" if running ; then echo "Cannot kill $NAME (pid=$pid)!" exit 1 fi fi fi rm -f $PIDFILE } case "$1" in start) log_daemon_msg "Starting $NAME" # Check if it's running first if running ; then log_progress_msg "apparently already running" log_end_msg 0 exit 0 fi if start_server && running ; then # It's ok, the server started and is running log_end_msg 0 else # Either we could not start it or it is not running # after we did # NOTE: Some servers might die some time after they start, # this code does not try to detect this and might give # a false positive (use 'status' for that) log_end_msg 1 fi ;; stop) log_daemon_msg "Stopping $NAME" if running ; then # Only stop the server if we see it running stop_server log_end_msg $? else # If it's not running don't do anything log_progress_msg "apparently not running" log_end_msg 0 exit 0 fi ;; force-stop) # First try to stop gracefully the program $0 stop if running; then # If it's still running try to kill it more forcefully log_daemon_msg "Stopping (force) $NAME" force_stop log_end_msg $? fi ;; restart|force-reload) log_daemon_msg "Restarting $NAME" stop_server # Wait some sensible amount, some server need this [ -n "$DODTIME" ] && sleep $DODTIME start_server running log_end_msg $? ;; status) log_daemon_msg "Checking status of $NAME" if running ; then log_progress_msg "running" log_end_msg 0 else log_progress_msg "apparently not running" log_end_msg 1 exit 1 fi ;; # Use this if the daemon cannot reload reload) log_warning_msg "Reloading $NAME daemon: not implemented, as the daemon" log_warning_msg "cannot re-read the config file (use restart)." ;; *) N=/etc/init.d/openvswitch-ipsec echo "Usage: $N {start|stop|force-stop|restart|force-reload|status}" >&2 exit 1 ;; esac exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.links0000644000000000000000000000013212631676263022001 xustar0030 mtime=1449622707.102443967 30 atime=1456592667.335091389 30 ctime=1456594659.997280581 openvswitch-2.5.0/debian/openvswitch-switch.links0000664000175000017500000000023712631676263023473 0ustar00jpettitjpettit00000000000000usr/share/openvswitch/scripts/ifupdown.sh etc/network/if-post-down.d/openvswitch usr/share/openvswitch/scripts/ifupdown.sh etc/network/if-pre-up.d/openvswitch openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-vtep.init0000644000000000000000000000013212631676263021301 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.017281422 openvswitch-2.5.0/debian/openvswitch-vtep.init0000664000175000017500000000370612631676263022777 0ustar00jpettitjpettit00000000000000#!/bin/sh ### BEGIN INIT INFO # Provides: openvswitch-vtep # Required-Start: $network $named $remote_fs $syslog # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Open vSwitch VTEP emulator # Description: Initializes the Open vSwitch VTEP emulator ### END INIT INFO # Include defaults if available default=/etc/default/openvswitch-vtep if [ -f $default ] ; then . $default fi start () { if [ "$ENABLE_OVS_VTEP" = "false" ]; then exit 0 fi update-rc.d -f openvswitch-switch remove >/dev/null 2>&1 /etc/init.d/openvswitch-switch stop mkdir -p "/var/run/openvswitch" if [ ! -e "/etc/openvswitch/conf.db" ]; then ovsdb-tool create /etc/openvswitch/conf.db /usr/share/openvswitch/vswitch.ovsschema fi if [ ! -e "/etc/openvswitch/vtep.db" ]; then ovsdb-tool create /etc/openvswitch/vtep.db /usr/share/openvswitch/vtep.ovsschema fi if [ ! -e "/etc/openvswitch/ovsclient-cert.pem" ]; then export RANDFILE="/root/.rnd" cd /etc/openvswitch && ovs-pki req ovsclient && ovs-pki self-sign ovsclient fi ovsdb-server --pidfile --detach --log-file --remote \ punix:/var/run/openvswitch/db.sock \ --remote=db:hardware_vtep,Global,managers \ --private-key=/etc/openvswitch/ovsclient-privkey.pem \ --certificate=/etc/openvswitch/ovsclient-cert.pem \ --bootstrap-ca-cert=/etc/openvswitch/vswitchd.cacert \ /etc/openvswitch/conf.db /etc/openvswitch/vtep.db modprobe openvswitch ovs-vswitchd --pidfile --detach --log-file \ unix:/var/run/openvswitch/db.sock } stop () { /etc/init.d/openvswitch-switch stop } case $1 in start) start ;; stop) stop ;; restart|force-reload) stop start ;; *) echo "Usage: $0 {start|stop|restart|force-reload}" >&2 exit 1 ;; esac exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/source0000644000000000000000000000013212664357344016314 xustar0030 mtime=1456594660.025281758 30 atime=1456594661.701352216 30 ctime=1456594660.025281758 openvswitch-2.5.0/debian/source/0000775000175000017500000000000012664357344020061 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/debian/source/PaxHeaders.69223/format0000644000000000000000000000013211776774137017612 xustar0030 mtime=1341913183.440755827 30 atime=1456592667.343091717 30 ctime=1456594660.025281758 openvswitch-2.5.0/debian/source/format0000664000175000017500000000001411776774137021275 0ustar00jpettitjpettit000000000000003.0 (quilt) openvswitch-2.5.0/debian/PaxHeaders.69223/compat0000644000000000000000000000013212127012313016251 xustar0030 mtime=1364989131.694833468 30 atime=1456592667.331091225 30 ctime=1456594659.965279236 openvswitch-2.5.0/debian/compat0000664000175000017500000000000212127012313017731 0ustar00jpettitjpettit000000000000008 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.postinst0000644000000000000000000000013212631676263022544 xustar0030 mtime=1449622707.102443967 30 atime=1456592667.335091389 30 ctime=1456594659.997280581 openvswitch-2.5.0/debian/openvswitch-switch.postinst0000775000175000017500000000324512631676263024243 0ustar00jpettitjpettit00000000000000#!/bin/sh # postinst script for openvswitch-switch # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `configure' # * `abort-upgrade' # * `abort-remove' `in-favour' # # * `abort-remove' # * `abort-deconfigure' `in-favour' # `removing' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in configure) DEFAULT=/etc/default/openvswitch-switch TEMPLATE=/usr/share/openvswitch/switch/default.template if ! test -e $DEFAULT; then cp $TEMPLATE $DEFAULT else for var in $(awk -F'[ :]' '/^# [_A-Z0-9]+:/{print $2}' $TEMPLATE) do if ! grep $var $DEFAULT >/dev/null 2>&1; then echo >> $DEFAULT sed -n "/$var:/,/$var=/p" $TEMPLATE >> $DEFAULT fi done fi ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac # Do not fail package installation just because the kernel module # is not available. OVS_MISSING_KMOD_OK=yes export OVS_MISSING_KMOD_OK # force-reload-kmod during upgrade. If a user wants to override this, # they can set the variable OVS_FORCE_RELOAD_KMOD=no while installing. [ -z "${OVS_FORCE_RELOAD_KMOD}" ] && OVS_FORCE_RELOAD_KMOD=yes || true export OVS_FORCE_RELOAD_KMOD #DEBHELPER# exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.template0000644000000000000000000000013212631270735022466 xustar0030 mtime=1449488861.319997842 30 atime=1456592667.335091389 30 ctime=1456594659.997280581 openvswitch-2.5.0/debian/openvswitch-switch.template0000664000175000017500000000045012631270735024155 0ustar00jpettitjpettit00000000000000# This is a POSIX shell fragment -*- sh -*- # FORCE_COREFILES: If 'yes' then core files will be enabled. # FORCE_COREFILES=yes # OVS_CTL_OPTS: Extra options to pass to ovs-ctl. This is, for example, # a suitable place to specify --ovs-vswitchd-wrapper=valgrind. # OVS_CTL_OPTS= openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.default0000644000000000000000000000013212631676263024067 xustar0030 mtime=1449622707.106444108 30 atime=1456592667.335091389 30 ctime=1456594660.005280915 openvswitch-2.5.0/debian/openvswitch-testcontroller.default0000664000175000017500000000175312631676263025565 0ustar00jpettitjpettit00000000000000# This is a POSIX shell fragment -*- sh -*- # LISTEN: What OpenFlow connection methods should the controller listen on? # # This is a space-delimited list of connection methods: # # * "pssl:[PORT]": Listen for SSL connections on the specified PORT # (default: 6653). The private key, certificate, and CA certificate # must be specified below. # # * "ptcp:[PORT]": Listen for TCP connections on the specified PORT # (default: 6653). Not recommended for security reasons. # LISTEN="pssl:" # PRIVKEY: Name of file containing controller's private key. # Required if SSL enabled. PRIVKEY=/etc/openvswitch-testcontroller/privkey.pem # CERT: Name of file containing certificate for private key. # Required if SSL enabled. CERT=/etc/openvswitch-testcontroller/cert.pem # CACERT: Name of file containing switch CA certificate. # Required if SSL enabled. CACERT=/etc/openvswitch-testcontroller/cacert.pem # Additional options to pass to ovs-testcontroller, e.g. "--hub" DAEMON_OPTS="" openvswitch-2.5.0/debian/PaxHeaders.69223/dkms.conf.in0000644000000000000000000000013212631676263017301 xustar0030 mtime=1449622707.090443546 30 atime=1456592667.331091225 30 ctime=1456594659.969279403 openvswitch-2.5.0/debian/dkms.conf.in0000664000175000017500000000057112631676263020774 0ustar00jpettitjpettit00000000000000MODULES=( __MODULES__ ) PACKAGE_NAME="openvswitch" PACKAGE_VERSION="__VERSION__" MAKE="./configure --with-linux='${kernel_source_dir}' && make -C datapath/linux" for __idx in ${!MODULES[@]}; do BUILT_MODULE_NAME[__idx]=${MODULES[__idx]} BUILT_MODULE_LOCATION[__idx]=datapath/linux/ DEST_MODULE_LOCATION[__idx]=/kernel/drivers/net/openvswitch/ done AUTOINSTALL=yes openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-datapath-source.README.Debian0000644000000000000000000000013211776774137024572 xustar0030 mtime=1341913183.408755824 30 atime=1456592667.335091389 30 ctime=1456594659.977279738 openvswitch-2.5.0/debian/openvswitch-datapath-source.README.Debian0000664000175000017500000000154411776774137026266 0ustar00jpettitjpettit00000000000000Open vSwitch for Debian ---------------------- * How do I build this module the Debian way? - Building with module-assistant: $ module-assistant auto-install openvswitch-datapath or $ m-a a-i openvswitch-datapath If kernel source or headers are in a non-standard directory, add the option -k /path/to/kernel/source with the correct path. - Building with make-kpkg $ cd /usr/src/ $ tar jxvf openvswitch.tar.bz2 $ cd /usr/src/kernel-source-2.6.26 $ make-kpkg --added-modules=openvswitch modules - Building without make-kpkg $ cd /usr/src/ $ tar jxvf openvswitch.tar.bz2 $ cd modules/openvswitch $ fakeroot debian/rules kdist_image If you run this as root, fakeroot is not needed. -- Ben Pfaff , Wed, 22 Jun 2011 09:51:28 -0700 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.manpages0000644000000000000000000000013212631676263024236 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.009281083 openvswitch-2.5.0/debian/openvswitch-testcontroller.manpages0000664000175000017500000000003712631676263025726 0ustar00jpettitjpettit00000000000000utilities/ovs-testcontroller.8 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-test.install0000644000000000000000000000013212631676263022005 xustar0030 mtime=1449622707.102443967 30 atime=1456592667.335091389 30 ctime=1456594660.001280748 openvswitch-2.5.0/debian/openvswitch-test.install0000664000175000017500000000015212631676263023473 0ustar00jpettitjpettit00000000000000usr/bin/ovs-l3ping usr/bin/ovs-test usr/share/openvswitch/python/ovstest usr/lib/python2.7/dist-packages/ openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-datapath-source.copyright0000644000000000000000000000013212130751561024441 xustar0030 mtime=1365496689.370878591 30 atime=1456592667.335091389 30 ctime=1456594659.981279906 openvswitch-2.5.0/debian/openvswitch-datapath-source.copyright0000664000175000017500000000052712130751561026135 0ustar00jpettitjpettit00000000000000Upstream Authors: Nicira, Inc. Copyright: Copyright (C) 2008 Nicira, Inc. License: Files in the datapath/ and its sub-directories are covered under the GNU General Public License Version 2. On Debian systems, the complete text of the GNU General Public License can be found in `/usr/share/common-licenses/GPL'. openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-ipsec.install0000644000000000000000000000013211674446641022132 xustar0030 mtime=1324502433.550026265 30 atime=1456592667.335091389 30 ctime=1456594659.985280076 openvswitch-2.5.0/debian/openvswitch-ipsec.install0000664000175000017500000000006711674446641023625 0ustar00jpettitjpettit00000000000000debian/ovs-monitor-ipsec usr/share/openvswitch/scripts openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-test.manpages0000644000000000000000000000013212631676263022132 xustar0030 mtime=1449622707.102443967 30 atime=1456592667.335091389 30 ctime=1456594660.001280748 openvswitch-2.5.0/debian/openvswitch-test.manpages0000664000175000017500000000005412631676263023621 0ustar00jpettitjpettit00000000000000utilities/ovs-l3ping.8 utilities/ovs-test.8 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.install0000644000000000000000000000013212631676263024111 xustar0030 mtime=1449622707.110444249 30 atime=1456592667.335091389 30 ctime=1456594660.009281083 openvswitch-2.5.0/debian/openvswitch-testcontroller.install0000664000175000017500000000003312631676263025575 0ustar00jpettitjpettit00000000000000usr/bin/ovs-testcontroller openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.init0000644000000000000000000000013212664352753021625 xustar0030 mtime=1456592363.438620837 30 atime=1456592368.174815358 30 ctime=1456594659.993280413 openvswitch-2.5.0/debian/openvswitch-switch.init0000775000175000017500000001055612664352753023327 0ustar00jpettitjpettit00000000000000#! /bin/sh # # Copyright (C) 2011, 2012 Nicira, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ### BEGIN INIT INFO # Provides: openvswitch-switch # Required-Start: $network $named $remote_fs $syslog # Required-Stop: $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Open vSwitch switch # Description: openvswitch-switch provides the userspace components and utilities for # the Open vSwitch kernel-based switch. ### END INIT INFO (test -x /usr/sbin/ovs-vswitchd && test -x /usr/sbin/ovsdb-server) || exit 0 _SYSTEMCTL_SKIP_REDIRECT=yes . /usr/share/openvswitch/scripts/ovs-lib test -e /etc/default/openvswitch-switch && . /etc/default/openvswitch-switch network_interfaces () { INTERFACES="/etc/network/interfaces" [ -e "${INTERFACES}" ] || return bridges=`ifquery --allow ovs --list` [ -n "${bridges}" ] && $1 --allow=ovs ${bridges} } load_kmod () { ovs_ctl load-kmod || exit $? } start () { if ovs_ctl load-kmod; then : else echo "Module has probably not been built for this kernel." if ! test -d /usr/share/doc/openvswitch-datapath-source; then echo "Install the openvswitch-datapath-source package, then read" else echo "For instructions, read" fi echo "/usr/share/doc/openvswitch-datapath-source/README.Debian" if test X"$OVS_MISSING_KMOD_OK" = Xyes; then # We're being invoked by the package postinst. Do not # fail package installation just because the kernel module # is not available. exit 0 fi fi set ovs_ctl ${1-start} --system-id=random if test X"$FORCE_COREFILES" != X; then set "$@" --force-corefiles="$FORCE_COREFILES" fi set "$@" $OVS_CTL_OPTS "$@" || exit $? if [ "$2" = "start" ] && [ "$READ_INTERFACES" != "no" ]; then network_interfaces ifup fi } stop () { [ "$READ_INTERFACES" != "no" ] && network_interfaces ifdown ovs_ctl stop } restart () { # OVS_FORCE_RELOAD_KMOD can be set by package postinst script. if [ "$1" = "--save-flows=yes" ] || \ [ "${OVS_FORCE_RELOAD_KMOD}" = "no" ]; then start restart elif [ "${OVS_FORCE_RELOAD_KMOD}" = "yes" ]; then depmod -a if [ -e /sys/module/openvswitch ]; then LOADED_SRCVERSION=`cat /sys/module/openvswitch/srcversion` LOADED_VERSION=`cat /sys/module/openvswitch/version` elif [ -e /sys/module/openvswitch_mod ]; then LOADED_SRCVERSION=`cat /sys/module/openvswitch_mod/srcversion` LOADED_VERSION=`cat /sys/module/openvswitch_mod/version` fi SRCVERSION=`modinfo -F srcversion openvswitch 2>/dev/null` VERSION=`modinfo -F version openvswitch 2>/dev/null` ovs_ctl_log "Package upgrading:\n"\ "Loaded version: ${LOADED_VERSION} ${LOADED_SRCVERSION}.\n"\ "Version on disk: ${VERSION} ${SRCVERSION}." # If the kernel module was previously loaded and it is different than # the kernel module on disk, then do a 'force-reload-kmod'. if [ -n "${LOADED_SRCVERSION}" ] && [ -n "${SRCVERSION}" ] && \ [ "${SRCVERSION}" != "${LOADED_SRCVERSION}" ]; then start force-reload-kmod else start restart fi else READ_INTERFACES="no" stop READ_INTERFACES="no" start fi } case $1 in start) start ;; stop | force-stop) stop ;; reload | force-reload) # The OVS daemons keep up-to-date. ;; restart) shift restart "$@" ;; status) ovs_ctl status exit $? ;; force-reload-kmod) start force-reload-kmod ;; load-kmod) load_kmod ;; *) echo "Usage: $0 {start|stop|restart|force-reload|status|force-stop|force-reload-kmod|load-kmod}" >&2 exit 1 ;; esac exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/python-openvswitch.dirs0000644000000000000000000000013111776774137021651 xustar0030 mtime=1341913183.436755826 30 atime=1456592667.339091552 29 ctime=1456594660.02128159 openvswitch-2.5.0/debian/python-openvswitch.dirs0000664000175000017500000000006311776774137023341 0ustar00jpettitjpettit00000000000000usr/share/pyshared/ovs/ usr/share/pyshared/ovs/db/ openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-datapath-dkms.prerm0000644000000000000000000000013211776774137023237 xustar0030 mtime=1341913183.408755824 30 atime=1456592667.335091389 30 ctime=1456594659.977279738 openvswitch-2.5.0/debian/openvswitch-datapath-dkms.prerm0000664000175000017500000000037411776774137024733 0ustar00jpettitjpettit00000000000000#!/bin/sh set -e package=openvswitch-datapath-dkms name=openvswitch version=`dpkg-query -W -f='${Version}' "$package" \ |rev|cut -d- -f2-|rev|cut -d':' -f2|tr -d "\n"` dkms remove -m "$name" -v "$version" --all || true #DEBHELPER# exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/control.modules.in0000644000000000000000000000013211674446641020547 xustar0030 mtime=1324502433.550026265 30 atime=1456592667.331091225 30 ctime=1456594659.965279236 openvswitch-2.5.0/debian/control.modules.in0000664000175000017500000000137211674446641022242 0ustar00jpettitjpettit00000000000000Source: openvswitch Section: net Priority: extra Maintainer: Open vSwitch developers Build-Depends: debhelper (>= 5.0.37) Standards-Version: 3.7.3 Package: openvswitch-datapath-module-_KVERS_ Architecture: any Recommends: kernel-image-_KVERS_, openvswitch-switch Provides: openvswitch-datapath-module Description: Open vSwitch Linux datapath kernel module This package contains the Open vSwitch loadable datapath kernel modules for the kernel-image-_KVERS_ package. . If you compiled a custom kernel, you will most likely need to compile a custom version of this module as well. The openvswitch-datapath-source package has been provided for this purpose. Refer to README.Debian provided in that package for further instructions. openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-ipsec.dirs0000644000000000000000000000013211674446641021425 xustar0030 mtime=1324502433.550026265 30 atime=1456592667.343091717 30 ctime=1456594659.981279906 openvswitch-2.5.0/debian/openvswitch-ipsec.dirs0000664000175000017500000000003611674446641023114 0ustar00jpettitjpettit00000000000000usr/share/openvswitch/scripts openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-pki.postinst0000644000000000000000000000013112663320001022002 xustar0029 mtime=1456316417.49493277 30 atime=1456592667.335091389 30 ctime=1456594659.989280245 openvswitch-2.5.0/debian/openvswitch-pki.postinst0000775000175000017500000000175312663320001023504 0ustar00jpettitjpettit00000000000000#!/bin/sh # postinst script for openvswitch-pki # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `configure' # * `abort-upgrade' # * `abort-remove' `in-favour' # # * `abort-remove' # * `abort-deconfigure' `in-favour' # `removing' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in configure) # Create certificate authorities. if test ! -e /var/lib/openvswitch/pki; then ovs-pki init fi ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "postinst called with unknown argument \`$1'" >&2 exit 1 ;; esac #DEBHELPER# exit 0 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-testcontroller.dirs0000644000000000000000000000013212631676263023404 xustar0030 mtime=1449622707.106444108 30 atime=1456592667.335091389 30 ctime=1456594660.005280915 openvswitch-2.5.0/debian/openvswitch-testcontroller.dirs0000664000175000017500000000003712631676263025074 0ustar00jpettitjpettit00000000000000etc/openvswitch-testcontroller openvswitch-2.5.0/debian/PaxHeaders.69223/dirs0000644000000000000000000000013211674446641015754 xustar0030 mtime=1324502433.550026265 30 atime=1456592667.331091225 30 ctime=1456594659.969279403 openvswitch-2.5.0/debian/dirs0000664000175000017500000000002111674446641017435 0ustar00jpettitjpettit00000000000000usr/bin usr/sbin openvswitch-2.5.0/debian/PaxHeaders.69223/automake.mk0000644000000000000000000000013212664352753017227 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594659.577262924 openvswitch-2.5.0/debian/automake.mk0000664000175000017500000000537312664352753020727 0ustar00jpettitjpettit00000000000000EXTRA_DIST += \ debian/changelog \ debian/compat \ debian/control \ debian/control.modules.in \ debian/copyright \ debian/copyright.in \ debian/dkms.conf.in \ debian/dirs \ debian/openvswitch-common.dirs \ debian/openvswitch-common.docs \ debian/openvswitch-common.install \ debian/openvswitch-common.manpages \ debian/openvswitch-datapath-module-_KVERS_.postinst.modules.in \ debian/openvswitch-datapath-dkms.postinst \ debian/openvswitch-datapath-dkms.prerm \ debian/openvswitch-datapath-source.README.Debian \ debian/openvswitch-datapath-source.copyright \ debian/openvswitch-datapath-source.dirs \ debian/openvswitch-datapath-source.install \ debian/openvswitch-ipsec.dirs \ debian/openvswitch-ipsec.init \ debian/openvswitch-ipsec.install \ debian/openvswitch-pki.dirs \ debian/openvswitch-pki.postinst \ debian/openvswitch-pki.postrm \ debian/openvswitch-switch.README.Debian \ debian/openvswitch-switch.dirs \ debian/openvswitch-switch.init \ debian/openvswitch-switch.install \ debian/openvswitch-switch.logrotate \ debian/openvswitch-switch.manpages \ debian/openvswitch-switch.postinst \ debian/openvswitch-switch.postrm \ debian/openvswitch-switch.template \ debian/openvswitch-switch.links \ debian/openvswitch-test.dirs \ debian/openvswitch-test.install \ debian/openvswitch-test.manpages \ debian/openvswitch-testcontroller.README.Debian \ debian/openvswitch-testcontroller.default \ debian/openvswitch-testcontroller.dirs \ debian/openvswitch-testcontroller.init \ debian/openvswitch-testcontroller.install \ debian/openvswitch-testcontroller.manpages \ debian/openvswitch-testcontroller.postinst \ debian/openvswitch-testcontroller.postrm \ debian/openvswitch-vtep.default \ debian/openvswitch-vtep.dirs \ debian/openvswitch-vtep.init \ debian/openvswitch-vtep.install \ debian/openvswitch-vtep.manpages \ debian/ovs-monitor-ipsec \ debian/python-openvswitch.dirs \ debian/python-openvswitch.install \ debian/rules \ debian/rules.modules \ debian/ifupdown.sh \ debian/source/format check-debian-changelog-version: @DEB_VERSION=`echo '$(VERSION)' | sed 's/pre/~pre/'`; \ if $(FGREP) '($(DEB_VERSION)' $(srcdir)/debian/changelog >/dev/null; \ then \ :; \ else \ echo "Update debian/changelog to mention version $(VERSION)"; \ exit 1; \ fi ALL_LOCAL += check-debian-changelog-version DIST_HOOKS += check-debian-changelog-version $(srcdir)/debian/copyright: AUTHORS debian/copyright.in $(AM_V_GEN) \ { sed -n -e '/%AUTHORS%/q' -e p < $(srcdir)/debian/copyright.in; \ sed '1,/^$$/d' $(srcdir)/AUTHORS | \ sed -n -e '/^$$/q' -e 's/^/ /p'; \ sed -e '1,/%AUTHORS%/d' $(srcdir)/debian/copyright.in; \ } > $@ DISTCLEANFILES += debian/copyright openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.manpages0000644000000000000000000000013212631676263022454 xustar0030 mtime=1449622707.102443967 30 atime=1456592667.335091389 30 ctime=1456594659.993280413 openvswitch-2.5.0/debian/openvswitch-switch.manpages0000664000175000017500000000036012631676263024143 0ustar00jpettitjpettit00000000000000ovsdb/ovsdb-server.1 utilities/ovs-ctl.8 utilities/ovs-dpctl-top.8 utilities/ovs-dpctl.8 utilities/ovs-pcap.1 utilities/ovs-tcpundump.1 utilities/ovs-vlan-test.8 utilities/ovs-vsctl.8 vswitchd/ovs-vswitchd.8 vswitchd/ovs-vswitchd.conf.db.5 openvswitch-2.5.0/debian/PaxHeaders.69223/openvswitch-switch.postrm0000644000000000000000000000013212631270603022171 xustar0030 mtime=1449488771.915992872 30 atime=1456592667.335091389 30 ctime=1456594659.997280581 openvswitch-2.5.0/debian/openvswitch-switch.postrm0000775000175000017500000000236412631270603023671 0ustar00jpettitjpettit00000000000000#!/bin/sh # postrm script for openvswitch-switch # # see: dh_installdeb(1) set -e # summary of how this script can be called: # * `remove' # * `purge' # * `upgrade' # * `failed-upgrade' # * `abort-install' # * `abort-install' # * `abort-upgrade' # * `disappear' # # for details, see http://www.debian.org/doc/debian-policy/ or # the debian-policy package case "$1" in purge) rm -f /etc/openvswitch/conf.db rm -f /etc/openvswitch/.conf.db.~lock~ rm -f /etc/default/openvswitch-switch rm -f /var/log/openvswitch/ovs-vswitchd.log* || true rm -f /var/log/openvswitch/ovsdb-server.log* || true rm -f /etc/openvswitch/system-id.conf ;; remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "postrm called with unknown argument \`$1'" >&2 exit 1 ;; esac # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. #DEBHELPER# exit 0 openvswitch-2.5.0/PaxHeaders.69223/CONTRIBUTING.md0000644000000000000000000000013212664352753016077 xustar0030 mtime=1456592363.422620179 30 atime=1456592368.170815194 30 ctime=1456594659.641265614 openvswitch-2.5.0/CONTRIBUTING.md0000664000175000017500000003424412664352753017576 0ustar00jpettitjpettit00000000000000How to Submit Patches for Open vSwitch ====================================== Send changes to Open vSwitch as patches to dev@openvswitch.org. One patch per email, please. More details are included below. If you are using Git, then `git format-patch` takes care of most of the mechanics described below for you. Before You Start ---------------- Before you send patches at all, make sure that each patch makes sense. In particular: - A given patch should not break anything, even if later patches fix the problems that it causes. The source tree should still build and work after each patch is applied. (This enables `git bisect` to work best.) - A patch should make one logical change. Don't make multiple, logically unconnected changes to disparate subsystems in a single patch. - A patch that adds or removes user-visible features should also update the appropriate user documentation or manpages. Check "Feature Deprecation Guidelines" section in this document if you intend to remove user-visible feature. Testing is also important: - A patch that modifies existing code should be tested with `make check` before submission. - A patch that adds or deletes files should also be tested with `make distcheck` before submission. - A patch that modifies Linux kernel code should be at least build-tested on various Linux kernel versions before submission. I suggest versions 2.6.32 and whatever the current latest release version is at the time. - A patch that modifies the ofproto or vswitchd code should be tested in at least simple cases before submission. - A patch that modifies xenserver code should be tested on XenServer before submission. If you are using GitHub, then you may utilize the travis-ci.org CI build system by linking your GitHub repository to it. This will run some of the above tests automatically when you push changes to your repository. See the "Continuous Integration with Travis-CI" in the [INSTALL.md] file for details on how to set it up. Email Subject ------------- The subject line of your email should be in the following format: `[PATCH /] : ` - `[PATCH /]` indicates that this is the nth of a series of m patches. It helps reviewers to read patches in the correct order. You may omit this prefix if you are sending only one patch. - `:` indicates the area of the Open vSwitch to which the change applies (often the name of a source file or a directory). You may omit it if the change crosses multiple distinct pieces of code. - `` briefly describes the change. The subject, minus the `[PATCH /]` prefix, becomes the first line of the commit's change log message. Description ----------- The body of the email should start with a more thorough description of the change. This becomes the body of the commit message, following the subject. There is no need to duplicate the summary given in the subject. Please limit lines in the description to 79 characters in width. The description should include: - The rationale for the change. - Design description and rationale (but this might be better added as code comments). - Testing that you performed (or testing that should be done but you could not for whatever reason). - Tags (see below). There is no need to describe what the patch actually changed, if the reader can see it for himself. If the patch refers to a commit already in the Open vSwitch repository, please include both the commit number and the subject of the patch, e.g. 'commit 632d136c (vswitch: Remove restriction on datapath names.)'. If you, the person sending the patch, did not write the patch yourself, then the very first line of the body should take the form `From: `, followed by a blank line. This will automatically cause the named author to be credited with authorship in the repository. Tags ---- The description ends with a series of tags, written one to a line as the last paragraph of the email. Each tag indicates some property of the patch in an easily machine-parseable manner. Examples of common tags follow. Signed-off-by: Author Name Informally, this indicates that Author Name is the author or submitter of a patch and has the authority to submit it under the terms of the license. The formal meaning is to agree to the Developer's Certificate of Origin (see below). If the author and submitter are different, each must sign off. If the patch has more than one author, all must sign off. Signed-off-by: Author Name Signed-off-by: Submitter Name Co-authored-by: Author Name Git can only record a single person as the author of a given patch. In the rare event that a patch has multiple authors, one must be given the credit in Git and the others must be credited via Co-authored-by: tags. (All co-authors must also sign off.) Acked-by: Reviewer Name Reviewers will often give an Acked-by: tag to code of which they approve. It is polite for the submitter to add the tag before posting the next version of the patch or applying the patch to the repository. Quality reviewing is hard work, so this gives a small amount of credit to the reviewer. Not all reviewers give Acked-by: tags when they provide positive reviews. It's customary only to add tags from reviewers who actually provide them explicitly. Tested-by: Tester Name When someone tests a patch, it is customary to add a Tested-by: tag indicating that. It's rare for a tester to actually provide the tag; usually the patch submitter makes the tag himself in response to an email indicating successful testing results. Tested-at: When a test report is publicly available, this provides a way to reference it. Typical s would be build logs from autobuilders or references to mailing list archives. Some autobuilders only retain their logs for a limited amount of time. It is less useful to cite these because they may be dead links for a developer reading the commit message months or years later. Reported-by: Reporter Name When a patch fixes a bug reported by some person, please credit the reporter in the commit log in this fashion. Please also add the reporter's name and email address to the list of people who provided helpful bug reports in the AUTHORS file at the top of the source tree. Fairly often, the reporter of a bug also tests the fix. Occasionally one sees a combined "Reported-and-tested-by:" tag used to indicate this. It is also acceptable, and more common, to include both tags separately. (If a bug report is received privately, it might not always be appropriate to publicly credit the reporter. If in doubt, please ask the reporter.) Requested-by: Requester Name Suggested-by: Suggester Name When a patch implements a request or a suggestion made by some person, please credit that person in the commit log in this fashion. For a helpful suggestion, please also add the person's name and email address to the list of people who provided suggestions in the AUTHORS file at the top of the source tree. (If a suggestion or a request is received privately, it might not always be appropriate to publicly give credit. If in doubt, please ask.) Reported-at: If a patch fixes or is otherwise related to a bug reported in a public bug tracker, please include a reference to the bug in the form of a URL to the specific bug, e.g.: Reported-at: https://bugs.debian.org/743635 This is also an appropriate way to refer to bug report emails in public email archives, e.g.: Reported-at: http://openvswitch.org/pipermail/dev/2014-June/040952.html VMware-BZ: #1234567 ONF-JIRA: EXT-12345 If a patch fixes or is otherwise related to a bug reported in a private bug tracker, you may include some tracking ID for the bug for your own reference. Please include some identifier to make the origin clear, e.g. "VMware-BZ" refers to VMware's internal Bugzilla instance and "ONF-JIRA" refers to the Open Networking Foundation's JIRA bug tracker. Bug #1234567. Issue: 1234567 These are obsolete forms of VMware-BZ: that can still be seen in old change log entries. (They are obsolete because they do not tell the reader what bug tracker is referred to.) Developer's Certificate of Origin --------------------------------- To help track the author of a patch as well as the submission chain, and be clear that the developer has authority to submit a patch for inclusion in openvswitch please sign off your work. The sign off certifies the following: Developer's Certificate of Origin 1.1 By making a contribution to this project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the open source license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate open source license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same open source license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the open source license(s) involved. Feature Deprecation Guidelines ------------------------------ Open vSwitch is intended to be user friendly. This means that under normal circumstances we don't abruptly remove features from OVS that some users might still be using. Otherwise, if we would, then we would possibly break our user setup when they upgrade and would receive bug reports. Typical process to deprecate a feature in Open vSwitch is to: (a) Mention deprecation of a feature in the NEWS file. Also, mention expected release or absolute time when this feature would be removed from OVS altogether. Don't use relative time (e.g. "in 6 months") because that is not clearly interpretable. (b) If Open vSwitch is configured to use deprecated feature it should print a warning message to the log files clearly indicating that feature is deprecated and that use of it should be avoided. (c) If this feature is mentioned in man pages, then add "Deprecated" keyword to it. Also, if there is alternative feature to the one that is about to be marked as deprecated, then mention it in (a), (b) and (c) as well. Remember to followup and actually remove the feature from OVS codebase once deprecation grace period has expired and users had opportunity to use at least one OVS release that would have informed them about feature deprecation! Comments -------- If you want to include any comments in your email that should not be part of the commit's change log message, put them after the description, separated by a line that contains just `---`. It may be helpful to include a diffstat here for changes that touch multiple files. Patch ----- The patch should be in the body of the email following the description, separated by a blank line. Patches should be in `diff -up` format. We recommend that you use Git to produce your patches, in which case you should use the `-M -C` options to `git diff` (or other Git tools) if your patch renames or copies files. Quilt (http://savannah.nongnu.org/projects/quilt) might be useful if you do not want to use Git. Patches should be inline in the email message. Some email clients corrupt white space or wrap lines in patches. There are hints on how to configure many email clients to avoid this problem at: http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob_plain;f=Documentation/email-clients.txt If you cannot convince your email client not to mangle patches, then sending the patch as an attachment is a second choice. Please follow the style used in the code that you are modifying. The [CodingStyle.md] file describes the coding style used in most of Open vSwitch. Use Linux kernel coding style for Linux kernel code. Example ------- ``` From fa29a1c2c17682879e79a21bb0cdd5bbe67fa7c0 Mon Sep 17 00:00:00 2001 From: Jesse Gross Date: Thu, 8 Dec 2011 13:17:24 -0800 Subject: [PATCH] datapath: Alphabetize include/net/ipv6.h compat header. Signed-off-by: Jesse Gross --- datapath/linux/Modules.mk | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/datapath/linux/Modules.mk b/datapath/linux/Modules.mk index fdd952e..f6cb88e 100644 --- a/datapath/linux/Modules.mk +++ b/datapath/linux/Modules.mk @@ -56,11 +56,11 @@ openvswitch_headers += \ linux/compat/include/net/dst.h \ linux/compat/include/net/genetlink.h \ linux/compat/include/net/ip.h \ + linux/compat/include/net/ipv6.h \ linux/compat/include/net/net_namespace.h \ linux/compat/include/net/netlink.h \ linux/compat/include/net/protocol.h \ linux/compat/include/net/route.h \ - linux/compat/include/net/ipv6.h \ linux/compat/genetlink.inc both_modules += brcompat -- 1.7.7.3 ``` [INSTALL.md]:INSTALL.md [CodingStyle.md]:CodingStyle.md openvswitch-2.5.0/PaxHeaders.69223/manpages.mk0000644000000000000000000000013212664353573015773 xustar0030 mtime=1456592763.387028506 30 atime=1456592770.447317792 30 ctime=1456594659.565262417 openvswitch-2.5.0/manpages.mk0000664000175000017500000001515112664353573017466 0ustar00jpettitjpettit00000000000000# Generated automatically -- do not modify! -*- buffer-read-only: t -*- ovn/utilities/ovn-sbctl.8: \ ovn/utilities/ovn-sbctl.8.in \ lib/db-ctl-base.man \ lib/table.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man ovn/utilities/ovn-sbctl.8.in: lib/db-ctl-base.man: lib/table.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/ovsdb-client.1: \ ovsdb/ovsdb-client.1.in \ lib/common-syn.man \ lib/common.man \ lib/daemon-syn.man \ lib/daemon.man \ lib/ssl-bootstrap-syn.man \ lib/ssl-bootstrap.man \ lib/ssl-syn.man \ lib/ssl.man \ lib/table.man \ lib/vlog-syn.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man ovsdb/ovsdb-client.1.in: lib/common-syn.man: lib/common.man: lib/daemon-syn.man: lib/daemon.man: lib/ssl-bootstrap-syn.man: lib/ssl-bootstrap.man: lib/ssl-syn.man: lib/ssl.man: lib/table.man: lib/vlog-syn.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/ovsdb-server.1: \ ovsdb/ovsdb-server.1.in \ lib/common-syn.man \ lib/common.man \ lib/coverage-unixctl.man \ lib/daemon-syn.man \ lib/daemon.man \ lib/memory-unixctl.man \ lib/service-syn.man \ lib/service.man \ lib/ssl-bootstrap-syn.man \ lib/ssl-bootstrap.man \ lib/ssl-peer-ca-cert-syn.man \ lib/ssl-peer-ca-cert.man \ lib/ssl-syn.man \ lib/ssl.man \ lib/unixctl-syn.man \ lib/unixctl.man \ lib/vlog-syn.man \ lib/vlog-unixctl.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man ovsdb/ovsdb-server.1.in: lib/common-syn.man: lib/common.man: lib/coverage-unixctl.man: lib/daemon-syn.man: lib/daemon.man: lib/memory-unixctl.man: lib/service-syn.man: lib/service.man: lib/ssl-bootstrap-syn.man: lib/ssl-bootstrap.man: lib/ssl-peer-ca-cert-syn.man: lib/ssl-peer-ca-cert.man: lib/ssl-syn.man: lib/ssl.man: lib/unixctl-syn.man: lib/unixctl.man: lib/vlog-syn.man: lib/vlog-unixctl.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/ovsdb-tool.1: \ ovsdb/ovsdb-tool.1.in \ lib/common-syn.man \ lib/common.man \ lib/vlog-syn.man \ lib/vlog.man ovsdb/ovsdb-tool.1.in: lib/common-syn.man: lib/common.man: lib/vlog-syn.man: lib/vlog.man: utilities/bugtool/ovs-bugtool.8: \ utilities/bugtool/ovs-bugtool.8.in utilities/bugtool/ovs-bugtool.8.in: utilities/ovs-appctl.8: \ utilities/ovs-appctl.8.in \ lib/common.man utilities/ovs-appctl.8.in: lib/common.man: utilities/ovs-benchmark.1: \ utilities/ovs-benchmark.1.in \ lib/ovs.tmac utilities/ovs-benchmark.1.in: lib/ovs.tmac: utilities/ovs-dpctl-top.8: \ utilities/ovs-dpctl-top.8.in utilities/ovs-dpctl-top.8.in: utilities/ovs-dpctl.8: \ utilities/ovs-dpctl.8.in \ lib/common.man \ lib/dpctl.man \ lib/vlog.man utilities/ovs-dpctl.8.in: lib/common.man: lib/dpctl.man: lib/vlog.man: utilities/ovs-l3ping.8: \ utilities/ovs-l3ping.8.in \ lib/common-syn.man \ lib/common.man utilities/ovs-l3ping.8.in: lib/common-syn.man: lib/common.man: utilities/ovs-ofctl.8: \ utilities/ovs-ofctl.8.in \ lib/common.man \ lib/daemon.man \ lib/ofp-version.man \ lib/ssl.man \ lib/unixctl.man \ lib/vconn-active.man \ lib/vlog.man utilities/ovs-ofctl.8.in: lib/common.man: lib/daemon.man: lib/ofp-version.man: lib/ssl.man: lib/unixctl.man: lib/vconn-active.man: lib/vlog.man: utilities/ovs-pcap.1: \ utilities/ovs-pcap.1.in \ lib/common-syn.man \ lib/common.man utilities/ovs-pcap.1.in: lib/common-syn.man: lib/common.man: utilities/ovs-pki.8: \ utilities/ovs-pki.8.in utilities/ovs-pki.8.in: utilities/ovs-tcpundump.1: \ utilities/ovs-tcpundump.1.in \ lib/common-syn.man \ lib/common.man utilities/ovs-tcpundump.1.in: lib/common-syn.man: lib/common.man: utilities/ovs-test.8: \ utilities/ovs-test.8.in \ lib/common-syn.man \ lib/common.man \ utilities/ovs-vlan-bugs.man utilities/ovs-test.8.in: lib/common-syn.man: lib/common.man: utilities/ovs-vlan-bugs.man: utilities/ovs-testcontroller.8: \ utilities/ovs-testcontroller.8.in \ lib/common.man \ lib/daemon.man \ lib/ofp-version.man \ lib/ssl-peer-ca-cert.man \ lib/ssl.man \ lib/unixctl.man \ lib/vconn-active.man \ lib/vconn-passive.man \ lib/vlog.man utilities/ovs-testcontroller.8.in: lib/common.man: lib/daemon.man: lib/ofp-version.man: lib/ssl-peer-ca-cert.man: lib/ssl.man: lib/unixctl.man: lib/vconn-active.man: lib/vconn-passive.man: lib/vlog.man: utilities/ovs-vlan-bug-workaround.8: \ utilities/ovs-vlan-bug-workaround.8.in \ lib/common.man \ utilities/ovs-vlan-bugs.man utilities/ovs-vlan-bug-workaround.8.in: lib/common.man: utilities/ovs-vlan-bugs.man: utilities/ovs-vlan-test.8: \ utilities/ovs-vlan-test.8.in \ lib/common-syn.man \ lib/common.man \ utilities/ovs-vlan-bugs.man utilities/ovs-vlan-test.8.in: lib/common-syn.man: lib/common.man: utilities/ovs-vlan-bugs.man: utilities/ovs-vsctl.8: \ utilities/ovs-vsctl.8.in \ lib/common.man \ lib/db-ctl-base.man \ lib/ssl-bootstrap.man \ lib/ssl-peer-ca-cert.man \ lib/ssl.man \ lib/table.man \ lib/vconn-active.man \ lib/vconn-passive.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man \ ovsdb/remote-passive.man utilities/ovs-vsctl.8.in: lib/common.man: lib/db-ctl-base.man: lib/ssl-bootstrap.man: lib/ssl-peer-ca-cert.man: lib/ssl.man: lib/table.man: lib/vconn-active.man: lib/vconn-passive.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/remote-passive.man: vswitchd/ovs-vswitchd.8: \ vswitchd/ovs-vswitchd.8.in \ lib/common.man \ lib/coverage-unixctl.man \ lib/daemon.man \ lib/dpctl.man \ lib/memory-unixctl.man \ lib/service.man \ lib/ssl-bootstrap.man \ lib/ssl.man \ lib/unixctl.man \ lib/vlog-unixctl.man \ lib/vlog.man \ ofproto/ofproto-dpif-unixctl.man \ ofproto/ofproto-tnl-unixctl.man \ ofproto/ofproto-unixctl.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man vswitchd/ovs-vswitchd.8.in: lib/common.man: lib/coverage-unixctl.man: lib/daemon.man: lib/dpctl.man: lib/memory-unixctl.man: lib/service.man: lib/ssl-bootstrap.man: lib/ssl.man: lib/unixctl.man: lib/vlog-unixctl.man: lib/vlog.man: ofproto/ofproto-dpif-unixctl.man: ofproto/ofproto-tnl-unixctl.man: ofproto/ofproto-unixctl.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: vtep/vtep-ctl.8: \ vtep/vtep-ctl.8.in \ lib/common.man \ lib/db-ctl-base.man \ lib/ssl-bootstrap.man \ lib/ssl-peer-ca-cert.man \ lib/ssl.man \ lib/table.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man \ ovsdb/remote-passive.man vtep/vtep-ctl.8.in: lib/common.man: lib/db-ctl-base.man: lib/ssl-bootstrap.man: lib/ssl-peer-ca-cert.man: lib/ssl.man: lib/table.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/remote-passive.man: openvswitch-2.5.0/PaxHeaders.69223/NOTICE0000644000000000000000000000013112631676262014547 xustar0029 mtime=1449622706.91043722 30 atime=1456592667.291089585 30 ctime=1456594659.681267294 openvswitch-2.5.0/NOTICE0000664000175000017500000000242312631676262016241 0ustar00jpettitjpettit00000000000000This file is included in compliance with the Apache 2.0 license, available at http://www.apache.org/licenses/LICENSE-2.0.html Open vSwitch Copyright (c) 2007, 2008, 2009, 2010, 2011, 2013 Nicira, Inc. Open vSwitch BSD port Copyright (c) 2011 Gaetano Catalli Apache Portable Runtime Copyright 2008 The Apache Software Foundation. This product includes software developed by The Apache Software Foundation (http://www.apache.org/). Portions of this software were developed at the National Center for Supercomputing Applications (NCSA) at the University of Illinois at Urbana-Champaign. lib/ovs.tmac includes troff macros written by Eric S. Raymond and Werner Lemberg. m4/include_next.m4 and m4/absolute-header.m4 Copyright (C) 2006-2013 Free Software Foundation, Inc. Rapid Spanning Tree Protocol (RSTP) implementation Copyright (c) 2011-2014 M3S, Srl - Italy LLDP implementation Copyright (c) 2008, 2012 Vincent Bernat LLDP includes code used from the Net::CDP project based on the ISC license Copyright (c) 2014 Michael Chapman LLDP includes code used from the ladvd project based on the ISC license Copyright (c) 2008, 2009, 2010 Sten Spans Auto Attach implementation Copyright (c) 2014, 2015 WindRiver, Inc Copyright (c) 2014, 2015 Avaya, Inc openvswitch-2.5.0/PaxHeaders.69223/TODO.md0000644000000000000000000000013112631676262014732 xustar0029 mtime=1449622706.91443736 30 atime=1456592667.291089585 30 ctime=1456594659.669266791 openvswitch-2.5.0/TODO.md0000664000175000017500000002526212631676262016432 0ustar00jpettitjpettit00000000000000Open vSwitch Project Ideas ========================== This file lists a number of project ideas for Open vSwitch. The ideas here overlap somewhat with those in the [OPENFLOW-1.1+.md] file. Programming Project Ideas ========================= Each of these projects would ideally result in a patch or a short series of them posted to ovs-dev. Please read [CONTRIBUTING.md] and [CodingStyle.md] in the top of the source tree before you begin work. The [OPENFLOW-1.1+.md] file also has an introduction to how OpenFlow is implemented in Open vSwitch. It is also a good idea to look around the source tree for related code, and back through the Git history for commits on related subjects, to allow you to follow existing patterns and conventions. Meters ------ Open vSwitch has OpenFlow protocol support for meters, but it does not have an implementation in the kernel or userspace datapaths. An implementation was proposed some time ago (I recommend looking for the discussion in the ovs-dev mailing list archives), but for a few different reasons it was not accepted. Some of those reasons apply only to a kernel implementation of meters. At the time, a userspace implementation wasn't as interesting, because the userspace switch did not perform at a production speed, but with the advent of multithreaded forwarding and, now, DPDK support, userspace-only meters would be a great way to get started. Improve SSL/TLS Security ------------------------ Open vSwitch allows some weak ciphers to be used for its secure connections. Security audits often suggest that the project remove those ciphers, but there's not a clean way to modify the acceptable ciphers. At the very least, the cipher list should be audited, but it would be nice to make it configurable. Open vSwitch does not insist on perfect forward security via ephemeral Diffie-Hellman key exchange when it establishes an SSL/TLS connection. Given the wiretapping revelations over the last year, it seems wise to turn this on. (This would probably amount to finding the right OpenSSL function to call or just reducing the acceptable ciphers further.) These changes might have backward-compatibility implications; one would have to test the behavior of the reduced cipher list OVS against older versions. Bash Command Completion ----------------------- ovs-vsctl and other programs would be easier to use if bash command completion (with ``tab'', etc.) were supported. Alex Wang is leading a team for this project. Auxiliary Connections --------------------- Auxiliary connections are a feature of OpenFlow 1.3 and later that allow OpenFlow messages to be carried over datagram channels such as UDP or DTLS. One place to start would be to implement a datagram abstraction library for OVS analogous to the ``stream'' library that already abstracts TCP, SSL, and other stream protocols. Basic OpenFlow 1.4 support -------------------------- Some basic support for OpenFlow 1.4 is missing and needs to be implemented. These can be found by looking through lib/ofp-util.c for mentions of OFP14_VERSION followed by a call to OVS_NOT_REACHED (which aborts the program). OpenFlow 1.4: Flow monitoring ----------------------------- OpenFlow 1.4 introduces OFPMP_FLOW_MONITOR for notifying a controller of changes to selected flow tables. This feature is based on NXST_FLOW_MONITOR that is already part of Open vSwitch, so to implement this feature would be to extend that code to handle the OpenFlow 1.4 wire protocol. OpenFlow 1.3 also includes this feature as a ONF-defined extension, so ideally OVS would support that too. OpenFlow 1.4 Role Status Message -------------------------------- OpenFlow 1.4 section 7.4.4 ``Controller Role Status Message'' defines a new message sent by a switch to notify the controller that its role (whether it is a master or a slave) has changed. OVS should implement this. OpenFlow 1.3 also includes this feature as a ONF-defined extension, so ideally OVS would support that too. OpenFlow 1.4 Vacancy Events --------------------------- OpenFlow 1.4 section 7.4.5 ``Table Status Message'' defines a new message sent by a switch to notify the controller that a flow table is close to filling up (or that it is no longer close to filling up). OVS should implement this. OpenFlow 1.3 also includes this feature as a ONF-defined extension, so ideally OVS would support that too. OpenFlow 1.4 Group and Meter Change Notification ------------------------------------------------ OpenFlow 1.4 adds a feature whereby a controller can ask the switch to send it copies of messages that change groups and meters. (This is only useful in the presence of multiple controllers.) OVS should implement this. OpenFlow 1.3 also includes this feature as a ONF-defined extension, so ideally OVS would support that too. Testing Project Ideas ===================== Each of these projects would ideally result in confirmation that features work or bug reports explaining how they do not. Please sent bug reports to dev at openvswitch.org, with as many details as you have. ONF Plugfest Results Analysis ----------------------------- Ben Pfaff has a collection of files reporting Open vSwitch conformance to OpenFlow 1.3 provided by one of the vendors at the ONF plugfest last year. Some of the reported failures have been fixed, some of the other failures probably result from differing interpretations of OpenFlow 1.3, and others are probably genuine bugs in Open vSwitch. Open vSwitch has also improved in the meantime. Ben can provide the results, privately, to some person or team who wishes to check them out and try to pick out the genuine bugs. OpenFlow Fuzzer --------------- Build a ``fuzzer'' for the OpenFlow protocol (or use an existing one, if there is one) and run it against the Open vSwitch implementation. One could also build a fuzzer for the OSVDB protocol. Ryu Certification Tests Analysis -------------------------------- The Ryu controller comes with a suite of ``certification tests'' that check the correctness of a switch's implementation of various OpenFlow 1.3 features. The INSTALL file in the OVS source tree has a section that explains how to easily run these tests against an OVS source tree. Run the tests and figure out whether any tests fail but should pass. (Some tests fail and should fail because OVS does not implement the particular feature; for example, OVS does not implement PBB encapsulation, so related tests fail.) OFTest Results Analysis ----------------------- OFTest is a test suite for OpenFlow 1.0 compliance. The INSTALL file in the OVS source tree has a section that explains how to easily run these tests against an OVS source tree. Run the tests and figure out whether any tests fail but should pass, and ideally why. OFTest is not particularly well vetted--in the past, at least, some tests have failed against OVS due to bugs in OFTest, not in OVS--so some care is warranted. Documentation Project Ideas =========================== Each of these projects would ideally result in creating some new documentation for users. Some documentation might be suitable to accompany Open vSwitch as part of its source tree most likely either in plain text or ``nroff'' (manpage) format. OpenFlow Basics Tutorial ------------------------ Open vSwitch has a tutorial that covers its advanced features, but it does not have a basic tutorial. There are several tutorials on the Internet already, so a new tutorial would have to distinguish itself in some way. One way would be to use the Open vSwitch ``sandbox'' environment already used in the advanced tutorial. The sandbox does not require any real network or even supervisor privilege on the machine where it runs, and thus it is easy to use with hardly any up-front setup, so it is a gentle way to get started. FlowVisor via patch ports ------------------------- FlowVisor is a proxy that sits between OpenFlow controllers and a switch. It divides up switch resources, allowing each controller to control a ``slice'' of the network. For example, it can break up a network based on VLAN, allowing different controllers to handle packets with different VLANs. It seems that Open vSwitch has features that allow it to implement at least simple forms of FlowVisor control without any need for FlowVisor. Consider an Open vSwitch instance with three bridges. Bridge br0 has physical ports eth0 and eth1. Bridge v9 has no physical ports, but it has two ``patch ports'' that connect it to br0. Bridge v11 has the same setup. Flows in br0 match packets received on vlan 9, strip the vlan header, and direct them to the appropriate patch port leading to v9. Additional flows in br0 match packets received from v9, attach a VLAN 9 tag to them, and direct them out eth0 or eth1 as appropriate. Other flows in br0 treat packets on VLAN 11 similarly. Controllers attached to bridge v9 or v11 may thus work as if they had full control of a network. It seems to me that this is a good example of the power of OpenFlow and Open vSwitch. The point of this project is to explain how to do this, with detailed examples, in case someone finds it handy and to open eyes toward the generality of Open vSwitch usefulness. ``Cookbooks'' ------------- The Open vSwitch website has a few ``cookbook'' entries that describe how to use Open vSwitch in a few scenarios. There are only a few of these and all of them are dated. It would be a good idea to come up with ideas for some more and write them. These could be added to the Open vSwitch website or the source tree or somewhere else. Demos ----- Record a demo of Open vSwitch functionality in use (or something else relevant) and post it to youtube or another video site so that we can link to it from openvswitch.org. How to contribute ================= If you plan to contribute code for a feature, please let everyone know on ovs-dev before you start work. This will help avoid duplicating work. Please consider the following: * Testing. Please test your code. * Unit tests. Please consider writing some. The tests directory has many examples that you can use as a starting point. * ovs-ofctl. If you add a feature that is useful for some ovs-ofctl command then you should add support for it there. * Documentation. If you add a user-visible feature, then you should document it in the appropriate manpage and mention it in NEWS as well. * Coding style (see the [CodingStyle.md] file at the top of the source tree). * The patch submission guidelines (see [CONTRIBUTING.md]). I recommend using "git send-email", which automatically follows a lot of those guidelines. Bug Reporting ============= Please report problems to bugs@openvswitch.org. Local Variables: mode: text End: [OPENFLOW-1.1+.md]:OPENFLOW-1.1+.md [CONTRIBUTING.md]:CONTRIBUTING.md [CodingStyle.md]:CodingStyle.md openvswitch-2.5.0/PaxHeaders.69223/config.h.in0000644000000000000000000000013212664357151015666 xustar0030 mtime=1456594537.780140481 30 atime=1456594549.632639164 30 ctime=1456594659.617264604 openvswitch-2.5.0/config.h.in0000664000175000017500000001716212664357151017365 0ustar00jpettitjpettit00000000000000/* config.h.in. Generated from configure.ac by autoheader. */ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD /* If the C compiler is GCC 4.7 or later, define to the return value of __atomic_always_lock_free(1, 0). If the C compiler is not GCC or is an older version of GCC, the value does not matter. */ #undef ATOMIC_ALWAYS_LOCK_FREE_1B /* If the C compiler is GCC 4.7 or later, define to the return value of __atomic_always_lock_free(2, 0). If the C compiler is not GCC or is an older version of GCC, the value does not matter. */ #undef ATOMIC_ALWAYS_LOCK_FREE_2B /* If the C compiler is GCC 4.7 or later, define to the return value of __atomic_always_lock_free(4, 0). If the C compiler is not GCC or is an older version of GCC, the value does not matter. */ #undef ATOMIC_ALWAYS_LOCK_FREE_4B /* If the C compiler is GCC 4.7 or later, define to the return value of __atomic_always_lock_free(8, 0). If the C compiler is not GCC or is an older version of GCC, the value does not matter. */ #undef ATOMIC_ALWAYS_LOCK_FREE_8B /* System uses the DPDK module. */ #undef DPDK_NETDEV /* Define to 1 if building on ESX. */ #undef ESX /* Define to 1 if you have backtrace(3). */ #undef HAVE_BACKTRACE /* Define to 1 if you have the declaration of `strerror_r', and to 0 if you don't. */ #undef HAVE_DECL_STRERROR_R /* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you don't. */ #undef HAVE_DECL_SYS_SIGLIST /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H /* Define to 1 if the C compiler and linker supports the GCC 4.0+ atomic built-ins. */ #undef HAVE_GCC4_ATOMICS /* Define to 1 if you have the `getloadavg' function. */ #undef HAVE_GETLOADAVG /* Define to 1 if you have the `getmntent_r' function. */ #undef HAVE_GETMNTENT_R /* Define to 1 if pthread_setname_np() is available and takes 2 parameters (like glibc). */ #undef HAVE_GLIBC_PTHREAD_SETNAME_NP /* Define to 1 if net/if_dl.h is available. */ #undef HAVE_IF_DL /* Define to 1 if net/if_packet.h is available. */ #undef HAVE_IF_PACKET /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if libcap-ng is available. */ #undef HAVE_LIBCAPNG /* Define to 1 if you have the `socket' library (-lsocket). */ #undef HAVE_LIBSOCKET /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_IF_ETHER_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_PERF_EVENT_H /* Define to 1 if you have the header file. */ #undef HAVE_LINUX_TYPES_H /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `mlockall' function. */ #undef HAVE_MLOCKALL /* Define to 1 if you have the header file. */ #undef HAVE_MNTENT_H /* Define to 1 if pthread_setname_np() is available and takes 3 parameters (like NetBSD). */ #undef HAVE_NETBSD_PTHREAD_SETNAME_NP /* Define to 1 if Netlink protocol is available. */ #undef HAVE_NETLINK /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_MIB_H /* Define to 1 if OpenSSL is installed. */ #undef HAVE_OPENSSL /* Define to 1 if `posix_memalign' works. */ #undef HAVE_POSIX_MEMALIGN /* Define if compiler supports #pragma message directive */ #undef HAVE_PRAGMA_MESSAGE /* Define to 1 if you have the `pthread_set_name_np' function. */ #undef HAVE_PTHREAD_SET_NAME_NP /* Define to 1 if you have the `statvfs' function. */ #undef HAVE_STATVFS /* Define to 1 if you have the header file. */ #undef HAVE_STDATOMIC_H /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDIO_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strerror_r' function. */ #undef HAVE_STRERROR_R /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strnlen' function. */ #undef HAVE_STRNLEN /* Define if strtok_r macro segfaults on some inputs */ #undef HAVE_STRTOK_R_BUG /* Define to 1 if `ifr_flagshigh' is a member of `struct ifreq'. */ #undef HAVE_STRUCT_IFREQ_IFR_FLAGSHIGH /* Define to 1 if `st_mtimensec' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIMENSEC /* Define to 1 if `st_mtim.tv_nsec' is a member of `struct stat'. */ #undef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STATVFS_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if the C compiler and linker supports the C11 thread_local matcro defined in . */ #undef HAVE_THREAD_LOCAL /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the header file. */ #undef HAVE_VALGRIND_VALGRIND_H /* Define to 1 if the C compiler and linker supports the GCC __thread extenions. */ #undef HAVE___THREAD /* Define to the sub-directory in which libtool stores uninstalled libraries. */ #undef LT_OBJDIR /* Name of package */ #undef PACKAGE /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if strerror_r returns char *. */ #undef STRERROR_R_CHAR_P /* Enable extensions on AIX 3, Interix. */ #ifndef _ALL_SOURCE # undef _ALL_SOURCE #endif /* Enable GNU extensions on systems that have them. */ #ifndef _GNU_SOURCE # undef _GNU_SOURCE #endif /* Enable threading extensions on Solaris. */ #ifndef _POSIX_PTHREAD_SEMANTICS # undef _POSIX_PTHREAD_SEMANTICS #endif /* Enable extensions on HP NonStop. */ #ifndef _TANDEM_SOURCE # undef _TANDEM_SOURCE #endif /* Enable general extensions on Solaris. */ #ifndef __EXTENSIONS__ # undef __EXTENSIONS__ #endif /* Version number of package */ #undef VERSION /* DPDK vhost-cuse support enabled, vhost-user disabled. */ #undef VHOST_CUSE /* System uses the Visual Studio build target. */ #undef VSTUDIO_DDK /* Define to 1 if building on WIN32. */ #undef WIN32 /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel). */ #if defined AC_APPLE_UNIVERSAL_BUILD # if defined __BIG_ENDIAN__ # define WORDS_BIGENDIAN 1 # endif #else # ifndef WORDS_BIGENDIAN # undef WORDS_BIGENDIAN # endif #endif /* Enable large inode numbers on Mac OS X 10.5. */ #ifndef _DARWIN_USE_64_BIT_INODE # define _DARWIN_USE_64_BIT_INODE 1 #endif /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS /* Define for large files, on AIX-style hosts. */ #undef _LARGE_FILES /* Define to 1 if on MINIX. */ #undef _MINIX /* Define to 2 if the system does not provide POSIX.1 features except with this defined. */ #undef _POSIX_1_SOURCE /* Define to 1 if you need to in order for `stat' and other things to work. */ #undef _POSIX_SOURCE #ifdef WIN32 #include "include/windows/windefs.h" #endif openvswitch-2.5.0/PaxHeaders.69223/datapath-windows0000644000000000000000000000013212664357344017050 xustar0030 mtime=1456594660.165287644 30 atime=1456594661.705352384 30 ctime=1456594660.165287644 openvswitch-2.5.0/datapath-windows/0000775000175000017500000000000012664357344020615 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/include0000644000000000000000000000013212664357344020473 xustar0030 mtime=1456594660.161287475 30 atime=1456594661.705352384 30 ctime=1456594660.161287475 openvswitch-2.5.0/datapath-windows/include/0000775000175000017500000000000012664357344022240 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/datapath-windows/include/PaxHeaders.69223/OvsDpInterfaceExt.h0000644000000000000000000000013212631676262024253 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.299089913 30 ctime=1456594660.161287475 openvswitch-2.5.0/datapath-windows/include/OvsDpInterfaceExt.h0000664000175000017500000001437512631676262025755 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __OVS_DP_INTERFACE_EXT_H_ #define __OVS_DP_INTERFACE_EXT_H_ 1 /* Windows kernel datapath extensions to the standard datapath interface. */ /* Version number of the datapath interface extensions. */ #define OVS_DATAPATH_EXT_VERSION 1 /* Name of the device. */ #define OVS_DEVICE_NAME_NT L"\\Device\\OpenvSwitchDevice" #define OVS_DEVICE_NAME_DOS L"\\DosDevices\\OpenvSwitchDevice" #define OVS_DEVICE_NAME_USER TEXT("\\\\.\\OpenvSwitchDevice") #define OVS_IOCTL_DEVICE_TYPE 45000 #define OVS_IOCTL_START 0x100 /* We used Direct I/O (zero copy) for the buffers. */ /* Non-Netlink-based IOCTLs. */ #define OVS_IOCTL_GET_PID \ CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x0, METHOD_BUFFERED,\ FILE_WRITE_ACCESS) /* Netlink-based IOCTLs. */ #define OVS_IOCTL_READ \ CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x1, METHOD_OUT_DIRECT,\ FILE_READ_ACCESS) #define OVS_IOCTL_READ_EVENT \ CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x2, METHOD_OUT_DIRECT, \ FILE_READ_ACCESS) #define OVS_IOCTL_READ_PACKET \ CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x3, METHOD_OUT_DIRECT, \ FILE_READ_ACCESS) #define OVS_IOCTL_WRITE \ CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x4, METHOD_IN_DIRECT,\ FILE_READ_ACCESS) #define OVS_IOCTL_TRANSACT \ CTL_CODE (OVS_IOCTL_DEVICE_TYPE, OVS_IOCTL_START + 0x5, METHOD_OUT_DIRECT,\ FILE_WRITE_ACCESS) /* * On platforms that support netlink natively, the operating system assigns a * dynamic value to a netlink family when it is registered. In the absense of * such mechanism, defined hard-coded values that are known both to userspace * and kernel. */ #define OVS_WIN_NL_INVALID_FAMILY_ID 0 #define OVS_WIN_NL_CTRL_FAMILY_ID (NLMSG_MIN_TYPE + 1) #define OVS_WIN_NL_DATAPATH_FAMILY_ID (NLMSG_MIN_TYPE + 2) #define OVS_WIN_NL_PACKET_FAMILY_ID (NLMSG_MIN_TYPE + 3) #define OVS_WIN_NL_VPORT_FAMILY_ID (NLMSG_MIN_TYPE + 4) #define OVS_WIN_NL_FLOW_FAMILY_ID (NLMSG_MIN_TYPE + 5) #define OVS_WIN_NL_NETDEV_FAMILY_ID (NLMSG_MIN_TYPE + 6) #define OVS_WIN_NL_INVALID_MCGRP_ID 0 #define OVS_WIN_NL_MCGRP_START_ID 100 #define OVS_WIN_NL_VPORT_MCGRP_ID (OVS_WIN_NL_MCGRP_START_ID + 1) /* * Define a family of netlink command specific to Windows. This is part of the * extensions. */ #define OVS_WIN_CONTROL_FAMILY "ovs_win_control" #define OVS_WIN_CONTROL_MCGROUP "ovs_win_control" #define OVS_WIN_CONTROL_VERSION 1 /* Commands available under the OVS_WIN_CONTROL_FAMILY. */ enum ovs_win_control_cmd { OVS_CTRL_CMD_WIN_PEND_REQ, OVS_CTRL_CMD_WIN_PEND_PACKET_REQ, OVS_CTRL_CMD_MC_SUBSCRIBE_REQ, OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ, /* This command is logically belong to the Vport family */ OVS_CTRL_CMD_EVENT_NOTIFY, OVS_CTRL_CMD_READ_NOTIFY }; /* NL Attributes for joining/unjoining an MC group */ enum ovs_nl_mcast_attr { OVS_NL_ATTR_MCAST_GRP, /* (UINT32) Join an MC group */ OVS_NL_ATTR_MCAST_JOIN, /* (UINT8) 1/0 - Join/Unjoin */ OVS_NL_ATTR_PACKET_SUBSCRIBE, /* (UNINT8): 1/0 - subscribe/unsubscribe */ OVS_NL_ATTR_PACKET_PID, /* (UNINT32) netlink PID to receive upcalls */ __OVS_NL_ATTR_CTRL_MAX }; #define OVS_WIN_CONTROL_ATTR_MAX (__OVS_NL_ATTR_CTRL_MAX - 1) /* * Netdev family of commands specific to Windows. */ #define OVS_WIN_NETDEV_FAMILY "ovs_win_netdev" #define OVS_WIN_NETDEV_MCGROUP "ovs_win_netdev" #define OVS_WIN_NETDEV_VERSION 1 enum ovs_win_netdev_cmd { OVS_WIN_NETDEV_CMD_UNSPEC, OVS_WIN_NETDEV_CMD_GET, /* information about the netdev. */ }; /** * For every vport on the datapath, there is a corresponding netdev. General * network device attributes of a vport that are not specific to OVS, such as * MTU are represented using a netdev. For convenience, some of the vport * attributes are also included as netdev attributes. * * enum ovs_win_netdev_attr - attributes for %OVS_WIN_NETDEV_* commands. * @OVS_WIN_NETDEV_ATTR_PORT_NO: 32-bit port number of the vport within the * datapath. * @OVS_WIN_NETDEV_ATTR_TYPE: 32-bit %OVS_VPORT_TYPE_* constant describing * the type of vport. * @OVS_WIN_NETDEV_ATTR_NAME: Name of vport. Maximum length %IFNAMSIZ-1 bytes * plus a null terminator. * @OVS_WIN_NETDEV_ATTR_MAC_ADDR: MAC address of the vport. %ETH_ADDR_LEN bytes * long. * @OVS_WIN_NETDEV_ATTR_MTU : 32-bit MTU of the vport. * @OVS_WIN_NETDEV_ATTR_IF_FLAGS: 32-bit %OVS_WIN_NETDEV_IFF_* interface flags * of the vport. * * These attributes follow the &struct ovs_header within the Generic Netlink * payload for %OVS_WIN_NETDEV_* commands. * * For all requests, if %OVS_WIN_NETDEV_ATTR_NAME is specified then it is used * to look up the netdev to operate on; dp_idx from the &struct * ovs_header is not relevant for the look up. */ enum ovs_win_netdev_attr { OVS_WIN_NETDEV_ATTR_UNSPEC, OVS_WIN_NETDEV_ATTR_PORT_NO, /* u32 port number within datapath. */ OVS_WIN_NETDEV_ATTR_TYPE, /* u32 OVS_NETDEV_TYPE_* constant. */ OVS_WIN_NETDEV_ATTR_NAME, /* string name, up to IFNAMSIZ bytes long. */ OVS_WIN_NETDEV_ATTR_MAC_ADDR, /* MAC address of the vport. */ OVS_WIN_NETDEV_ATTR_MTU, /* MTU of the vport. */ OVS_WIN_NETDEV_ATTR_IF_FLAGS, /* Interface flags o the vport. */ __OVS_WIN_NETDEV_ATTR_MAX }; #define OVS_WIN_NETDEV_ATTR_MAX (__OVS_WIN_NETDEV_ATTR_MAX - 1) #define OVS_WIN_NETDEV_IFF_UP (1 << 0) #define OVS_WIN_NETDEV_IFF_PROMISC (1 << 1) typedef struct ovs_dp_stats OVS_DP_STATS; typedef enum ovs_vport_type OVS_VPORT_TYPE; #endif /* __OVS_DP_INTERFACE_EXT_H_ */ openvswitch-2.5.0/datapath-windows/include/PaxHeaders.69223/automake.mk0000644000000000000000000000013212631676262022704 xustar0030 mtime=1449622706.934438063 30 atime=1456592426.481209631 30 ctime=1456594659.589263427 openvswitch-2.5.0/datapath-windows/include/automake.mk0000664000175000017500000000072612631676262024401 0ustar00jpettitjpettit00000000000000if WIN32 BUILT_SOURCES += $(srcdir)/datapath-windows/include/OvsDpInterface.h endif $(srcdir)/datapath-windows/include/OvsDpInterface.h: \ datapath/linux/compat/include/linux/openvswitch.h \ build-aux/extract-odp-netlink-windows-dp-h $(AM_V_GEN)sed -f $(srcdir)/build-aux/extract-odp-netlink-windows-dp-h < $< > $@ EXTRA_DIST += $(srcdir)/build-aux/extract-odp-netlink-windows-dp-h CLEANFILES += $(srcdir)/datapath-windows/include/OvsDpInterface.h openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/CodingStyle0000644000000000000000000000013212631676262021271 xustar0030 mtime=1449622706.930437922 30 atime=1456592667.299089913 30 ctime=1456594660.157287306 openvswitch-2.5.0/datapath-windows/CodingStyle0000664000175000017500000001335212631676262022765 0ustar00jpettitjpettit00000000000000 Open vSwitch Windows Datapath Coding Style ========================================== The coding style described in the Open vSwitch distribution gives the flexiblity for each platform to use its own coding style for the kernel datapath. This file describes the specific coding style used in most of the C files in the Windows kernel datapath of the Open vSwitch distribution. Most of the coding conventions applicable for the Open vSwitch distribution are applicable to the Windows kernel datapath as well. There are some exceptions and new guidlines owing to the commonly followed practices in Windows kernel/driver code. They are noted as follows: BASICS Limit lines to 79 characters. Many times, this is not possible due to long names of functions and it is fine to go beyond the characters limit. One common example is when calling into NDIS functions. TYPES Use data types defined by Windows for most of the code. This is a common practice in Windows driver code, and it makes integrating with the data structures and functions defined by Windows easier. Example: DWORD and BOOLEAN. Use caution in portions of the code that interface with the OVS userspace. OVS userspace does not use Windows specific data types, and when copying data back and forth between kernel and userspace, care should be exercised. NAMING It is common practice to use camel casing for naming variables, functions and files in Windows. For types, especially structures, unions and enums, using all upper case letters with words seprated by '_' is common. These practices can be used for OVS Windows datapath. However, use the following guidelines: Use lower case to begin the name of a variable. Do not use '_' to begin the name of the variable. '_' is to be used to begin the parameters of a pre-processor macro. Use upper case to begin the name of a function, enum, file name etc. Static functions whose scope is limited to the file they are defined in can be prefixed with '_'. This is not mandatory though. For types, use all upper case for all letters with words separated by '_'. If camel casing is preferred, use upper case for the first letter. It is a common practice to define a pointer type by prefixing the letter 'P' to a data type. The same practice can be followed here as well. Example: static __inline BOOLEAN OvsDetectTunnelRxPkt(POVS_FORWARDING_CONTEXT ovsFwdCtx, POVS_FLOW_KEY flowKey) { POVS_VPORT_ENTRY tunnelVport = NULL; if (!flowKey->ipKey.nwFrag && flowKey->ipKey.nwProto == IPPROTO_UDP && flowKey->ipKey.l4.tpDst == VXLAN_UDP_PORT_NBO) { tunnelVport = OvsGetTunnelVport(OVSWIN_VPORT_TYPE_VXLAN); ovsActionStats.rxVxlan++; } if (tunnelVport) { ASSERT(ovsFwdCtx->tunnelRxNic == NULL); ovsFwdCtx->tunnelRxNic = tunnelVport; return TRUE; } return FALSE; } For declaring variables of pointer type, use of the pointer data type prefixed with 'P' is preferred over using '*'. This is not mandatory though, and is only prescribed since it is a common practice in Windows. Example, #1 is preferred over #2 though #2 is also equally correct: 1. PNET_BUFFER_LIST curNbl; 2. NET_BUFFER_LIST *curNbl; COMMENTS Comments should be written as full sentences that start with a capital letter and end with a period. Putting two spaces between sentances is not necessary. // can be used for comments as long as the comment is a single line comment. For block comments, use /* */ comments FUNCTIONS Put the return type, function name, and the braces that surround the function's code on separate lines, all starting in column 0. Before each function definition, write a comment that describes the function's purpose, including each parameter, the return value, and side effects. References to argument names should be given in single-quotes, e.g. 'arg'. The comment should not include the function name, nor need it follow any formal structure. The comment does not need to describe how a function does its work, unless this information is needed to use the function correctly (this is often better done with comments *inside* the function). Mention any side effects that the function has that are not obvious based on the name of the function or based on the workflow it is called from. In the interest of keeping comments describing functions similar in structure, use the following template. /* *---------------------------------------------------------------------------- * Any description of the function, arguments, return types, assumptions and * side effects. *---------------------------------------------------------------------------- */ SOURCE FILES Each source file should state its license in a comment at the very top, followed by a comment explaining the purpose of the code that is in that file. The comment should explain how the code in the file relates to code in other files. The goal is to allow a programmer to quickly figure out where a given module fits into the larger system. The first non-comment line in a .c source file should be: #include #include directives should appear in the following order: 1. #include 2. The module's own headers, if any. Including this before any other header (besides ) ensures that the module's header file is self-contained (see HEADER FILES) below. 3. Standard C library headers and other system headers, preferably in alphabetical order. (Occasionally one encounters a set of system headers that must be included in a particular order, in which case that order must take precedence.) 4. Open vSwitch headers, in alphabetical order. Use "", not <>, to specify Open vSwitch header names. openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/ovsext.sln0000644000000000000000000000013212631676262021170 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.303090077 30 ctime=1456594660.165287644 openvswitch-2.5.0/datapath-windows/ovsext.sln0000664000175000017500000000572512631676262022671 0ustar00jpettitjpettit00000000000000Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 VisualStudioVersion = 12.0.31101.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Package", "Package", "{6BA8554E-AE50-49B0-9C98-4592447FEF8D}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "OVSExt", "OVSExt", "{4A841675-477D-40A2-9CC6-128C3B8714F8}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "package", "Package\package.VcxProj", "{911D7389-3E61-449F-B8F3-14AD7EE9A0F2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ovsext", "ovsext\ovsext.vcxproj", "{63FE215D-98BE-4440-8081-C6160EFB80FA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Win8.1Debug|x64 = Win8.1Debug|x64 Win8.1Release|x64 = Win8.1Release|x64 Win8Debug|x64 = Win8Debug|x64 Win8Release|x64 = Win8Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Debug|x64.ActiveCfg = Win8.1 Debug|x64 {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Debug|x64.Build.0 = Win8.1 Debug|x64 {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Release|x64.ActiveCfg = Win8.1 Release|x64 {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8.1Release|x64.Build.0 = Win8.1 Release|x64 {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Debug|x64.ActiveCfg = Win8 Debug|x64 {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Debug|x64.Build.0 = Win8 Debug|x64 {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Release|x64.ActiveCfg = Win8 Release|x64 {911D7389-3E61-449F-B8F3-14AD7EE9A0F2}.Win8Release|x64.Build.0 = Win8 Release|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Debug|x64.ActiveCfg = Win8.1 Debug|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Debug|x64.Build.0 = Win8.1 Debug|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Debug|x64.Deploy.0 = Win8.1 Debug|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Release|x64.ActiveCfg = Win8.1 Release|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Release|x64.Build.0 = Win8.1 Release|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8.1Release|x64.Deploy.0 = Win8.1 Release|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Debug|x64.ActiveCfg = Win8 Debug|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Debug|x64.Build.0 = Win8 Debug|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Debug|x64.Deploy.0 = Win8 Debug|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Release|x64.ActiveCfg = Win8 Release|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Release|x64.Build.0 = Win8 Release|x64 {63FE215D-98BE-4440-8081-C6160EFB80FA}.Win8Release|x64.Deploy.0 = Win8 Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {911D7389-3E61-449F-B8F3-14AD7EE9A0F2} = {6BA8554E-AE50-49B0-9C98-4592447FEF8D} {63FE215D-98BE-4440-8081-C6160EFB80FA} = {4A841675-477D-40A2-9CC6-128C3B8714F8} EndGlobalSection EndGlobal openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/Package0000644000000000000000000000013212664357344020403 xustar0030 mtime=1456594660.161287475 30 atime=1456594661.705352384 30 ctime=1456594660.161287475 openvswitch-2.5.0/datapath-windows/Package/0000775000175000017500000000000012664357344022150 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/datapath-windows/Package/PaxHeaders.69223/package.VcxProj0000644000000000000000000000013212631676262023365 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.299089913 30 ctime=1456594660.157287306 openvswitch-2.5.0/datapath-windows/Package/package.VcxProj0000664000175000017500000001146012631676262025057 0ustar00jpettitjpettit00000000000000 Win8.1 Debug x64 Win8 Debug x64 Win8.1 Release x64 Win8 Release x64 Utility Package true Win8 Debug $(VCTargetsPath11) {911D7389-3E61-449F-B8F3-14AD7EE9A0F2} {E753AF15-94DC-4773-AED9-06A6636E6E67} $(MSBuildProjectName) WindowsV6.3 true WindowsKernelModeDriver8.1 Windows8 true WindowsKernelModeDriver8.1 WindowsV6.3 false WindowsKernelModeDriver8.1 Windows8 false WindowsKernelModeDriver8.1 DbgengKernelDebugger False False None %PathToInf% False False True 133563 true true true true {63FE215D-98BE-4440-8081-C6160EFB80FA} openvswitch-2.5.0/datapath-windows/Package/PaxHeaders.69223/package.VcxProj.user0000644000000000000000000000013212631676262024342 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.299089913 30 ctime=1456594660.161287475 openvswitch-2.5.0/datapath-windows/Package/package.VcxProj.user0000664000175000017500000000124712631676262026036 0ustar00jpettitjpettit00000000000000 TestSign TestSign TestSign TestSign openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/misc0000644000000000000000000000013212664357344020003 xustar0030 mtime=1456594660.165287644 30 atime=1456594661.705352384 30 ctime=1456594660.165287644 openvswitch-2.5.0/datapath-windows/misc/0000775000175000017500000000000012664357344021550 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/datapath-windows/misc/PaxHeaders.69223/OVS.psm10000644000000000000000000000013212631676262021326 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.303090077 30 ctime=1456594660.161287475 openvswitch-2.5.0/datapath-windows/misc/OVS.psm10000664000175000017500000001306312631676262023021 0ustar00jpettitjpettit00000000000000<# Copyright 2014, 2015 Cloudbase Solutions Srl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. #> $WMI_JOB_STATUS_STARTED = 4096 $WMI_JOB_STATE_RUNNING = 4 $WMI_JOB_STATE_COMPLETED = 7 $hvassembly = [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.HyperV.PowerShell") function Set-VMNetworkAdapterOVSPort { [CmdletBinding()] param ( [parameter(Mandatory=$true, ValueFromPipeline=$true)] [Microsoft.HyperV.PowerShell.VMNetworkAdapter]$VMNetworkAdapter, [parameter(Mandatory=$true)] [ValidateLength(1, 48)] [string]$OVSPortName ) process { $ns = "root\virtualization\v2" $EscapedId = $VMNetworkAdapter.Id.Replace('\', '\\') $sd = gwmi -namespace $ns -class Msvm_EthernetPortAllocationSettingData -Filter "ElementName = '$OVSPortName'" if($sd) { if($sd.InstanceId.Contains($VMNetworkAdapter.Id)) { throw "The OVS port name '$OVSPortName' is already assigned to this port." } throw "Cannot assign the OVS port name '$OVSPortName' as it is already assigned to an other port." } $sd = gwmi -namespace $ns -class Msvm_EthernetPortAllocationSettingData -Filter "InstanceId like '$EscapedId%'" if($sd) { $sd.ElementName = $OVSPortName $vsms = gwmi -namespace $ns -class Msvm_VirtualSystemManagementService $retVal = $vsms.ModifyResourceSettings(@($sd.GetText(1))) try { CheckWMIReturnValue $retVal } catch { throw "Assigning OVS port '$OVSPortName' failed" } } } } function Get-VMNetworkAdapterByOVSPort { [CmdletBinding()] param ( [parameter(Mandatory=$true)] [ValidateLength(1, 48)] [string]$OVSPortName ) process { $ns = "root\virtualization\v2" $sd = gwmi -namespace $ns -class Msvm_EthernetPortAllocationSettingData -Filter "ElementName = '$OVSPortName'" if($sd) { return $sd } } } function Get-VMByOVSPort { [CmdletBinding()] param ( [parameter(Mandatory=$true)] [ValidateLength(1, 48)] [string]$OVSPortName ) process { $ns = "root\virtualization\v2" $vms = gwmi -namespace $ns -class Msvm_VirtualSystemSettingData ForEach($vm in $vms) { $ports = gwmi -Namespace $ns -Query " Associators of {$vm} Where ResultClass = Msvm_EthernetPortAllocationSettingData" if ($ports.ElementName -eq $OVSPortName) { return $vm } } } } #This function returns the Msvm_VirtualSystemSettingData given a VMName function Get-VMNetworkAdapterWithOVSPort { [CmdletBinding()] param ( [parameter(Mandatory=$true)] [ValidateLength(1, 1024)] [string]$vmName ) process { $ns = "root\virtualization\v2" $vm = {} $ports = {} $vm = gwmi -namespace $ns -class Msvm_VirtualSystemSettingData -Filter "ElementName = '$VMName'" $ports = gwmi -Namespace $ns -Query " Associators of {$vm} Where ResultClass = Msvm_EthernetPortAllocationSettingData" return $ports } } function CheckWMIReturnValue($retVal) { if ($retVal.ReturnValue -ne 0) { if ($retVal.ReturnValue -eq $WMI_JOB_STATUS_STARTED) { do { $job = [wmi]$retVal.Job } while ($job.JobState -eq $WMI_JOB_STATE_RUNNING) if ($job.JobState -ne $WMI_JOB_STATE_COMPLETED) { echo $job.ReturnValue $errorString = "Job Failed. Job State: " + $job.JobState.ToString() if ($job.__CLASS -eq "Msvm_ConcreteJob") { $errorString += " Error Code: " + $job.ErrorCode.ToString() $errorString += " Error Details: " + $job.ErrorDescription } else { $error = $job.GetError() if ($error.Error) { $errorString += " Error:" + $error.Error } } throw $errorString } } else { throw "Job Failed. Return Value: {0}" -f $job.ReturnValue } } } function Set-VMNetworkAdapterOVSPortDirect { [CmdletBinding()] param ( [parameter(Mandatory=$true)] [ValidateLength(1, 1024)] [string]$vmName, [parameter(Mandatory=$true)] [ValidateLength(1, 48)] [string]$OVSPortName ) process { $vnic = 0 if ($vmName) { $vnic = Get-VMNetworkAdapter -VMName $vmName } # XXX the vnic index should be provided by the caller $vnic[0] | Set-VMNetworkAdapterOVSPort -OVSPortName $OVSPortName } } Export-ModuleMember -function Set-*, Get-* openvswitch-2.5.0/datapath-windows/misc/PaxHeaders.69223/install.cmd0000644000000000000000000000013212631676262022210 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.303090077 30 ctime=1456594660.161287475 openvswitch-2.5.0/datapath-windows/misc/install.cmd0000664000175000017500000000010412631676262023673 0ustar00jpettitjpettit00000000000000netcfg -l .\ovsext.inf -c s -i OVSExt net stop vmms net start vmms openvswitch-2.5.0/datapath-windows/misc/PaxHeaders.69223/uninstall.cmd0000644000000000000000000000013212631676262022553 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.303090077 30 ctime=1456594660.165287644 openvswitch-2.5.0/datapath-windows/misc/uninstall.cmd0000664000175000017500000000002112631676262024234 0ustar00jpettitjpettit00000000000000netcfg -u OVSExt openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/DESIGN0000644000000000000000000000013212631676262020016 xustar0030 mtime=1449622706.934438063 30 atime=1456592667.303090077 30 ctime=1456594660.157287306 openvswitch-2.5.0/datapath-windows/DESIGN0000664000175000017500000005625112631676262021517 0ustar00jpettitjpettit00000000000000 OVS-on-Hyper-V Design Document ============================== There has been a community effort to develop Open vSwitch on Microsoft Hyper-V. In this document, we provide details of the development effort. We believe this document should give enough information to understand the overall design. The userspace portion of the OVS has been ported to Hyper-V in a separate effort, and committed to the openvswitch repo. So, this document will mostly emphasize on the kernel driver, though we touch upon some of the aspects of userspace as well. We cover the following topics: 1. Background into relevant Hyper-V architecture 2. Design of the OVS Windows implementation a. Kernel module (datapath) b. Userspace components c. Kernel-Userspace interface d. Flow of a packet 3. Build/Deployment environment For more questions, please contact dev@openvswitch.org 1) Background into relevant Hyper-V architecture ------------------------------------------------ Microsoft’s hypervisor solution - Hyper-V[1] implements a virtual switch that is extensible and provides opportunities for other vendors to implement functional extensions[2]. The extensions need to be implemented as NDIS drivers that bind within the extensible switch driver stack provided. The extensions can broadly provide the functionality of monitoring, modifying and forwarding packets to destination ports on the Hyper-V extensible switch. Correspondingly, the extensions can be categorized into the following types and provide the functionality noted: * Capturing extensions: monitoring packets * Filtering extensions: monitoring, modifying packets * Forwarding extensions: monitoring, modifying, forwarding packets As can be expected, the kernel portion (datapath) of OVS on Hyper-V solution will be implemented as a forwarding extension. In Hyper-V, the virtual machine is called the Child Partition. Each VIF or physical NIC on the Hyper-V extensible switch is attached via a port. Each port is both on the ingress path or the egress path of the switch. The ingress path is used for packets being sent out of a port, and egress is used for packet being received on a port. By design, NDIS provides a layered interface. In this layered interface, higher level layers call into lower level layers, in the ingress path. In the egress path, it is the other way round. In addition, there is a object identifier (OID) interface for control operations Eg. addition of a port. The workflow for the calls is similar in nature to the packets, where higher level layers call into the lower level layers. A good representational diagram of this architecture is in [4]. Windows Filtering Platform (WFP)[5] is a platform implemented on Hyper-V that provides APIs and services for filtering packets. WFP has been utilized to filter on some of the packets that OVS is not equipped to handle directly. More details in later sections. IP Helper [6] is a set of API available on Hyper-V to retrieve information related to the network configuration information on the host machine. IP Helper has been used to retrieve some of the configuration information that OVS needs. 2) Design of the OVS Windows implementation ------------------------------------------- +-------------------------------+ | | | CHILD PARTITION | | | +------+ +--------------+ | +-----------+ +------------+ | | | | | | | | | | | | ovs- | | OVS- | | | Virtual | | Virtual | | | *ctl | | USERSPACE | | | Machine #1| | Machine #2 | | | | | DAEMON | | | | | | | +------+-++---+---------+ | +--+------+-+ +----+------++ | +--------+ | dpif- | | netdev- | | |VIF #1| |VIF #2| | |Physical| | netlink | | windows | | +------+ +------+ | | NIC | +---------+ +---------+ | || /\ | +--------+ User /\ /\ | || *#1* *#4* || | /\ =========||=========||============+------||-------------------||--+ || Kernel || || \/ || ||=====/ \/ \/ +-----+ +-----+ *#5* +-------------------------------+ | | | | | +----------------------+ | | | | | | | OVS Pseudo Device | | | | | | | +----------------------+ | | | | | | | Netlink Impl. | | | | | | | ----------------- | | I | | | | +------------+ | | N | | E | | | Flowtable | +------------+ | | G | | G | | +------------+ | Packet | |*#2*| R | | R | | +--------+ | Processing | |<=> | E | | E | | | WFP | | | | | S | | S | | | Driver | +------------+ | | S | | S | | +--------+ | | | | | | | | | | | | OVS FORWARDING EXTENSION | | | | | +-------------------------------+ +-----+-----------------+-----+ |HYPER-V Extensible Switch *#3| +-----------------------------+ NDIS STACK Fig 2. Various blocks of the OVS Windows implementation Figure 2 shows the various blocks involved in the OVS Windows implementation, along with some of the components available in the NDIS stack, and also the virtual machines. The workflow of a packet being transmitted from a VIF out and into another VIF and to a physical NIC is also shown. Later on in this section, we will discuss the flow of a packet at a high level. The figure gives a general idea of where the OVS userspace and the kernel components fit in, and how they interface with each other. The kernel portion (datapath) of OVS on Hyper-V solution has be implemented as a forwarding extension roughly implementing the following sub-modules/functionality. Details of each of these sub-components in the kernel are contained in later sections: * Interfacing with the NDIS stack * Netlink message parser * Netlink sockets * Switch/Datapath management * Interfacing with userspace portion of the OVS solution to implement the necessary functionality that userspace needs * Port management * Flowtable/Actions/packet forwarding * Tunneling * Event notifications The datapath for the OVS on Linux is a kernel module, and cannot be directly ported since there are significant differences in architecture even though the end functionality provided would be similar. Some examples of the differences are: * Interfacing with the NDIS stack to hook into the NDIS callbacks for functionality such as receiving and sending packets, packet completions, OIDs used for events such as a new port appearing on the virtual switch. * Interface between the userspace and the kernel module. * Event notifications are significantly different. * The communication interface between DPIF and the kernel module need not be implemented in the way OVS on Linux does. That said, it would be advantageous to have a similar interface to the kernel module for reasons of readability and maintainability. * Any licensing issues of using Linux kernel code directly. Due to these differences, it was a straightforward decision to develop the datapath for OVS on Hyper-V from scratch rather than porting the one on Linux. A re-development focused on the following goals: * Adhere to the existing requirements of userspace portion of OVS (such as ovs-vswitchd), to minimize changes in the userspace workflow. * Fit well into the typical workflow of a Hyper-V extensible switch forwarding extension. The userspace portion of the OVS solution is mostly POSIX code, and not very Linux specific. Majority of the userspace code does not interface directly with the kernel datapath and was ported independently of the kernel datapath effort. As explained in the OVS porting design document [7], DPIF is the portion of userspace that interfaces with the kernel portion of the OVS. The interface that each DPIF provider has to implement is defined in dpif-provider.h [3]. Though each platform is allowed to have its own implementation of the DPIF provider, it was found, via community feedback, that it is desired to share code whenever possible. Thus, the DPIF provider for OVS on Hyper-V shares code with the DPIF provider on Linux. This interface is implemented in dpif-netlink.c, formerly dpif-linux.c. We'll elaborate more on kernel-userspace interface in a dedicated section below. Here it suffices to say that the DPIF provider implementation for Windows is netlink-based and shares code with the Linux one. 2.a) Kernel module (datapath) ----------------------------- Interfacing with the NDIS stack ------------------------------- For each virtual switch on Hyper-V, the OVS extensible switch extension can be enabled/disabled. We support enabling the OVS extension on only one switch. This is consistent with using a single datapath in the kernel on Linux. All the physical adapters are connected as external adapters to the extensible switch. When the OVS switch extension registers itself as a filter driver, it also registers callbacks for the switch/port management and datapath functions. In other words, when a switch is created on the Hyper-V root partition (host), the extension gets an activate callback upon which it can initialize the data structures necessary for OVS to function. Similarly, there are callbacks for when a port gets added to the Hyper-V switch, and an External Network adapter or a VM Network adapter is connected/disconnected to the port. There are also callbacks for when a VIF (NIC of a child partition) send out a packet, or a packet is received on an external NIC. As shown in the figures, an extensible switch extension gets to see a packet sent by the VM (VIF) twice - once on the ingress path and once on the egress path. Forwarding decisions are to be made on the ingress path. Correspondingly, we will be hooking onto the following interfaces: * Ingress send indication: intercept packets for performing flow based forwarding.This includes straight forwarding to output ports. Any packet modifications needed to be performed are done here either inline or by creating a new packet. A forwarding action is performed as the flow actions dictate. * Ingress completion indication: cleanup and free packets that we generated on the ingress send path, pass-through for packets that we did not generate. * Egress receive indication: pass-through. * Egress completion indication: pass-through. Interfacing with OVS userspace ------------------------------ We have implemented a pseudo device interface for letting OVS userspace talk to the OVS kernel module. This is equivalent to the typical character device interface on POSIX platforms where we can register custom functions for read, write and ioctl functionality. The pseudo device supports a whole bunch of ioctls that netdev and DPIF on OVS userspace make use of. Netlink message parser ---------------------- The communication between OVS userspace and OVS kernel datapath is in the form of Netlink messages [1]. More details about this are provided in #2.c section, kernel-userspace interface. In the kernel, a full fledged netlink message parser has been implemented along the lines of the netlink message parser in OVS userspace. In fact, a lot of the code is ported code. On the lines of 'struct ofpbuf' in OVS userspace, a managed buffer has been implemented in the kernel datapath to make it easier to parse and construct netlink messages. Netlink sockets --------------- On Linux, OVS userspace utilizes netlink sockets to pass back and forth netlink messages. Since much of userspace code including DPIF provider in dpif-netlink.c (formerly dpif-linux.c) has been reused, pseudo-netlink sockets have been implemented in OVS userspace. As it is known, Windows lacks native netlink socket support, and also the socket family is not extensible either. Hence it is not possible to provide a native implementation of netlink socket. We emulate netlink sockets in lib/netlink-socket.c and support all of the nl_* APIs to higher levels. The implementation opens a handle to the pseudo device for each netlink socket. Some more details on this topic are provided in the userspace section on netlink sockets. Typical netlink semantics of read message, write message, dump, and transaction have been implemented so that higher level layers are not affected by the netlink implementation not being native. Switch/Datapath management -------------------------- As explained above, we hook onto the management callback functions in the NDIS interface for when to initialize the OVS data structures, flow tables etc. Some of this code is also driven by OVS userspace code which sends down ioctls for operations like creating a tunnel port etc. Port management --------------- As explained above, we hook onto the management callback functions in the NDIS interface to know when a port is added/connected to the Hyper-V switch. We use these callbacks to initialize the port related data structures in OVS. Also, some of the ports are tunnel ports that don’t exist on the Hyper-V switch and get added from OVS userspace. In order to identify a Hyper-V port, we use the value of 'FriendlyName' field in each Hyper-V port. We call this the "OVS-port-name". The idea is that OVS userspace sets 'OVS-port-name' in each Hyper-V port to the same value as the 'name' field of the 'Interface' table in OVSDB. When OVS userspace calls into the kernel datapath to add a port, we match the name of the port with the 'OVS-port-name' of a Hyper-V port. We maintain separate hash tables, and separate counters for ports that have been added from the Hyper-V switch, and for ports that have been added from OVS userspace. Flowtable/Actions/packet forwarding ----------------------------------- The flowtable and flow actions based packet forwarding is the core of the OVS datapath functionality. For each packet on the ingress path, we consult the flowtable and execute the corresponding actions. The actions can be limited to simple forwarding to a particular destination port(s), or more commonly involves modifying the packet to insert a tunnel context or a VLAN ID, and thereafter forwarding to the external port to send the packet to a destination host. Tunneling --------- We make use of the Internal Port on a Hyper-V switch for implementing tunneling. The Internal Port is a virtual adapter that is exposed on the Hyper- V host, and connected to the Hyper-V switch. Basically, it is an interface between the host and the virtual switch. The Internal Port acts as the Tunnel end point for the host (aka VTEP), and holds the VTEP IP address. Tunneling ports are not actual ports on the Hyper-V switch. These are virtual ports that OVS maintains and while executing actions, if the outport is a tunnel port, we short circuit by performing the encapsulation action based on the tunnel context. The encapsulated packet gets forwarded to the external port, and appears to the outside world as though it was set from the VTEP. Similarly, when a tunneled packet enters the OVS from the external port bound to the internal port (VTEP), and if yes, we short circuit the path, and directly forward the inner packet to the destination port (mostly a VIF, but dictated by the flow). We leverage the Windows Filtering Platform (WFP) framework to be able to receive tunneled packets that cannot be decapsulated by OVS right away. Currently, fragmented IP packets fall into that category, and we leverage the code in the host IP stack to reassemble the packet, and performing decapsulation on the reassembled packet. We’ll also be using the IP helper library to provide us IP address and other information corresponding to the Internal port. Event notifications ------------------- The pseudo device interface described above is also used for providing event notifications back to OVS userspace. A shared memory/overlapped IO model is used. 2.b) Userspace components ------------------------- The userspace portion of the OVS solution is mostly POSIX code, and not very Linux specific. Majority of the userspace code does not interface directly with the kernel datapath and was ported independently of the kernel datapath effort. In this section, we cover the userspace components that interface with the kernel datapath. As explained earlier, OVS on Hyper-V shares the DPIF provider implementation with Linux. The DPIF provider on Linux uses netlink sockets and netlink messages. Netlink sockets and messages are extensively used on Linux to exchange information between userspace and kernel. In order to satisfy these dependencies, netlink socket (pseudo and non-native) and netlink messages are implemented on Hyper-V. The following are the major advantages of sharing DPIF provider code: 1. Maintenance is simpler: Any change made to the interface defined in dpif-provider.h need not be propagated to multiple implementations. Also, developers familiar with the Linux implementation of the DPIF provider can easily ramp on the Hyper-V implementation as well. 2. Netlink messages provides inherent advantages: Netlink messages are known for their extensibility. Each message is versioned, so the provided data structures offer a mechanism to perform version checking and forward/backward compatibility with the kernel module. Netlink sockets --------------- As explained in other sections, an emulation of netlink sockets has been implemented in lib/netlink-socket.c for Windows. The implementation creates a handle to the OVS pseudo device, and emulates netlink socket semantics of receive message, send message, dump, and transact. Most of the nl_* functions are supported. The fact that the implementation is non-native manifests in various ways. One example is that PID for the netlink socket is not automatically assigned in userspace when a handle is created to the OVS pseudo device. There's an extra command (defined in OvsDpInterfaceExt.h) that is used to grab the PID generated in the kernel. DPIF provider -------------- As has been mentioned in earlier sections, the netlink socket and netlink message based DPIF provider on Linux has been ported to Windows. Correspondingly, the file is called lib/dpif-netlink.c now from its former name of lib/dpif-linux.c. Most of the code is common. Some divergence is in the code to receive packets. The Linux implementation uses epoll() which is not natively supported on Windows. Netdev-Windows -------------- We have a Windows implementation of the interface defined in lib/netdev-provider.h. The implementation provides functionality to get extended information about an interface. It is limited in functionality compared to the Linux implementation of the netdev provider and cannot be used to add any interfaces in the kernel such as a tap interface or to send/receive packets. The netdev-windows implementation uses the datapath interface extensions defined in: datapath-windows/include/OvsDpInterfaceExt.h Powershell extensions to set "OVS-port-name" -------------------------------------------- As explained in the section on "Port management", each Hyper-V port has a 'FriendlyName' field, which we call as the "OVS-port-name" field. We have implemented powershell command extensions to be able to set the "OVS-port-name" of a Hyper-V port. 2.c) Kernel-Userspace interface ------------------------------- openvswitch.h and OvsDpInterfaceExt.h ------------------------------------- Since the DPIF provider is shared with Linux, the kernel datapath provides the same interface as the Linux datapath. The interface is defined in datapath/linux/compat/include/linux/openvswitch.h. Derivatives of this interface file are created during OVS userspace compilation. The derivative for the kernel datapath on Hyper-V is provided in the following location: datapath-windows/include/OvsDpInterface.h That said, there are Windows specific extensions that are defined in the interface file: datapath-windows/include/OvsDpInterfaceExt.h 2.d) Flow of a packet --------------------- Figure 2 shows the numbered steps in which a packets gets sent out of a VIF and is forwarded to another VIF or a physical NIC. As mentioned earlier, each VIF is attached to the switch via a port, and each port is both on the ingress and egress path of the switch, and depending on whether a packet is being transmitted or received, one of the paths gets used. In the figure, each step n is annotated as *#n* The steps are as follows: 1. When a packet is sent out of a VIF or an physical NIC or an internal port, the packet is part of the ingress path. 2. The OVS kernel driver gets to intercept this packet. a. OVS looks up the flows in the flowtable for this packet, and executes the corresponding action. b. If there is not action, the packet is sent up to OVS userspace to examine the packet and figure out the actions. v. Userspace executes the packet by specifying the actions, and might also insert a flow for such a packet in the future. d. The destination ports are added to the packet and sent down to the Hyper- V switch. 3. The Hyper-V forwards the packet to the destination ports specified in the packet, and sends it out on the egress path. 4. The packet gets forwarded to the destination VIF. 5. It might also get forwarded to a physical NIC as well, if the physical NIC has been added as a destination port by OVS. 3) Build/Deployment: -------------------- The userspace components added as part of OVS Windows implementation have been integrated with autoconf, and can be built using the steps mentioned in the BUILD.Windows file. Additional targets need to be specified to make. The OVS kernel code is part of a Visual Studio 2013 solution, and is compiled from the IDE. There are plans in the future to move this to a compilation mode such that we can compile it without an IDE as well. Once compiled, we have an install script that can be used to load the kernel driver. Reference list: =============== 1. Hyper-V Extensible Switch http://msdn.microsoft.com/en-us/library/windows/hardware/hh598161(v=vs.85).aspx 2. Hyper-V Extensible Switch Extensions http://msdn.microsoft.com/en-us/library/windows/hardware/hh598169(v=vs.85).aspx 3. DPIF Provider http://openvswitch.sourcearchive.com/documentation/1.1.0-1/dpif- provider_8h_source.html 4. Hyper-V Extensible Switch Components http://msdn.microsoft.com/en-us/library/windows/hardware/hh598163(v=vs.85).aspx 5. Windows Filtering Platform http://msdn.microsoft.com/en-us/library/windows/desktop/aa366510(v=vs.85).aspx 6. IP Helper http://msdn.microsoft.com/en-us/library/windows/hardware/ff557015(v=vs.85).aspx 7. How to Port Open vSwitch to New Software or Hardware http://git.openvswitch.org/cgi-bin/gitweb.cgi?p=openvswitch;a=blob;f=PORTING 8. Netlink http://en.wikipedia.org/wiki/Netlink 9. epoll http://en.wikipedia.org/wiki/Epoll openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/ovsext0000644000000000000000000000013012664357344020376 xustar0029 mtime=1456594660.23729067 30 atime=1456594661.705352384 29 ctime=1456594660.23729067 openvswitch-2.5.0/datapath-windows/ovsext/0000775000175000017500000000000012664357344022145 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Actions.c0000644000000000000000000000013212664352753022220 xustar0030 mtime=1456592363.426620342 30 atime=1456592368.170815194 30 ctime=1456594660.165287644 openvswitch-2.5.0/datapath-windows/ovsext/Actions.c0000664000175000017500000016621212664352753023720 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Checksum.h" #include "Event.h" #include "Flow.h" #include "Gre.h" #include "NetProto.h" #include "PacketIO.h" #include "Stt.h" #include "Switch.h" #include "User.h" #include "Vport.h" #include "Vxlan.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_ACTION #include "Debug.h" typedef struct _OVS_ACTION_STATS { UINT64 rxGre; UINT64 txGre; UINT64 rxVxlan; UINT64 txVxlan; UINT64 rxStt; UINT64 txStt; UINT64 flowMiss; UINT64 flowUserspace; UINT64 txTcp; UINT32 failedFlowMiss; UINT32 noVport; UINT32 failedFlowExtract; UINT32 noResource; UINT32 noCopiedNbl; UINT32 failedEncap; UINT32 failedDecap; UINT32 cannotGrowDest; UINT32 zeroActionLen; UINT32 failedChecksum; } OVS_ACTION_STATS, *POVS_ACTION_STATS; OVS_ACTION_STATS ovsActionStats; /* * There a lot of data that needs to be maintained while executing the pipeline * as dictated by the actions of a flow, across different functions at different * levels. Such data is put together in a 'context' structure. Care should be * exercised while adding new members to the structure - only add ones that get * used across multiple stages in the pipeline/get used in multiple functions. */ #define OVS_DEST_PORTS_ARRAY_MIN_SIZE 2 typedef struct OvsForwardingContext { POVS_SWITCH_CONTEXT switchContext; /* The NBL currently used in the pipeline. */ PNET_BUFFER_LIST curNbl; /* NDIS forwarding detail for 'curNbl'. */ PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; /* Array of destination ports for 'curNbl'. */ PNDIS_SWITCH_FORWARDING_DESTINATION_ARRAY destinationPorts; /* send flags while sending 'curNbl' into NDIS. */ ULONG sendFlags; /* Total number of output ports, used + unused, in 'curNbl'. */ UINT32 destPortsSizeIn; /* Total number of used output ports in 'curNbl'. */ UINT32 destPortsSizeOut; /* * If 'curNbl' is not owned by OVS, they need to be tracked, if they need to * be freed/completed. */ OvsCompletionList *completionList; /* * vport number of 'curNbl' when it is passed from the PIF bridge to the INT * bridge. ie. during tunneling on the Rx side. */ UINT32 srcVportNo; /* * Tunnel key: * - specified in actions during tunneling Tx * - extracted from an NBL during tunneling Rx */ OvsIPv4TunnelKey tunKey; /* * Tunneling - Tx: * To store the output port, when it is a tunneled port. We don't foresee * multiple tunneled ports as outport for any given NBL. */ POVS_VPORT_ENTRY tunnelTxNic; /* * Tunneling - Rx: * Points to the Internal port on the PIF Bridge, if the packet needs to be * de-tunneled. */ POVS_VPORT_ENTRY tunnelRxNic; /* header information */ OVS_PACKET_HDR_INFO layers; } OvsForwardingContext; /* * -------------------------------------------------------------------------- * OvsInitForwardingCtx -- * Function to init/re-init the 'ovsFwdCtx' context as the actions pipeline * is being executed. * * Result: * NDIS_STATUS_SUCCESS on success * Other NDIS_STATUS upon failure. Upon failure, it is safe to call * OvsCompleteNBLForwardingCtx(), since 'ovsFwdCtx' has been initialized * enough for OvsCompleteNBLForwardingCtx() to do its work. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsInitForwardingCtx(OvsForwardingContext *ovsFwdCtx, POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, UINT32 srcVportNo, ULONG sendFlags, PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail, OvsCompletionList *completionList, OVS_PACKET_HDR_INFO *layers, BOOLEAN resetTunnelInfo) { ASSERT(ovsFwdCtx); ASSERT(switchContext); ASSERT(curNbl); ASSERT(fwdDetail); /* * Set values for curNbl and switchContext so upon failures, we have enough * information to do cleanup. */ ovsFwdCtx->curNbl = curNbl; ovsFwdCtx->switchContext = switchContext; ovsFwdCtx->completionList = completionList; ovsFwdCtx->fwdDetail = fwdDetail; if (fwdDetail->NumAvailableDestinations > 0) { /* * XXX: even though MSDN says GetNetBufferListDestinations() returns * NDIS_STATUS, the header files say otherwise. */ switchContext->NdisSwitchHandlers.GetNetBufferListDestinations( switchContext->NdisSwitchContext, curNbl, &ovsFwdCtx->destinationPorts); ASSERT(ovsFwdCtx->destinationPorts); /* Ensure that none of the elements are consumed yet. */ ASSERT(ovsFwdCtx->destinationPorts->NumElements == fwdDetail->NumAvailableDestinations); } else { ovsFwdCtx->destinationPorts = NULL; } ovsFwdCtx->destPortsSizeIn = fwdDetail->NumAvailableDestinations; ovsFwdCtx->destPortsSizeOut = 0; ovsFwdCtx->srcVportNo = srcVportNo; ovsFwdCtx->sendFlags = sendFlags; if (layers) { ovsFwdCtx->layers = *layers; } else { RtlZeroMemory(&ovsFwdCtx->layers, sizeof ovsFwdCtx->layers); } if (resetTunnelInfo) { ovsFwdCtx->tunnelTxNic = NULL; ovsFwdCtx->tunnelRxNic = NULL; RtlZeroMemory(&ovsFwdCtx->tunKey, sizeof ovsFwdCtx->tunKey); } return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsDetectTunnelRxPkt -- * Utility function for an RX packet to detect its tunnel type. * * Result: * True - if the tunnel type was detected. * False - if not a tunnel packet or tunnel type not supported. * -------------------------------------------------------------------------- */ static __inline BOOLEAN OvsDetectTunnelRxPkt(OvsForwardingContext *ovsFwdCtx, const OvsFlowKey *flowKey) { POVS_VPORT_ENTRY tunnelVport = NULL; /* XXX: we should also check for the length of the UDP payload to pick * packets only if they are at least VXLAN header size. */ if (!flowKey->ipKey.nwFrag) { UINT16 dstPort = htons(flowKey->ipKey.l4.tpDst); switch (flowKey->ipKey.nwProto) { case IPPROTO_GRE: tunnelVport = OvsFindTunnelVportByPortType(ovsFwdCtx->switchContext, OVS_VPORT_TYPE_GRE); if (tunnelVport) { ovsActionStats.rxGre++; } break; case IPPROTO_TCP: tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext, dstPort, OVS_VPORT_TYPE_STT); if (tunnelVport) { ovsActionStats.rxStt++; } break; case IPPROTO_UDP: tunnelVport = OvsFindTunnelVportByDstPort(ovsFwdCtx->switchContext, dstPort, OVS_VPORT_TYPE_VXLAN); if (tunnelVport) { ovsActionStats.rxVxlan++; } break; } } // We might get tunnel packets even before the tunnel gets initialized. if (tunnelVport) { ASSERT(ovsFwdCtx->tunnelRxNic == NULL); ovsFwdCtx->tunnelRxNic = tunnelVport; return TRUE; } return FALSE; } /* * -------------------------------------------------------------------------- * OvsDetectTunnelPkt -- * Utility function to detect if a packet is to be subjected to * tunneling (Tx) or de-tunneling (Rx). Various factors such as source * port, destination port, packet contents, and previously setup tunnel * context are used. * * Result: * True - If the packet is to be subjected to tunneling. * In case of invalid tunnel context, the tunneling functionality is * a no-op and is completed within this function itself by consuming * all of the tunneling context. * False - If not a tunnel packet or tunnel type not supported. Caller should * process the packet as a non-tunnel packet. * -------------------------------------------------------------------------- */ static __inline BOOLEAN OvsDetectTunnelPkt(OvsForwardingContext *ovsFwdCtx, const POVS_VPORT_ENTRY dstVport, const OvsFlowKey *flowKey) { if (OvsIsInternalVportType(dstVport->ovsType)) { /* * Rx: * The source of NBL during tunneling Rx could be the external * port or if it is being executed from userspace, the source port is * default port. */ BOOLEAN validSrcPort = (ovsFwdCtx->fwdDetail->SourcePortId == ovsFwdCtx->switchContext->virtualExternalPortId) || (ovsFwdCtx->fwdDetail->SourcePortId == NDIS_SWITCH_DEFAULT_PORT_ID); if (validSrcPort && OvsDetectTunnelRxPkt(ovsFwdCtx, flowKey)) { ASSERT(ovsFwdCtx->tunnelTxNic == NULL); ASSERT(ovsFwdCtx->tunnelRxNic != NULL); return TRUE; } } else if (OvsIsTunnelVportType(dstVport->ovsType)) { ASSERT(ovsFwdCtx->tunnelTxNic == NULL); ASSERT(ovsFwdCtx->tunnelRxNic == NULL); /* * Tx: * The destination port is a tunnel port. Encapsulation must be * performed only on packets that originate from: * - a VIF port * - a bridge-internal port (packets generated from userspace) * - no port. * * If the packet will not be encapsulated, consume the tunnel context * by clearing it. */ if (ovsFwdCtx->srcVportNo != OVS_DPPORT_NUMBER_INVALID) { POVS_VPORT_ENTRY vport = OvsFindVportByPortNo( ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo); if (!vport || (vport->ovsType != OVS_VPORT_TYPE_NETDEV && !OvsIsBridgeInternalVport(vport))) { ovsFwdCtx->tunKey.dst = 0; } } /* Tunnel the packet only if tunnel context is set. */ if (ovsFwdCtx->tunKey.dst != 0) { switch(dstVport->ovsType) { case OVS_VPORT_TYPE_GRE: ovsActionStats.txGre++; break; case OVS_VPORT_TYPE_VXLAN: ovsActionStats.txVxlan++; break; case OVS_VPORT_TYPE_STT: ovsActionStats.txStt++; break; } ovsFwdCtx->tunnelTxNic = dstVport; } return TRUE; } return FALSE; } /* * -------------------------------------------------------------------------- * OvsAddPorts -- * Add the specified destination vport into the forwarding context. If the * vport is a VIF/external port, it is added directly to the NBL. If it is * a tunneling port, it is NOT added to the NBL. * * Result: * NDIS_STATUS_SUCCESS on success * Other NDIS_STATUS upon failure. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsAddPorts(OvsForwardingContext *ovsFwdCtx, OvsFlowKey *flowKey, NDIS_SWITCH_PORT_ID dstPortId, BOOLEAN preserveVLAN, BOOLEAN preservePriority) { POVS_VPORT_ENTRY vport; PNDIS_SWITCH_PORT_DESTINATION fwdPort; NDIS_STATUS status; POVS_SWITCH_CONTEXT switchContext = ovsFwdCtx->switchContext; /* * We hold the dispatch lock that protects the list of vports, so vports * validated here can be added as destinations safely before we call into * NDIS. * * Some of the vports can be tunnelled ports as well in which case * they should be added to a separate list of tunnelled destination ports * instead of the VIF ports. The context for the tunnel is settable * in OvsForwardingContext. */ vport = OvsFindVportByPortNo(ovsFwdCtx->switchContext, dstPortId); if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { /* * There may be some latency between a port disappearing, and userspace * updating the recalculated flows. In the meantime, handle invalid * ports gracefully. */ ovsActionStats.noVport++; return NDIS_STATUS_SUCCESS; } ASSERT(vport->nicState == NdisSwitchNicStateConnected); vport->stats.txPackets++; vport->stats.txBytes += NET_BUFFER_DATA_LENGTH(NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl)); if (OvsIsBridgeInternalVport(vport)) { return NDIS_STATUS_SUCCESS; } if (OvsDetectTunnelPkt(ovsFwdCtx, vport, flowKey)) { return NDIS_STATUS_SUCCESS; } if (ovsFwdCtx->destPortsSizeOut == ovsFwdCtx->destPortsSizeIn) { if (ovsFwdCtx->destPortsSizeIn == 0) { ASSERT(ovsFwdCtx->destinationPorts == NULL); ASSERT(ovsFwdCtx->fwdDetail->NumAvailableDestinations == 0); status = switchContext->NdisSwitchHandlers.GrowNetBufferListDestinations( switchContext->NdisSwitchContext, ovsFwdCtx->curNbl, OVS_DEST_PORTS_ARRAY_MIN_SIZE, &ovsFwdCtx->destinationPorts); if (status != NDIS_STATUS_SUCCESS) { ovsActionStats.cannotGrowDest++; return status; } ovsFwdCtx->destPortsSizeIn = ovsFwdCtx->fwdDetail->NumAvailableDestinations; ASSERT(ovsFwdCtx->destinationPorts); } else { ASSERT(ovsFwdCtx->destinationPorts != NULL); /* * NumElements: * A ULONG value that specifies the total number of * NDIS_SWITCH_PORT_DESTINATION elements in the * NDIS_SWITCH_FORWARDING_DESTINATION_ARRAY structure. * * NumDestinations: * A ULONG value that specifies the number of * NDIS_SWITCH_PORT_DESTINATION elements in the * NDIS_SWITCH_FORWARDING_DESTINATION_ARRAY structure that * specify port destinations. * * NumAvailableDestinations: * A value that specifies the number of unused extensible switch * destination ports elements within an NET_BUFFER_LIST structure. */ ASSERT(ovsFwdCtx->destinationPorts->NumElements == ovsFwdCtx->destPortsSizeIn); ASSERT(ovsFwdCtx->destinationPorts->NumDestinations == ovsFwdCtx->destPortsSizeOut - ovsFwdCtx->fwdDetail->NumAvailableDestinations); ASSERT(ovsFwdCtx->fwdDetail->NumAvailableDestinations > 0); /* * Before we grow the array of destination ports, the current set * of ports needs to be committed. Only the ports added since the * last commit need to be part of the new update. */ status = switchContext->NdisSwitchHandlers.UpdateNetBufferListDestinations( switchContext->NdisSwitchContext, ovsFwdCtx->curNbl, ovsFwdCtx->fwdDetail->NumAvailableDestinations, ovsFwdCtx->destinationPorts); if (status != NDIS_STATUS_SUCCESS) { ovsActionStats.cannotGrowDest++; return status; } ASSERT(ovsFwdCtx->destinationPorts->NumElements == ovsFwdCtx->destPortsSizeIn); ASSERT(ovsFwdCtx->destinationPorts->NumDestinations == ovsFwdCtx->destPortsSizeOut); ASSERT(ovsFwdCtx->fwdDetail->NumAvailableDestinations == 0); status = switchContext->NdisSwitchHandlers.GrowNetBufferListDestinations( switchContext->NdisSwitchContext, ovsFwdCtx->curNbl, ovsFwdCtx->destPortsSizeIn, &ovsFwdCtx->destinationPorts); if (status != NDIS_STATUS_SUCCESS) { ovsActionStats.cannotGrowDest++; return status; } ASSERT(ovsFwdCtx->destinationPorts != NULL); ovsFwdCtx->destPortsSizeIn <<= 1; } } ASSERT(ovsFwdCtx->destPortsSizeOut < ovsFwdCtx->destPortsSizeIn); fwdPort = NDIS_SWITCH_PORT_DESTINATION_AT_ARRAY_INDEX(ovsFwdCtx->destinationPorts, ovsFwdCtx->destPortsSizeOut); fwdPort->PortId = vport->portId; fwdPort->NicIndex = vport->nicIndex; fwdPort->IsExcluded = 0; fwdPort->PreserveVLAN = preserveVLAN; fwdPort->PreservePriority = preservePriority; ovsFwdCtx->destPortsSizeOut += 1; return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsClearTunTxCtx -- * Utility function to clear tx tunneling context. * -------------------------------------------------------------------------- */ static __inline VOID OvsClearTunTxCtx(OvsForwardingContext *ovsFwdCtx) { ovsFwdCtx->tunnelTxNic = NULL; ovsFwdCtx->tunKey.dst = 0; } /* * -------------------------------------------------------------------------- * OvsClearTunRxCtx -- * Utility function to clear rx tunneling context. * -------------------------------------------------------------------------- */ static __inline VOID OvsClearTunRxCtx(OvsForwardingContext *ovsFwdCtx) { ovsFwdCtx->tunnelRxNic = NULL; ovsFwdCtx->tunKey.dst = 0; } /* * -------------------------------------------------------------------------- * OvsCompleteNBLForwardingCtx -- * This utility function is responsible for freeing/completing an NBL - either * by adding it to a completion list or by freeing it. * * Side effects: * It also resets the necessary fields in 'ovsFwdCtx'. * -------------------------------------------------------------------------- */ static __inline VOID OvsCompleteNBLForwardingCtx(OvsForwardingContext *ovsFwdCtx, PCWSTR dropReason) { NDIS_STRING filterReason; RtlInitUnicodeString(&filterReason, dropReason); if (ovsFwdCtx->completionList) { OvsAddPktCompletionList(ovsFwdCtx->completionList, TRUE, ovsFwdCtx->fwdDetail->SourcePortId, ovsFwdCtx->curNbl, 1, &filterReason); ovsFwdCtx->curNbl = NULL; } else { /* If there is no completionList, we assume this is ovs created NBL */ ovsFwdCtx->curNbl = OvsCompleteNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, TRUE); ASSERT(ovsFwdCtx->curNbl == NULL); } /* XXX: these can be made debug only to save cycles. Ideally the pipeline * using these fields should reset the values at the end of the pipeline. */ ovsFwdCtx->destPortsSizeOut = 0; ovsFwdCtx->tunnelTxNic = NULL; ovsFwdCtx->tunnelRxNic = NULL; } /* * -------------------------------------------------------------------------- * OvsDoFlowLookupOutput -- * Function to be used for the second stage of a tunneling workflow, ie.: * - On the encapsulated packet on Tx path, to do a flow extract, flow * lookup and excuting the actions. * - On the decapsulated packet on Rx path, to do a flow extract, flow * lookup and excuting the actions. * * XXX: It is assumed that the NBL in 'ovsFwdCtx' is owned by OVS. This is * until the new buffer management framework is adopted. * * Side effects: * The NBL in 'ovsFwdCtx' is consumed. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsDoFlowLookupOutput(OvsForwardingContext *ovsFwdCtx) { OvsFlowKey key; OvsFlow *flow; UINT64 hash; NDIS_STATUS status; POVS_VPORT_ENTRY vport = OvsFindVportByPortNo(ovsFwdCtx->switchContext, ovsFwdCtx->srcVportNo); if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped due to internal/tunnel port removal"); ovsActionStats.noVport++; return NDIS_STATUS_SUCCESS; } ASSERT(vport->nicState == NdisSwitchNicStateConnected); /* Assert that in the Rx direction, key is always setup. */ ASSERT(ovsFwdCtx->tunnelRxNic == NULL || ovsFwdCtx->tunKey.dst != 0); status = OvsExtractFlow(ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo, &key, &ovsFwdCtx->layers, ovsFwdCtx->tunKey.dst != 0 ? &ovsFwdCtx->tunKey : NULL); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Flow extract failed"); ovsActionStats.failedFlowExtract++; return status; } flow = OvsLookupFlow(&ovsFwdCtx->switchContext->datapath, &key, &hash, FALSE); if (flow) { OvsFlowUsed(flow, ovsFwdCtx->curNbl, &ovsFwdCtx->layers); ovsFwdCtx->switchContext->datapath.hits++; status = OvsActionsExecute(ovsFwdCtx->switchContext, ovsFwdCtx->completionList, ovsFwdCtx->curNbl, ovsFwdCtx->srcVportNo, ovsFwdCtx->sendFlags, &key, &hash, &ovsFwdCtx->layers, flow->actions, flow->actionsLen); ovsFwdCtx->curNbl = NULL; } else { LIST_ENTRY missedPackets; UINT32 num = 0; ovsFwdCtx->switchContext->datapath.misses++; InitializeListHead(&missedPackets); status = OvsCreateAndAddPackets(NULL, 0, OVS_PACKET_CMD_MISS, vport, &key,ovsFwdCtx->curNbl, FALSE, &ovsFwdCtx->layers, ovsFwdCtx->switchContext, &missedPackets, &num); if (num) { OvsQueuePackets(&missedPackets, num); } if (status == NDIS_STATUS_SUCCESS) { /* Complete the packet since it was copied to user buffer. */ OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped since packet was copied to userspace"); ovsActionStats.flowMiss++; status = NDIS_STATUS_SUCCESS; } else { OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped due to failure to queue to userspace"); status = NDIS_STATUS_FAILURE; ovsActionStats.failedFlowMiss++; } } return status; } /* * -------------------------------------------------------------------------- * OvsTunnelPortTx -- * The start function for Tx tunneling - encapsulates the packet, and * outputs the packet on the PIF bridge. * * Side effects: * The NBL in 'ovsFwdCtx' is consumed. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsTunnelPortTx(OvsForwardingContext *ovsFwdCtx) { NDIS_STATUS status = NDIS_STATUS_FAILURE; PNET_BUFFER_LIST newNbl = NULL; /* * Setup the source port to be the internal port to as to facilitate the * second OvsLookupFlow. */ if (ovsFwdCtx->switchContext->internalVport == NULL || ovsFwdCtx->switchContext->virtualExternalVport == NULL) { OvsClearTunTxCtx(ovsFwdCtx); OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped since either internal or external port is absent"); return NDIS_STATUS_FAILURE; } ovsFwdCtx->srcVportNo = ((POVS_VPORT_ENTRY)ovsFwdCtx->switchContext->internalVport)->portNo; ovsFwdCtx->fwdDetail->SourcePortId = ovsFwdCtx->switchContext->internalPortId; ovsFwdCtx->fwdDetail->SourceNicIndex = ((POVS_VPORT_ENTRY)ovsFwdCtx->switchContext->internalVport)->nicIndex; /* Do the encap. Encap function does not consume the NBL. */ switch(ovsFwdCtx->tunnelTxNic->ovsType) { case OVS_VPORT_TYPE_GRE: status = OvsEncapGre(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, &ovsFwdCtx->layers, &newNbl); break; case OVS_VPORT_TYPE_VXLAN: status = OvsEncapVxlan(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, &ovsFwdCtx->layers, &newNbl); break; case OVS_VPORT_TYPE_STT: status = OvsEncapStt(ovsFwdCtx->tunnelTxNic, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, ovsFwdCtx->switchContext, &ovsFwdCtx->layers, &newNbl); break; default: ASSERT(! "Tx: Unhandled tunnel type"); } /* Reset the tunnel context so that it doesn't get used after this point. */ OvsClearTunTxCtx(ovsFwdCtx); if (status == NDIS_STATUS_SUCCESS) { ASSERT(newNbl); OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"Complete after cloning NBL for encapsulation"); ovsFwdCtx->curNbl = newNbl; status = OvsDoFlowLookupOutput(ovsFwdCtx); ASSERT(ovsFwdCtx->curNbl == NULL); } else { /* * XXX: Temporary freeing of the packet until we register a * callback to IP helper. */ OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped due to encap failure"); ovsActionStats.failedEncap++; status = NDIS_STATUS_SUCCESS; } return status; } /* * -------------------------------------------------------------------------- * OvsTunnelPortRx -- * Decapsulate the incoming NBL based on the tunnel type and goes through * the flow lookup for the inner packet. * * Note: IP checksum is validate here, but L4 checksum validation needs * to be done by the corresponding tunnel types. * * Side effects: * The NBL in 'ovsFwdCtx' is consumed. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsTunnelPortRx(OvsForwardingContext *ovsFwdCtx) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNET_BUFFER_LIST newNbl = NULL; POVS_VPORT_ENTRY tunnelRxVport = ovsFwdCtx->tunnelRxNic; PCWSTR dropReason = L"OVS-dropped due to new decap packet"; if (OvsValidateIPChecksum(ovsFwdCtx->curNbl, &ovsFwdCtx->layers) != NDIS_STATUS_SUCCESS) { ovsActionStats.failedChecksum++; OVS_LOG_INFO("Packet dropped due to IP checksum failure."); goto dropNbl; } /* * Decap port functions should return a new NBL if it was copied, and * this new NBL should be setup as the ovsFwdCtx->curNbl. */ switch(tunnelRxVport->ovsType) { case OVS_VPORT_TYPE_GRE: status = OvsDecapGre(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, &newNbl); break; case OVS_VPORT_TYPE_VXLAN: status = OvsDecapVxlan(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, &newNbl); break; case OVS_VPORT_TYPE_STT: status = OvsDecapStt(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, &ovsFwdCtx->tunKey, &newNbl); if (status == NDIS_STATUS_SUCCESS && newNbl == NULL) { /* This was an STT-LSO Fragment */ dropReason = L"OVS-STT segment is cached"; } break; default: OVS_LOG_ERROR("Rx: Unhandled tunnel type: %d\n", tunnelRxVport->ovsType); ASSERT(! "Rx: Unhandled tunnel type"); status = NDIS_STATUS_NOT_SUPPORTED; } if (status != NDIS_STATUS_SUCCESS) { ovsActionStats.failedDecap++; goto dropNbl; } /* * tunnelRxNic and other fields will be cleared, re-init the context * before usage. */ OvsCompleteNBLForwardingCtx(ovsFwdCtx, dropReason); if (newNbl) { /* Decapsulated packet is in a new NBL */ ovsFwdCtx->tunnelRxNic = tunnelRxVport; OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, newNbl, tunnelRxVport->portNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), ovsFwdCtx->completionList, &ovsFwdCtx->layers, FALSE); /* * Set the NBL's SourcePortId and SourceNicIndex to default values to * keep NDIS happy when we forward the packet. */ ovsFwdCtx->fwdDetail->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; ovsFwdCtx->fwdDetail->SourceNicIndex = 0; status = OvsDoFlowLookupOutput(ovsFwdCtx); } ASSERT(ovsFwdCtx->curNbl == NULL); OvsClearTunRxCtx(ovsFwdCtx); return status; dropNbl: OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-dropped due to decap failure"); OvsClearTunRxCtx(ovsFwdCtx); return status; } /* * -------------------------------------------------------------------------- * OvsOutputForwardingCtx -- * This function outputs an NBL to NDIS or to a tunneling pipeline based on * the ports added so far into 'ovsFwdCtx'. * * Side effects: * This function consumes the NBL - either by forwarding it successfully to * NDIS, or adding it to the completion list in 'ovsFwdCtx', or freeing it. * * Also makes sure that the list of destination ports - tunnel or otherwise is * drained. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsOutputForwardingCtx(OvsForwardingContext *ovsFwdCtx) { NDIS_STATUS status = STATUS_SUCCESS; POVS_SWITCH_CONTEXT switchContext = ovsFwdCtx->switchContext; PCWSTR dropReason; /* * Handle the case where the some of the destination ports are tunneled * ports - the non-tunneled ports get a unmodified copy of the NBL, and the * tunneling pipeline starts when we output the packet to tunneled port. */ if (ovsFwdCtx->destPortsSizeOut > 0) { PNET_BUFFER_LIST newNbl = NULL; PNET_BUFFER nb; UINT32 portsToUpdate = ovsFwdCtx->fwdDetail->NumAvailableDestinations - (ovsFwdCtx->destPortsSizeIn - ovsFwdCtx->destPortsSizeOut); ASSERT(ovsFwdCtx->destinationPorts != NULL); /* * Create a copy of the packet in order to do encap on it later. Also, * don't copy the offload context since the encap'd packet has a * different set of headers. This will change when we implement offloads * before doing encapsulation. */ if (ovsFwdCtx->tunnelTxNic != NULL || ovsFwdCtx->tunnelRxNic != NULL) { nb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl); newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, 0, 0, TRUE /*copy NBL info*/); if (newNbl == NULL) { status = NDIS_STATUS_RESOURCES; ovsActionStats.noCopiedNbl++; dropReason = L"Dropped due to failure to create NBL copy."; goto dropit; } } /* It does not seem like we'll get here unless 'portsToUpdate' > 0. */ ASSERT(portsToUpdate > 0); status = switchContext->NdisSwitchHandlers.UpdateNetBufferListDestinations( switchContext->NdisSwitchContext, ovsFwdCtx->curNbl, portsToUpdate, ovsFwdCtx->destinationPorts); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE); ovsActionStats.cannotGrowDest++; dropReason = L"Dropped due to failure to update destinations."; goto dropit; } OvsSendNBLIngress(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, ovsFwdCtx->sendFlags); /* End this pipeline by resetting the corresponding context. */ ovsFwdCtx->destPortsSizeOut = 0; ovsFwdCtx->curNbl = NULL; if (newNbl) { status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, newNbl, ovsFwdCtx->srcVportNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), ovsFwdCtx->completionList, &ovsFwdCtx->layers, FALSE); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"Dropped due to resouces."; goto dropit; } } } if (ovsFwdCtx->tunnelTxNic != NULL) { status = OvsTunnelPortTx(ovsFwdCtx); ASSERT(ovsFwdCtx->tunnelTxNic == NULL); ASSERT(ovsFwdCtx->tunKey.dst == 0); } else if (ovsFwdCtx->tunnelRxNic != NULL) { status = OvsTunnelPortRx(ovsFwdCtx); ASSERT(ovsFwdCtx->tunnelRxNic == NULL); ASSERT(ovsFwdCtx->tunKey.dst == 0); } ASSERT(ovsFwdCtx->curNbl == NULL); return status; dropit: if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBLForwardingCtx(ovsFwdCtx, dropReason); } return status; } /* * -------------------------------------------------------------------------- * OvsLookupFlowOutput -- * Utility function for external callers to do flow extract, lookup, * actions execute on a given NBL. * * Note: If this is being used from a callback function, make sure that the * arguments specified are still valid in the asynchronous context. * * Side effects: * This function consumes the NBL. * -------------------------------------------------------------------------- */ VOID OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext, VOID *compList, PNET_BUFFER_LIST curNbl) { NDIS_STATUS status; OvsForwardingContext ovsFwdCtx; POVS_VPORT_ENTRY internalVport = (POVS_VPORT_ENTRY)switchContext->internalVport; /* XXX: make sure comp list was not a stack variable previously. */ OvsCompletionList *completionList = (OvsCompletionList *)compList; /* * XXX: can internal port disappear while we are busy doing ARP resolution? * It could, but will we get this callback from IP helper in that case. Need * to check. */ ASSERT(switchContext->internalVport); status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl, internalVport->portNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl), completionList, NULL, TRUE); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBLForwardingCtx(&ovsFwdCtx, L"OVS-Dropped due to resources"); return; } ASSERT(FALSE); /* * XXX: We need to acquire the dispatch lock and the datapath lock. */ OvsDoFlowLookupOutput(&ovsFwdCtx); } /* * -------------------------------------------------------------------------- * OvsOutputBeforeSetAction -- * Function to be called to complete one set of actions on an NBL, before * we start the next one. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsOutputBeforeSetAction(OvsForwardingContext *ovsFwdCtx) { PNET_BUFFER_LIST newNbl; NDIS_STATUS status = NDIS_STATUS_SUCCESS; /* * Create a copy and work on the copy after this point. The original NBL is * forwarded. One reason to not use the copy for forwarding is that * ports have already been added to the original NBL, and it might be * inefficient/impossible to remove/re-add them to the copy. There's no * notion of removing the ports, the ports need to be marked as * "isExcluded". There's seems no real advantage to retaining the original * and sending out the copy instead. * * XXX: We are copying the offload context here. This is to handle actions * such as: * outport, pop_vlan(), outport, push_vlan(), outport * * copy size needs to include inner ether + IP + TCP, need to revisit * if we support IP options. * XXX Head room needs to include the additional encap. * XXX copySize check is not considering multiple NBs. */ newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, 0, 0, TRUE /*copy NBL info*/); ASSERT(ovsFwdCtx->destPortsSizeOut > 0 || ovsFwdCtx->tunnelTxNic != NULL || ovsFwdCtx->tunnelRxNic != NULL); /* Send the original packet out and save the original source port number */ UINT32 tempVportNo = ovsFwdCtx->srcVportNo; status = OvsOutputForwardingCtx(ovsFwdCtx); ASSERT(ovsFwdCtx->curNbl == NULL); ASSERT(ovsFwdCtx->destPortsSizeOut == 0); ASSERT(ovsFwdCtx->tunnelRxNic == NULL); ASSERT(ovsFwdCtx->tunnelTxNic == NULL); /* If we didn't make a copy, can't continue. */ if (newNbl == NULL) { ovsActionStats.noCopiedNbl++; return NDIS_STATUS_RESOURCES; } /* Finish the remaining actions with the new NBL */ if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBL(ovsFwdCtx->switchContext, newNbl, TRUE); } else { status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, newNbl, tempVportNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), ovsFwdCtx->completionList, &ovsFwdCtx->layers, FALSE); } return status; } /* * -------------------------------------------------------------------------- * OvsPopVlanInPktBuf -- * Function to pop a VLAN tag when the tag is in the packet buffer. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsPopVlanInPktBuf(OvsForwardingContext *ovsFwdCtx) { PNET_BUFFER curNb; PMDL curMdl; PUINT8 bufferStart; ULONG dataLength = sizeof (DL_EUI48) + sizeof (DL_EUI48); UINT32 packetLen, mdlLen; PNET_BUFFER_LIST newNbl; NDIS_STATUS status; /* * Declare a dummy vlanTag structure since we need to compute the size * of shiftLength. The NDIS one is a unionized structure. */ NDIS_PACKET_8021Q_INFO vlanTag = {0}; ULONG shiftLength = sizeof (vlanTag.TagHeader); PUINT8 tempBuffer[sizeof (DL_EUI48) + sizeof (DL_EUI48)]; newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, 0, 0, TRUE /* copy NBL info */); if (!newNbl) { ovsActionStats.noCopiedNbl++; return NDIS_STATUS_RESOURCES; } /* Complete the original NBL and create a copy to modify. */ OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped due to copy"); status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, newNbl, ovsFwdCtx->srcVportNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), NULL, &ovsFwdCtx->layers, FALSE); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"Dropped due to resouces"); return NDIS_STATUS_RESOURCES; } curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl); packetLen = NET_BUFFER_DATA_LENGTH(curNb); ASSERT(curNb->Next == NULL); curMdl = NET_BUFFER_CURRENT_MDL(curNb); NdisQueryMdl(curMdl, &bufferStart, &mdlLen, LowPagePriority); if (!bufferStart) { return NDIS_STATUS_RESOURCES; } mdlLen -= NET_BUFFER_CURRENT_MDL_OFFSET(curNb); /* Bail out if L2 + VLAN header is not contiguous in the first buffer. */ if (MIN(packetLen, mdlLen) < sizeof (EthHdr) + shiftLength) { ASSERT(FALSE); return NDIS_STATUS_FAILURE; } bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); RtlCopyMemory(tempBuffer, bufferStart, dataLength); RtlCopyMemory(bufferStart + shiftLength, tempBuffer, dataLength); NdisAdvanceNetBufferDataStart(curNb, shiftLength, FALSE, NULL); return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsTunnelAttrToIPv4TunnelKey -- * Convert tunnel attribute to OvsIPv4TunnelKey. * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsTunnelAttrToIPv4TunnelKey(PNL_ATTR attr, OvsIPv4TunnelKey *tunKey) { PNL_ATTR a; INT rem; tunKey->attr[0] = 0; tunKey->attr[1] = 0; tunKey->attr[2] = 0; ASSERT(NlAttrType(attr) == OVS_KEY_ATTR_TUNNEL); NL_ATTR_FOR_EACH_UNSAFE (a, rem, NlAttrData(attr), NlAttrGetSize(attr)) { switch (NlAttrType(a)) { case OVS_TUNNEL_KEY_ATTR_ID: tunKey->tunnelId = NlAttrGetBe64(a); tunKey->flags |= OVS_TNL_F_KEY; break; case OVS_TUNNEL_KEY_ATTR_IPV4_SRC: tunKey->src = NlAttrGetBe32(a); break; case OVS_TUNNEL_KEY_ATTR_IPV4_DST: tunKey->dst = NlAttrGetBe32(a); break; case OVS_TUNNEL_KEY_ATTR_TOS: tunKey->tos = NlAttrGetU8(a); break; case OVS_TUNNEL_KEY_ATTR_TTL: tunKey->ttl = NlAttrGetU8(a); break; case OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT: tunKey->flags |= OVS_TNL_F_DONT_FRAGMENT; break; case OVS_TUNNEL_KEY_ATTR_CSUM: tunKey->flags |= OVS_TNL_F_CSUM; break; default: ASSERT(0); } } return NDIS_STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsUpdateEthHeader -- * Updates the ethernet header in ovsFwdCtx.curNbl inline based on the * specified key. *---------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsUpdateEthHeader(OvsForwardingContext *ovsFwdCtx, const struct ovs_key_ethernet *ethAttr) { PNET_BUFFER curNb; PMDL curMdl; PUINT8 bufferStart; EthHdr *ethHdr; UINT32 packetLen, mdlLen; curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl); ASSERT(curNb->Next == NULL); packetLen = NET_BUFFER_DATA_LENGTH(curNb); curMdl = NET_BUFFER_CURRENT_MDL(curNb); NdisQueryMdl(curMdl, &bufferStart, &mdlLen, LowPagePriority); if (!bufferStart) { ovsActionStats.noResource++; return NDIS_STATUS_RESOURCES; } mdlLen -= NET_BUFFER_CURRENT_MDL_OFFSET(curNb); ASSERT(mdlLen > 0); /* Bail out if the L2 header is not in a contiguous buffer. */ if (MIN(packetLen, mdlLen) < sizeof *ethHdr) { ASSERT(FALSE); return NDIS_STATUS_FAILURE; } ethHdr = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(curNb)); RtlCopyMemory(ethHdr->Destination, ethAttr->eth_dst, sizeof ethHdr->Destination); RtlCopyMemory(ethHdr->Source, ethAttr->eth_src, sizeof ethHdr->Source); return NDIS_STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsUpdateIPv4Header -- * Updates the IPv4 header in ovsFwdCtx.curNbl inline based on the * specified key. *---------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsUpdateIPv4Header(OvsForwardingContext *ovsFwdCtx, const struct ovs_key_ipv4 *ipAttr) { PNET_BUFFER curNb; PMDL curMdl; ULONG curMdlOffset; PUINT8 bufferStart; UINT32 mdlLen, hdrSize, packetLen; OVS_PACKET_HDR_INFO *layers = &ovsFwdCtx->layers; NDIS_STATUS status; IPHdr *ipHdr; TCPHdr *tcpHdr = NULL; UDPHdr *udpHdr = NULL; ASSERT(layers->value != 0); /* * Peek into the MDL to get a handle to the IP header and if required * the TCP/UDP header as well. We check if the required headers are in one * contiguous MDL, and if not, we copy them over to one MDL. */ curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl); ASSERT(curNb->Next == NULL); packetLen = NET_BUFFER_DATA_LENGTH(curNb); curMdl = NET_BUFFER_CURRENT_MDL(curNb); NdisQueryMdl(curMdl, &bufferStart, &mdlLen, LowPagePriority); if (!bufferStart) { ovsActionStats.noResource++; return NDIS_STATUS_RESOURCES; } curMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(curNb); mdlLen -= curMdlOffset; ASSERT((INT)mdlLen >= 0); if (layers->isTcp || layers->isUdp) { hdrSize = layers->l4Offset + layers->isTcp ? sizeof (*tcpHdr) : sizeof (*udpHdr); } else { hdrSize = layers->l3Offset + sizeof (*ipHdr); } /* Count of number of bytes of valid data there are in the first MDL. */ mdlLen = MIN(packetLen, mdlLen); if (mdlLen < hdrSize) { PNET_BUFFER_LIST newNbl; newNbl = OvsPartialCopyNBL(ovsFwdCtx->switchContext, ovsFwdCtx->curNbl, hdrSize, 0, TRUE /*copy NBL info*/); if (!newNbl) { ovsActionStats.noCopiedNbl++; return NDIS_STATUS_RESOURCES; } OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"Complete after partial copy."); status = OvsInitForwardingCtx(ovsFwdCtx, ovsFwdCtx->switchContext, newNbl, ovsFwdCtx->srcVportNo, 0, NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl), NULL, &ovsFwdCtx->layers, FALSE); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBLForwardingCtx(ovsFwdCtx, L"OVS-Dropped due to resources"); return NDIS_STATUS_RESOURCES; } curNb = NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx->curNbl); ASSERT(curNb->Next == NULL); curMdl = NET_BUFFER_CURRENT_MDL(curNb); NdisQueryMdl(curMdl, &bufferStart, &mdlLen, LowPagePriority); if (!curMdl) { ovsActionStats.noResource++; return NDIS_STATUS_RESOURCES; } curMdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(curNb); mdlLen -= curMdlOffset; ASSERT(mdlLen >= hdrSize); } ipHdr = (IPHdr *)(bufferStart + curMdlOffset + layers->l3Offset); if (layers->isTcp) { tcpHdr = (TCPHdr *)(bufferStart + curMdlOffset + layers->l4Offset); } else if (layers->isUdp) { udpHdr = (UDPHdr *)(bufferStart + curMdlOffset + layers->l4Offset); } /* * Adjust the IP header inline as dictated by the action, nad also update * the IP and the TCP checksum for the data modified. * * In the future, this could be optimized to make one call to * ChecksumUpdate32(). Ignoring this for now, since for the most common * case, we only update the TTL. */ if (ipHdr->saddr != ipAttr->ipv4_src) { if (tcpHdr) { tcpHdr->check = ChecksumUpdate32(tcpHdr->check, ipHdr->saddr, ipAttr->ipv4_src); } else if (udpHdr && udpHdr->check) { udpHdr->check = ChecksumUpdate32(udpHdr->check, ipHdr->saddr, ipAttr->ipv4_src); } if (ipHdr->check != 0) { ipHdr->check = ChecksumUpdate32(ipHdr->check, ipHdr->saddr, ipAttr->ipv4_src); } ipHdr->saddr = ipAttr->ipv4_src; } if (ipHdr->daddr != ipAttr->ipv4_dst) { if (tcpHdr) { tcpHdr->check = ChecksumUpdate32(tcpHdr->check, ipHdr->daddr, ipAttr->ipv4_dst); } else if (udpHdr && udpHdr->check) { udpHdr->check = ChecksumUpdate32(udpHdr->check, ipHdr->daddr, ipAttr->ipv4_dst); } if (ipHdr->check != 0) { ipHdr->check = ChecksumUpdate32(ipHdr->check, ipHdr->daddr, ipAttr->ipv4_dst); } ipHdr->daddr = ipAttr->ipv4_dst; } if (ipHdr->protocol != ipAttr->ipv4_proto) { UINT16 oldProto = (ipHdr->protocol << 16) & 0xff00; UINT16 newProto = (ipAttr->ipv4_proto << 16) & 0xff00; if (tcpHdr) { tcpHdr->check = ChecksumUpdate16(tcpHdr->check, oldProto, newProto); } else if (udpHdr && udpHdr->check) { udpHdr->check = ChecksumUpdate16(udpHdr->check, oldProto, newProto); } if (ipHdr->check != 0) { ipHdr->check = ChecksumUpdate16(ipHdr->check, oldProto, newProto); } ipHdr->protocol = ipAttr->ipv4_proto; } if (ipHdr->ttl != ipAttr->ipv4_ttl) { UINT16 oldTtl = (ipHdr->ttl) & 0xff; UINT16 newTtl = (ipAttr->ipv4_ttl) & 0xff; if (ipHdr->check != 0) { ipHdr->check = ChecksumUpdate16(ipHdr->check, oldTtl, newTtl); } ipHdr->ttl = ipAttr->ipv4_ttl; } return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsExecuteSetAction -- * Executes a set() action, but storing the actions into 'ovsFwdCtx' * -------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsExecuteSetAction(OvsForwardingContext *ovsFwdCtx, OvsFlowKey *key, UINT64 *hash, const PNL_ATTR a) { enum ovs_key_attr type = NlAttrType(a); NDIS_STATUS status = NDIS_STATUS_SUCCESS; switch (type) { case OVS_KEY_ATTR_ETHERNET: status = OvsUpdateEthHeader(ovsFwdCtx, NlAttrGetUnspec(a, sizeof(struct ovs_key_ethernet))); break; case OVS_KEY_ATTR_IPV4: status = OvsUpdateIPv4Header(ovsFwdCtx, NlAttrGetUnspec(a, sizeof(struct ovs_key_ipv4))); break; case OVS_KEY_ATTR_TUNNEL: { OvsIPv4TunnelKey tunKey; status = OvsTunnelAttrToIPv4TunnelKey((PNL_ATTR)a, &tunKey); ASSERT(status == NDIS_STATUS_SUCCESS); tunKey.flow_hash = (uint16)(hash ? *hash : OvsHashFlow(key)); tunKey.dst_port = key->ipKey.l4.tpDst; RtlCopyMemory(&ovsFwdCtx->tunKey, &tunKey, sizeof ovsFwdCtx->tunKey); break; } case OVS_KEY_ATTR_SKB_MARK: /* XXX: Not relevant to Hyper-V. Return OK */ break; case OVS_KEY_ATTR_UNSPEC: case OVS_KEY_ATTR_ENCAP: case OVS_KEY_ATTR_ETHERTYPE: case OVS_KEY_ATTR_IN_PORT: case OVS_KEY_ATTR_VLAN: case OVS_KEY_ATTR_ICMP: case OVS_KEY_ATTR_ICMPV6: case OVS_KEY_ATTR_ARP: case OVS_KEY_ATTR_ND: case __OVS_KEY_ATTR_MAX: default: OVS_LOG_INFO("Unhandled attribute %#x", type); ASSERT(FALSE); } return status; } /* * -------------------------------------------------------------------------- * OvsActionsExecute -- * Interpret and execute the specified 'actions' on the specifed packet * 'curNbl'. The expectation is that if the packet needs to be dropped * (completed) for some reason, it is added to 'completionList' so that the * caller can complete the packet. If 'completionList' is NULL, the NBL is * assumed to be generated by OVS and freed up. Otherwise, the function * consumes the NBL by generating a NDIS send indication for the packet. * * There are one or more of "clone" NBLs that may get generated while * executing the actions. Upon any failures, the "cloned" NBLs are freed up, * and the caller does not have to worry about them. * * Success or failure is returned based on whether the specified actions * were executed successfully on the packet or not. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext, OvsCompletionList *completionList, PNET_BUFFER_LIST curNbl, UINT32 portNo, ULONG sendFlags, OvsFlowKey *key, UINT64 *hash, OVS_PACKET_HDR_INFO *layers, const PNL_ATTR actions, INT actionsLen) { PNL_ATTR a; INT rem; UINT32 dstPortID; OvsForwardingContext ovsFwdCtx; PCWSTR dropReason = L""; NDIS_STATUS status; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); /* XXX: ASSERT that the flow table lock is held. */ status = OvsInitForwardingCtx(&ovsFwdCtx, switchContext, curNbl, portNo, sendFlags, fwdDetail, completionList, layers, TRUE); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"OVS-initing destination port list failed"; goto dropit; } if (actionsLen == 0) { dropReason = L"OVS-Dropped due to Flow action"; ovsActionStats.zeroActionLen++; goto dropit; } NL_ATTR_FOR_EACH_UNSAFE (a, rem, actions, actionsLen) { switch(NlAttrType(a)) { case OVS_ACTION_ATTR_OUTPUT: dstPortID = NlAttrGetU32(a); status = OvsAddPorts(&ovsFwdCtx, key, dstPortID, TRUE, TRUE); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"OVS-adding destination port failed"; goto dropit; } break; case OVS_ACTION_ATTR_PUSH_VLAN: { struct ovs_action_push_vlan *vlan; PVOID vlanTagValue; PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag; if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL || ovsFwdCtx.tunnelRxNic != NULL) { status = OvsOutputBeforeSetAction(&ovsFwdCtx); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"OVS-adding destination failed"; goto dropit; } } vlanTagValue = NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl, Ieee8021QNetBufferListInfo); if (vlanTagValue != NULL) { /* * XXX: We don't support double VLAN tag offload. In such cases, * we need to insert the existing one into the packet buffer, * and add the new one as offload. This will take care of * guest tag-in-tag case as well as OVS rules that specify * tag-in-tag. */ } else { vlanTagValue = 0; vlanTag = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue; vlan = (struct ovs_action_push_vlan *)NlAttrGet((const PNL_ATTR)a); vlanTag->TagHeader.VlanId = ntohs(vlan->vlan_tci) & 0xfff; vlanTag->TagHeader.UserPriority = ntohs(vlan->vlan_tci) >> 13; NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl, Ieee8021QNetBufferListInfo) = vlanTagValue; } break; } case OVS_ACTION_ATTR_POP_VLAN: { if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL || ovsFwdCtx.tunnelRxNic != NULL) { status = OvsOutputBeforeSetAction(&ovsFwdCtx); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"OVS-adding destination failed"; goto dropit; } } if (NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl, Ieee8021QNetBufferListInfo) != 0) { NET_BUFFER_LIST_INFO(ovsFwdCtx.curNbl, Ieee8021QNetBufferListInfo) = 0; } else { /* * The VLAN tag is inserted into the packet buffer. Pop the tag * by packet buffer modification. */ status = OvsPopVlanInPktBuf(&ovsFwdCtx); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"OVS-pop vlan action failed"; goto dropit; } } break; } case OVS_ACTION_ATTR_USERSPACE: { PNL_ATTR userdataAttr; PNL_ATTR queueAttr; POVS_PACKET_QUEUE_ELEM elem; BOOLEAN isRecv = FALSE; POVS_VPORT_ENTRY vport = OvsFindVportByPortNo(switchContext, portNo); if (vport) { if (vport->isExternal || OvsIsTunnelVportType(vport->ovsType)) { isRecv = TRUE; } } queueAttr = NlAttrFindNested(a, OVS_USERSPACE_ATTR_PID); userdataAttr = NlAttrFindNested(a, OVS_USERSPACE_ATTR_USERDATA); elem = OvsCreateQueueNlPacket((PVOID)userdataAttr, userdataAttr->nlaLen, OVS_PACKET_CMD_ACTION, vport, key, ovsFwdCtx.curNbl, NET_BUFFER_LIST_FIRST_NB(ovsFwdCtx.curNbl), isRecv, layers); if (elem) { LIST_ENTRY missedPackets; InitializeListHead(&missedPackets); InsertTailList(&missedPackets, &elem->link); OvsQueuePackets(&missedPackets, 1); dropReason = L"OVS-Completed since packet was copied to " L"userspace"; } else { dropReason = L"OVS-Dropped due to failure to queue to " L"userspace"; goto dropit; } break; } case OVS_ACTION_ATTR_SET: { if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL || ovsFwdCtx.tunnelRxNic != NULL) { status = OvsOutputBeforeSetAction(&ovsFwdCtx); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"OVS-adding destination failed"; goto dropit; } } status = OvsExecuteSetAction(&ovsFwdCtx, key, hash, (const PNL_ATTR)NlAttrGet ((const PNL_ATTR)a)); if (status != NDIS_STATUS_SUCCESS) { dropReason = L"OVS-set action failed"; goto dropit; } break; } case OVS_ACTION_ATTR_SAMPLE: default: status = NDIS_STATUS_NOT_SUPPORTED; break; } } if (ovsFwdCtx.destPortsSizeOut > 0 || ovsFwdCtx.tunnelTxNic != NULL || ovsFwdCtx.tunnelRxNic != NULL) { status = OvsOutputForwardingCtx(&ovsFwdCtx); ASSERT(ovsFwdCtx.curNbl == NULL); } ASSERT(ovsFwdCtx.destPortsSizeOut == 0); ASSERT(ovsFwdCtx.tunnelRxNic == NULL); ASSERT(ovsFwdCtx.tunnelTxNic == NULL); dropit: /* * If curNbl != NULL, it implies the NBL has not been not freed up so far. */ if (ovsFwdCtx.curNbl) { OvsCompleteNBLForwardingCtx(&ovsFwdCtx, dropReason); } return status; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/User.c0000644000000000000000000000013212664352753021536 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594660.221289997 openvswitch-2.5.0/datapath-windows/ovsext/User.c0000664000175000017500000011625212664352753023235 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * OvsUser.c * Manage packet queue for packet miss for userAction. */ #include "precomp.h" #include "Switch.h" #include "Vport.h" #include "Event.h" #include "User.h" #include "Datapath.h" #include "PacketIO.h" #include "Checksum.h" #include "NetProto.h" #include "Flow.h" #include "TunnelIntf.h" #include "Jhash.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_USER #include "Debug.h" POVS_PACKET_QUEUE_ELEM OvsGetNextPacket(POVS_OPEN_INSTANCE instance); extern PNDIS_SPIN_LOCK gOvsCtrlLock; extern POVS_SWITCH_CONTEXT gOvsSwitchContext; OVS_USER_STATS ovsUserStats; static VOID _MapNlAttrToOvsPktExec(PNL_ATTR *nlAttrs, PNL_ATTR *keyAttrs, OvsPacketExecute *execute); extern NL_POLICY nlFlowKeyPolicy[]; extern UINT32 nlFlowKeyPolicyLen; static __inline VOID OvsAcquirePidHashLock() { NdisAcquireSpinLock(&(gOvsSwitchContext->pidHashLock)); } static __inline VOID OvsReleasePidHashLock() { NdisReleaseSpinLock(&(gOvsSwitchContext->pidHashLock)); } static VOID OvsPurgePacketQueue(POVS_USER_PACKET_QUEUE queue, POVS_OPEN_INSTANCE instance) { PLIST_ENTRY link, next; LIST_ENTRY tmp; POVS_PACKET_QUEUE_ELEM elem; InitializeListHead(&tmp); NdisAcquireSpinLock(&queue->queueLock); if (queue->instance != instance) { NdisReleaseSpinLock(&queue->queueLock); return; } if (queue->numPackets) { OvsAppendList(&tmp, &queue->packetList); queue->numPackets = 0; } NdisReleaseSpinLock(&queue->queueLock); LIST_FORALL_SAFE(&tmp, link, next) { RemoveEntryList(link); elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link); OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG); } } VOID OvsCleanupPacketQueue(POVS_OPEN_INSTANCE instance) { POVS_USER_PACKET_QUEUE queue; POVS_PACKET_QUEUE_ELEM elem; PLIST_ENTRY link, next; LIST_ENTRY tmp; PIRP irp = NULL; ASSERT(instance); InitializeListHead(&tmp); queue = (POVS_USER_PACKET_QUEUE)instance->packetQueue; if (queue) { PDRIVER_CANCEL cancelRoutine; NdisAcquireSpinLock(&queue->queueLock); ASSERT(queue->instance == instance); /* XXX Should not happen */ if (queue->instance != instance) { NdisReleaseSpinLock(&queue->queueLock); NdisFreeSpinLock(&queue->queueLock); return; } if (queue->numPackets) { OvsAppendList(&tmp, &queue->packetList); queue->numPackets = 0; } queue->instance = NULL; instance->packetQueue = NULL; irp = queue->pendingIrp; queue->pendingIrp = NULL; if (irp) { cancelRoutine = IoSetCancelRoutine(irp, NULL); if (cancelRoutine == NULL) { irp = NULL; } } NdisReleaseSpinLock(&queue->queueLock); NdisFreeSpinLock(&queue->queueLock); } LIST_FORALL_SAFE(&tmp, link, next) { RemoveEntryList(link); elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link); OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG); } if (irp) { OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS); } if (queue) { OvsFreeMemoryWithTag(queue, OVS_USER_POOL_TAG); } /* Verify if gOvsSwitchContext exists. */ if (gOvsSwitchContext) { /* Remove the instance from pidHashArray */ OvsAcquirePidHashLock(); OvsDelPidInstance(gOvsSwitchContext, instance->pid); OvsReleasePidHashLock(); } } NTSTATUS OvsSubscribeDpIoctl(PVOID instanceP, UINT32 pid, UINT8 join) { POVS_USER_PACKET_QUEUE queue; POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)instanceP; if (instance->packetQueue && !join) { /* unsubscribe */ OvsCleanupPacketQueue(instance); } else if (instance->packetQueue == NULL && join) { queue = (POVS_USER_PACKET_QUEUE) OvsAllocateMemoryWithTag( sizeof *queue, OVS_USER_POOL_TAG); if (queue == NULL) { return STATUS_NO_MEMORY; } InitializeListHead(&(instance->pidLink)); instance->packetQueue = queue; RtlZeroMemory(queue, sizeof (*queue)); NdisAllocateSpinLock(&queue->queueLock); NdisAcquireSpinLock(&queue->queueLock); InitializeListHead(&queue->packetList); queue->pid = pid; queue->instance = instance; instance->packetQueue = queue; NdisReleaseSpinLock(&queue->queueLock); OvsAcquirePidHashLock(); /* Insert the instance to pidHashArray */ OvsAddPidInstance(gOvsSwitchContext, pid, instance); OvsReleasePidHashLock(); } else { /* user mode should call only once for subscribe */ return STATUS_INVALID_PARAMETER; } return STATUS_SUCCESS; } NTSTATUS OvsReadDpIoctl(PFILE_OBJECT fileObject, PVOID outputBuffer, UINT32 outputLength, UINT32 *replyLen) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; POVS_PACKET_QUEUE_ELEM elem; UINT32 len; #define TCP_CSUM_OFFSET 16 #define UDP_CSUM_OFFSET 6 ASSERT(instance); if (instance->packetQueue == NULL) { return STATUS_INVALID_PARAMETER; } if (outputLength < (sizeof (OVS_PACKET_INFO) + OVS_MIN_PACKET_SIZE)) { return STATUS_BUFFER_TOO_SMALL; } elem = OvsGetNextPacket(instance); if (elem) { /* * XXX revisit this later */ len = elem->packet.totalLen > outputLength ? outputLength : elem->packet.totalLen; if ((elem->hdrInfo.tcpCsumNeeded || elem->hdrInfo.udpCsumNeeded) && len == elem->packet.totalLen) { UINT16 sum, *ptr; UINT16 size = (UINT16)(elem->packet.payload - elem->packet.data + elem->hdrInfo.l4Offset); RtlCopyMemory(outputBuffer, &elem->packet.data, size); ASSERT(len - size >= elem->hdrInfo.l4PayLoad); sum = CopyAndCalculateChecksum((UINT8 *)outputBuffer + size, (UINT8 *)&elem->packet.data + size, elem->hdrInfo.l4PayLoad, 0); ptr =(UINT16 *)((UINT8 *)outputBuffer + size + (elem->hdrInfo.tcpCsumNeeded ? TCP_CSUM_OFFSET : UDP_CSUM_OFFSET)); *ptr = sum; ovsUserStats.l4Csum++; } else { RtlCopyMemory(outputBuffer, &elem->packet.data, len); } *replyLen = len; OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG); } return STATUS_SUCCESS; } /* Helper function to allocate a Forwarding Context for an NBL */ NTSTATUS OvsAllocateForwardingContextForNBL(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST nbl) { return switchContext->NdisSwitchHandlers. AllocateNetBufferListForwardingContext( switchContext->NdisSwitchContext, nbl); } /* *---------------------------------------------------------------------------- * OvsNlExecuteCmdHandler -- * Handler for OVS_PACKET_CMD_EXECUTE command. *---------------------------------------------------------------------------- */ NTSTATUS OvsNlExecuteCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS status = STATUS_SUCCESS; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg); POVS_HDR ovsHdr = &(msgIn->ovsHdr); PNL_ATTR nlAttrs[__OVS_PACKET_ATTR_MAX]; PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL}; UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN; UINT32 keyAttrOffset = 0; OvsPacketExecute execute; NL_ERROR nlError = NL_ERROR_SUCCESS; NL_BUFFER nlBuf; static const NL_POLICY nlPktExecPolicy[] = { [OVS_PACKET_ATTR_PACKET] = {.type = NL_A_UNSPEC, .optional = FALSE}, [OVS_PACKET_ATTR_KEY] = {.type = NL_A_UNSPEC, .optional = FALSE}, [OVS_PACKET_ATTR_ACTIONS] = {.type = NL_A_UNSPEC, .optional = FALSE}, [OVS_PACKET_ATTR_USERDATA] = {.type = NL_A_UNSPEC, .optional = TRUE}, [OVS_PACKET_ATTR_EGRESS_TUN_KEY] = {.type = NL_A_UNSPEC, .optional = TRUE} }; RtlZeroMemory(&execute, sizeof(OvsPacketExecute)); /* Get all the top level Flow attributes */ if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr), nlPktExecPolicy, ARRAY_SIZE(nlPktExecPolicy), nlAttrs, ARRAY_SIZE(nlAttrs))) != TRUE) { OVS_LOG_ERROR("Attr Parsing failed for msg: %p", nlMsgHdr); status = STATUS_UNSUCCESSFUL; goto done; } keyAttrOffset = (UINT32)((PCHAR)nlAttrs[OVS_PACKET_ATTR_KEY] - (PCHAR)nlMsgHdr); /* Get flow keys attributes */ if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(nlAttrs[OVS_PACKET_ATTR_KEY]), nlFlowKeyPolicy, nlFlowKeyPolicyLen, keyAttrs, ARRAY_SIZE(keyAttrs))) != TRUE) { OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p", nlMsgHdr); status = STATUS_UNSUCCESSFUL; goto done; } execute.dpNo = ovsHdr->dp_ifindex; _MapNlAttrToOvsPktExec(nlAttrs, keyAttrs, &execute); status = OvsExecuteDpIoctl(&execute); /* Default reply that we want to send */ if (status == STATUS_SUCCESS) { BOOLEAN ok; NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); /* Prepare nl Msg headers */ ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0, nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid, genlMsgHdr->cmd, OVS_PACKET_VERSION, ovsHdr->dp_ifindex); if (ok) { *replyLen = msgOut->nlMsg.nlmsgLen; } else { status = STATUS_INVALID_BUFFER_SIZE; } } else { /* Map NTSTATUS to NL_ERROR */ nlError = NlMapStatusToNlErr(status); /* As of now there are no transactional errors in the implementation. * Once we have them then we need to map status to correct * nlError value, so that below mentioned code gets hit. */ if ((nlError != NL_ERROR_SUCCESS) && (usrParamsCtx->outputBuffer)) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; status = STATUS_SUCCESS; goto done; } } done: return status; } /* *---------------------------------------------------------------------------- * _MapNlAttrToOvsPktExec -- * Maps input Netlink attributes to OvsPacketExecute. *---------------------------------------------------------------------------- */ static VOID _MapNlAttrToOvsPktExec(PNL_ATTR *nlAttrs, PNL_ATTR *keyAttrs, OvsPacketExecute *execute) { execute->packetBuf = NlAttrGet(nlAttrs[OVS_PACKET_ATTR_PACKET]); execute->packetLen = NlAttrGetSize(nlAttrs[OVS_PACKET_ATTR_PACKET]); execute->actions = NlAttrGet(nlAttrs[OVS_PACKET_ATTR_ACTIONS]); execute->actionsLen = NlAttrGetSize(nlAttrs[OVS_PACKET_ATTR_ACTIONS]); execute->inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]); } NTSTATUS OvsExecuteDpIoctl(OvsPacketExecute *execute) { NTSTATUS status = STATUS_SUCCESS; NTSTATUS ndisStatus; LOCK_STATE_EX lockState; PNET_BUFFER_LIST pNbl; PNL_ATTR actions; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; OvsFlowKey key; OVS_PACKET_HDR_INFO layers; POVS_VPORT_ENTRY vport; if (execute->packetLen == 0) { status = STATUS_INVALID_PARAMETER; goto exit; } actions = execute->actions; ASSERT(actions); /* * Allocate the NBL, copy the data from the userspace buffer. Allocate * also, the forwarding context for the packet. */ pNbl = OvsAllocateNBLFromBuffer(gOvsSwitchContext, execute->packetBuf, execute->packetLen); if (pNbl == NULL) { status = STATUS_NO_MEMORY; goto exit; } fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(pNbl); vport = OvsFindVportByPortNo(gOvsSwitchContext, execute->inPort); if (vport) { fwdDetail->SourcePortId = vport->portId; fwdDetail->SourceNicIndex = vport->nicIndex; } else { fwdDetail->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; fwdDetail->SourceNicIndex = 0; } // XXX: Figure out if any of the other members of fwdDetail need to be set. ndisStatus = OvsExtractFlow(pNbl, fwdDetail->SourcePortId, &key, &layers, NULL); if (ndisStatus == NDIS_STATUS_SUCCESS) { NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0); ndisStatus = OvsActionsExecute(gOvsSwitchContext, NULL, pNbl, vport ? vport->portNo : OVS_DPPORT_NUMBER_INVALID, NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP, &key, NULL, &layers, actions, execute->actionsLen); pNbl = NULL; NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); } if (ndisStatus != NDIS_STATUS_SUCCESS) { if (ndisStatus == NDIS_STATUS_NOT_SUPPORTED) { status = STATUS_NOT_SUPPORTED; } else { status = STATUS_UNSUCCESSFUL; } } if (pNbl) { OvsCompleteNBL(gOvsSwitchContext, pNbl, TRUE); } exit: return status; } NTSTATUS OvsPurgeDpIoctl(PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; POVS_USER_PACKET_QUEUE queue = (POVS_USER_PACKET_QUEUE)instance->packetQueue; if (queue == NULL) { return STATUS_INVALID_PARAMETER; } OvsPurgePacketQueue(queue, instance); return STATUS_SUCCESS; } VOID OvsCancelIrpDatapath(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; POVS_OPEN_INSTANCE instance; POVS_USER_PACKET_QUEUE queue = NULL; UNREFERENCED_PARAMETER(deviceObject); IoReleaseCancelSpinLock(irp->CancelIrql); irpSp = IoGetCurrentIrpStackLocation(irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { goto done; } NdisAcquireSpinLock(gOvsCtrlLock); instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; if (instance) { queue = instance->packetQueue; } if (instance == NULL || queue == NULL) { NdisReleaseSpinLock(gOvsCtrlLock); goto done; } NdisReleaseSpinLock(gOvsCtrlLock); NdisAcquireSpinLock(&queue->queueLock); if (queue->pendingIrp == irp) { queue->pendingIrp = NULL; } NdisReleaseSpinLock(&queue->queueLock); done: OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED); } NTSTATUS OvsWaitDpIoctl(PIRP irp, PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; POVS_USER_PACKET_QUEUE queue = (POVS_USER_PACKET_QUEUE)instance->packetQueue; NTSTATUS status = STATUS_SUCCESS; BOOLEAN cancelled = FALSE; if (queue == NULL) { return STATUS_INVALID_PARAMETER; } NdisAcquireSpinLock(&queue->queueLock); if (queue->instance != instance) { NdisReleaseSpinLock(&queue->queueLock); return STATUS_INVALID_PARAMETER; } if (queue->pendingIrp) { NdisReleaseSpinLock(&queue->queueLock); return STATUS_DEVICE_BUSY; } if (queue->numPackets == 0) { PDRIVER_CANCEL cancelRoutine; IoMarkIrpPending(irp); IoSetCancelRoutine(irp, OvsCancelIrpDatapath); if (irp->Cancel) { cancelRoutine = IoSetCancelRoutine(irp, NULL); if (cancelRoutine) { cancelled = TRUE; } } else { queue->pendingIrp = irp; } status = STATUS_PENDING; } NdisReleaseSpinLock(&queue->queueLock); if (cancelled) { OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED); OVS_LOG_INFO("Datapath IRP cancelled: %p", irp); } return status; } POVS_PACKET_QUEUE_ELEM OvsGetNextPacket(POVS_OPEN_INSTANCE instance) { POVS_USER_PACKET_QUEUE queue; PLIST_ENTRY link; queue = (POVS_USER_PACKET_QUEUE)instance->packetQueue; if (queue == NULL) { return NULL; } NdisAcquireSpinLock(&queue->queueLock); if (queue->instance != instance || queue->numPackets == 0) { NdisReleaseSpinLock(&queue->queueLock); return NULL; } link = RemoveHeadList(&queue->packetList); queue->numPackets--; NdisReleaseSpinLock(&queue->queueLock); return CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link); } /* * --------------------------------------------------------------------------- * Given a pid, returns the corresponding USER_PACKET_QUEUE. * --------------------------------------------------------------------------- */ POVS_USER_PACKET_QUEUE OvsGetQueue(UINT32 pid) { POVS_OPEN_INSTANCE instance; POVS_USER_PACKET_QUEUE ret = NULL; instance = OvsGetPidInstance(gOvsSwitchContext, pid); if (instance) { ret = instance->packetQueue; } return ret; } /* * --------------------------------------------------------------------------- * Given a pid, returns the corresponding instance. * pidHashLock must be acquired before calling this API. * --------------------------------------------------------------------------- */ POVS_OPEN_INSTANCE OvsGetPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid) { POVS_OPEN_INSTANCE instance; PLIST_ENTRY head, link; UINT32 hash = OvsJhashBytes((const VOID *)&pid, sizeof(pid), OVS_HASH_BASIS); head = &(switchContext->pidHashArray[hash & OVS_PID_MASK]); LIST_FORALL(head, link) { instance = CONTAINING_RECORD(link, OVS_OPEN_INSTANCE, pidLink); if (instance->pid == pid) { return instance; } } return NULL; } /* * --------------------------------------------------------------------------- * Given a pid and an instance. This API adds instance to pidHashArray. * pidHashLock must be acquired before calling this API. * --------------------------------------------------------------------------- */ VOID OvsAddPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid, POVS_OPEN_INSTANCE instance) { PLIST_ENTRY head; UINT32 hash = OvsJhashBytes((const VOID *)&pid, sizeof(pid), OVS_HASH_BASIS); head = &(switchContext->pidHashArray[hash & OVS_PID_MASK]); InsertHeadList(head, &(instance->pidLink)); } /* * --------------------------------------------------------------------------- * Given a pid and an instance. This API removes instance from pidHashArray. * pidHashLock must be acquired before calling this API. * --------------------------------------------------------------------------- */ VOID OvsDelPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid) { POVS_OPEN_INSTANCE instance = OvsGetPidInstance(switchContext, pid); if (instance) { RemoveEntryList(&(instance->pidLink)); } } VOID OvsQueuePackets(PLIST_ENTRY packetList, UINT32 numElems) { POVS_USER_PACKET_QUEUE upcallQueue = NULL; POVS_PACKET_QUEUE_ELEM elem; PLIST_ENTRY link; UINT32 num = 0; LIST_ENTRY dropPackets; OVS_LOG_LOUD("Enter: numELems: %u", numElems); InitializeListHead(&dropPackets); while (!IsListEmpty(packetList)) { link = RemoveHeadList(packetList); elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link); ASSERT(elem); OvsAcquirePidHashLock(); upcallQueue = OvsGetQueue(elem->upcallPid); if (!upcallQueue) { /* No upcall queue found, drop this packet. */ InsertTailList(&dropPackets, &elem->link); } else { NdisAcquireSpinLock(&upcallQueue->queueLock); if (upcallQueue->instance == NULL) { InsertTailList(&dropPackets, &elem->link); } else { InsertTailList(&upcallQueue->packetList, &elem->link); upcallQueue->numPackets++; if (upcallQueue->pendingIrp) { PIRP irp = upcallQueue->pendingIrp; PDRIVER_CANCEL cancelRoutine; upcallQueue->pendingIrp = NULL; cancelRoutine = IoSetCancelRoutine(irp, NULL); if (cancelRoutine != NULL) { OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS); } } } NdisReleaseSpinLock(&upcallQueue->queueLock); } OvsReleasePidHashLock(); } while (!IsListEmpty(&dropPackets)) { link = RemoveHeadList(&dropPackets); elem = CONTAINING_RECORD(link, OVS_PACKET_QUEUE_ELEM, link); OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG); num++; } OVS_LOG_LOUD("Exit: drop %u packets", num); } /* *---------------------------------------------------------------------------- * OvsCreateAndAddPackets -- * * Create a packet and forwarded to user space. * * This function would fragment packet if needed, and queue * each segment to user space. *---------------------------------------------------------------------------- */ NTSTATUS OvsCreateAndAddPackets(PVOID userData, UINT32 userDataLen, UINT32 cmd, POVS_VPORT_ENTRY vport, OvsFlowKey *key, PNET_BUFFER_LIST nbl, BOOLEAN isRecv, POVS_PACKET_HDR_INFO hdrInfo, POVS_SWITCH_CONTEXT switchContext, LIST_ENTRY *list, UINT32 *num) { POVS_PACKET_QUEUE_ELEM elem; PNET_BUFFER_LIST newNbl = NULL; PNET_BUFFER nb; if (hdrInfo->isTcp) { NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; UINT32 packetLength; tsoInfo.Value = NET_BUFFER_LIST_INFO(nbl, TcpLargeSendNetBufferListInfo); nb = NET_BUFFER_LIST_FIRST_NB(nbl); packetLength = NET_BUFFER_DATA_LENGTH(nb); OVS_LOG_TRACE("MSS %u packet len %u", tsoInfo.LsoV1Transmit.MSS, packetLength); if (tsoInfo.LsoV1Transmit.MSS) { OVS_LOG_TRACE("l4Offset %d", hdrInfo->l4Offset); newNbl = OvsTcpSegmentNBL(switchContext, nbl, hdrInfo, tsoInfo.LsoV1Transmit.MSS , 0); if (newNbl == NULL) { return NDIS_STATUS_FAILURE; } nbl = newNbl; } } nb = NET_BUFFER_LIST_FIRST_NB(nbl); while (nb) { elem = OvsCreateQueueNlPacket(userData, userDataLen, cmd, vport, key, nbl, nb, isRecv, hdrInfo); if (elem) { InsertTailList(list, &elem->link); (*num)++; } nb = NET_BUFFER_NEXT_NB(nb); } if (newNbl) { OvsCompleteNBL(switchContext, newNbl, TRUE); } return NDIS_STATUS_SUCCESS; } static __inline UINT32 OvsGetUpcallMsgSize(PVOID userData, UINT32 userDataLen, OvsIPv4TunnelKey *tunnelKey, UINT32 payload) { UINT32 size = NLMSG_ALIGN(sizeof(struct ovs_header)) + NlAttrSize(payload) + NlAttrSize(OvsFlowKeyAttrSize()); /* OVS_PACKET_ATTR_USERDATA */ if (userData) { size += NlAttrTotalSize(userDataLen); } /* OVS_PACKET_ATTR_EGRESS_TUN_KEY */ /* Is it included in the flow key attr XXX */ if (tunnelKey) { size += NlAttrTotalSize(OvsTunKeyAttrSize()); } return size; } /* *---------------------------------------------------------------------------- * This function completes the IP Header csum. record the L4 payload offset and * if there is a need to calculate the TCP or UDP csum. The actual csum will be * caluculated simopultaneossly with the copy of the payload to the destination * buffer when the packet is read. *---------------------------------------------------------------------------- */ static VOID OvsCompletePacketHeader(UINT8 *packet, BOOLEAN isRecv, NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo, POVS_PACKET_HDR_INFO hdrInfoIn, POVS_PACKET_HDR_INFO hdrInfoOut) { if ((isRecv && csumInfo.Receive.IpChecksumValueInvalid) || (!isRecv && csumInfo.Transmit.IsIPv4 && csumInfo.Transmit.IpHeaderChecksum)) { PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet + hdrInfoOut->l3Offset); ASSERT(hdrInfoIn->isIPv4); ASSERT(ipHdr->Version == 4); ipHdr->HeaderChecksum = IPChecksum((UINT8 *)ipHdr, ipHdr->HeaderLength << 2, (UINT16)~ipHdr->HeaderChecksum); ovsUserStats.ipCsum++; } ASSERT(hdrInfoIn->tcpCsumNeeded == 0 && hdrInfoOut->udpCsumNeeded == 0); /* * calculate TCP/UDP pseudo checksum */ if (isRecv && csumInfo.Receive.TcpChecksumValueInvalid) { /* * Only this case, we need to reclaculate pseudo checksum * all other cases, it is assumed the pseudo checksum is * filled already. * */ PTCP_HDR tcpHdr = (PTCP_HDR)(packet + hdrInfoIn->l4Offset); if (hdrInfoIn->isIPv4) { PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet + hdrInfoIn->l3Offset); hdrInfoOut->l4PayLoad = (UINT16)(ntohs(ipHdr->TotalLength) - (ipHdr->HeaderLength << 2)); tcpHdr->th_sum = IPPseudoChecksum((UINT32 *)&ipHdr->SourceAddress, (UINT32 *)&ipHdr->DestinationAddress, IPPROTO_TCP, hdrInfoOut->l4PayLoad); } else { PIPV6_HEADER ipv6Hdr = (PIPV6_HEADER)(packet + hdrInfoIn->l3Offset); hdrInfoOut->l4PayLoad = (UINT16)(ntohs(ipv6Hdr->PayloadLength) + hdrInfoIn->l3Offset + sizeof(IPV6_HEADER)- hdrInfoIn->l4Offset); ASSERT(hdrInfoIn->isIPv6); tcpHdr->th_sum = IPv6PseudoChecksum((UINT32 *)&ipv6Hdr->SourceAddress, (UINT32 *)&ipv6Hdr->DestinationAddress, IPPROTO_TCP, hdrInfoOut->l4PayLoad); } hdrInfoOut->tcpCsumNeeded = 1; ovsUserStats.recalTcpCsum++; } else if (!isRecv) { if (csumInfo.Transmit.TcpChecksum) { hdrInfoOut->tcpCsumNeeded = 1; } else if (csumInfo.Transmit.UdpChecksum) { hdrInfoOut->udpCsumNeeded = 1; } if (hdrInfoOut->tcpCsumNeeded || hdrInfoOut->udpCsumNeeded) { #ifdef DBG UINT16 sum, *ptr; UINT8 proto = hdrInfoOut->tcpCsumNeeded ? IPPROTO_TCP : IPPROTO_UDP; #endif if (hdrInfoIn->isIPv4) { PIPV4_HEADER ipHdr = (PIPV4_HEADER)(packet + hdrInfoIn->l3Offset); hdrInfoOut->l4PayLoad = (UINT16)(ntohs(ipHdr->TotalLength) - (ipHdr->HeaderLength << 2)); #ifdef DBG sum = IPPseudoChecksum((UINT32 *)&ipHdr->SourceAddress, (UINT32 *)&ipHdr->DestinationAddress, proto, hdrInfoOut->l4PayLoad); #endif } else { PIPV6_HEADER ipv6Hdr = (PIPV6_HEADER)(packet + hdrInfoIn->l3Offset); hdrInfoOut->l4PayLoad = (UINT16)(ntohs(ipv6Hdr->PayloadLength) + hdrInfoIn->l3Offset + sizeof(IPV6_HEADER)- hdrInfoIn->l4Offset); ASSERT(hdrInfoIn->isIPv6); #ifdef DBG sum = IPv6PseudoChecksum((UINT32 *)&ipv6Hdr->SourceAddress, (UINT32 *)&ipv6Hdr->DestinationAddress, proto, hdrInfoOut->l4PayLoad); #endif } #ifdef DBG ptr = (UINT16 *)(packet + hdrInfoIn->l4Offset + (hdrInfoOut->tcpCsumNeeded ? TCP_CSUM_OFFSET : UDP_CSUM_OFFSET)); ASSERT(*ptr == sum); #endif } } } static NTSTATUS OvsGetPid(POVS_VPORT_ENTRY vport, PNET_BUFFER nb, UINT32 *pid) { UNREFERENCED_PARAMETER(nb); ASSERT(vport); /* XXX select a pid from an array of pids using a flow based hash */ *pid = vport->upcallPid; return STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsCreateQueueNlPacket -- * * Create a packet which will be forwarded to user space. * * InputParameter: * userData: when cmd is user action, this field contain * user action data. * userDataLen: as name indicated * cmd: either miss or user action * inPort: datapath port id from which the packet is received. * key: flow Key with a tunnel key if available * nbl: the NET_BUFFER_LIST which contain the packet * nb: the packet * isRecv: This is used to decide how to interprete the csum info * hdrInfo: include hdr info initialized during flow extraction. * * Results: * NULL if fail to create the packet * The packet element otherwise *---------------------------------------------------------------------------- */ POVS_PACKET_QUEUE_ELEM OvsCreateQueueNlPacket(PVOID userData, UINT32 userDataLen, UINT32 cmd, POVS_VPORT_ENTRY vport, OvsFlowKey *key, PNET_BUFFER_LIST nbl, PNET_BUFFER nb, BOOLEAN isRecv, POVS_PACKET_HDR_INFO hdrInfo) { #define VLAN_TAG_SIZE 4 UINT32 allocLen, dataLen, extraLen; POVS_PACKET_QUEUE_ELEM elem; UINT8 *src, *dst; NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; NDIS_NET_BUFFER_LIST_8021Q_INFO vlanInfo; OvsIPv4TunnelKey *tunnelKey = (OvsIPv4TunnelKey *)&key->tunKey; UINT32 pid; UINT32 nlMsgSize; NL_BUFFER nlBuf; PNL_MSG_HDR nlMsg; if (vport == NULL){ /* No vport is not fatal. */ return NULL; } OvsGetPid(vport, nb, &pid); if (!pid) { /* * There is no userspace queue created yet, so there is no point for * creating a new packet to be queued. */ return NULL; } csumInfo.Value = NET_BUFFER_LIST_INFO(nbl, TcpIpChecksumNetBufferListInfo); if (isRecv && (csumInfo.Receive.TcpChecksumFailed || (csumInfo.Receive.UdpChecksumFailed && !hdrInfo->udpCsumZero) || csumInfo.Receive.IpChecksumFailed)) { OVS_LOG_INFO("Packet dropped due to checksum failure."); ovsUserStats.dropDuetoChecksum++; return NULL; } vlanInfo.Value = NET_BUFFER_LIST_INFO(nbl, Ieee8021QNetBufferListInfo); extraLen = vlanInfo.TagHeader.VlanId ? VLAN_TAG_SIZE : 0; dataLen = NET_BUFFER_DATA_LENGTH(nb); if (NlAttrSize(dataLen) > MAXUINT16) { return NULL; } nlMsgSize = OvsGetUpcallMsgSize(userData, userDataLen, tunnelKey, dataLen + extraLen); allocLen = sizeof (OVS_PACKET_QUEUE_ELEM) + nlMsgSize; elem = (POVS_PACKET_QUEUE_ELEM)OvsAllocateMemoryWithTag(allocLen, OVS_USER_POOL_TAG); if (elem == NULL) { ovsUserStats.dropDuetoResource++; return NULL; } elem->hdrInfo.value = hdrInfo->value; elem->upcallPid = pid; elem->packet.totalLen = nlMsgSize; /* XXX remove queueid */ elem->packet.queue = 0; /* XXX no need as the length is already in the NL attrib */ elem->packet.userDataLen = userDataLen; elem->packet.inPort = vport->portNo; elem->packet.cmd = cmd; if (cmd == (UINT32)OVS_PACKET_CMD_MISS) { ovsUserStats.miss++; } else if (cmd == (UINT32)OVS_PACKET_CMD_ACTION) { ovsUserStats.action++; } else { ASSERT(FALSE); goto fail; } /* XXX Should we have both packetLen and TotalLen*/ elem->packet.packetLen = dataLen + extraLen; NlBufInit(&nlBuf, (PCHAR)elem->packet.data, nlMsgSize); /* * Initialize the OVS header * Since we are pre allocating memory for the NL buffer * the attribute settings should not fail */ if (!NlFillOvsMsg(&nlBuf, OVS_WIN_NL_PACKET_FAMILY_ID, 0, 0, pid, (UINT8)cmd, OVS_PACKET_VERSION, gOvsSwitchContext->dpNo)) { goto fail; } if (MapFlowKeyToNlKey(&nlBuf, key, OVS_PACKET_ATTR_KEY, OVS_KEY_ATTR_TUNNEL) != STATUS_SUCCESS) { goto fail; } /* XXX must send OVS_PACKET_ATTR_EGRESS_TUN_KEY if set by vswtchd */ if (userData){ if (!NlMsgPutTailUnspec(&nlBuf, OVS_PACKET_ATTR_USERDATA, userData, (UINT16)userDataLen)) { goto fail; } } /* * Make space for the payload to be copied and set the attribute * XXX Uninit set initilizes the buffer with xero, we don't actually need * that the payload to be initailized */ dst = (UINT8 *)NlMsgPutTailUnspecUninit(&nlBuf, OVS_PACKET_ATTR_PACKET, (UINT16)(dataLen + extraLen)); if (!dst) { goto fail; } /* Store the payload for csum calculation when packet is read */ elem->packet.payload = dst; dst += extraLen; src = NdisGetDataBuffer(nb, dataLen, dst, 1, 0); if (src == NULL) { ovsUserStats.dropDuetoResource++; goto fail; } else if (src != dst) { /* Copy the data from the NDIS buffer to dst. */ RtlCopyMemory(dst, src, dataLen); } /* Set csum if was offloaded */ OvsCompletePacketHeader(dst, isRecv, csumInfo, hdrInfo, &elem->hdrInfo); /* * Finally insert VLAN tag */ if (extraLen) { dst = elem->packet.payload; src = dst + extraLen; ((UINT32 *)dst)[0] = ((UINT32 *)src)[0]; ((UINT32 *)dst)[1] = ((UINT32 *)src)[1]; ((UINT32 *)dst)[2] = ((UINT32 *)src)[2]; dst += 12; ((UINT16 *)dst)[0] = htons(0x8100); ((UINT16 *)dst)[1] = htons(vlanInfo.TagHeader.VlanId | (vlanInfo.TagHeader.UserPriority << 13)); elem->hdrInfo.l3Offset += VLAN_TAG_SIZE; elem->hdrInfo.l4Offset += VLAN_TAG_SIZE; ovsUserStats.vlanInsert++; } nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuf, 0, 0); nlMsg->nlmsgLen = NlBufSize(&nlBuf); /* 'totalLen' should be size of valid data. */ elem->packet.totalLen = nlMsg->nlmsgLen; return elem; fail: OvsFreeMemoryWithTag(elem, OVS_USER_POOL_TAG); return NULL; } /* * -------------------------------------------------------------------------- * Handler for the subscription for a packet queue * -------------------------------------------------------------------------- */ NTSTATUS OvsSubscribePacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NDIS_STATUS status; BOOLEAN rc; UINT8 join; UINT32 pid; const NL_POLICY policy[] = { [OVS_NL_ATTR_PACKET_PID] = {.type = NL_A_U32 }, [OVS_NL_ATTR_PACKET_SUBSCRIBE] = {.type = NL_A_U8 } }; PNL_ATTR attrs[ARRAY_SIZE(policy)]; UNREFERENCED_PARAMETER(replyLen); POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; rc = NlAttrParse(&msgIn->nlMsg, sizeof (*msgIn), NlMsgAttrsLen((PNL_MSG_HDR)msgIn), policy, ARRAY_SIZE(policy), attrs, ARRAY_SIZE(attrs)); if (!rc) { status = STATUS_INVALID_PARAMETER; goto done; } join = NlAttrGetU8(attrs[OVS_NL_ATTR_PACKET_SUBSCRIBE]); pid = NlAttrGetU32(attrs[OVS_NL_ATTR_PACKET_PID]); /* The socket subscribed with must be the same socket we perform receive*/ ASSERT(pid == instance->pid); status = OvsSubscribeDpIoctl(instance, pid, join); /* * XXX Need to add this instance to a global data structure * which hold all packet based instances. The data structure (hash) * should be searched through the pid field of the instance for * placing the missed packet into the correct queue */ done: return status; } /* * -------------------------------------------------------------------------- * Handler for queueing an IRP used for missed packet notification. The IRP is * completed when a packet received and mismatched. STATUS_PENDING is returned * on success. User mode keep a pending IRP at all times. * -------------------------------------------------------------------------- */ NTSTATUS OvsPendPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { UNREFERENCED_PARAMETER(replyLen); POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; /* * XXX access to packet queue must be through acquiring a lock as user mode * could unsubscribe and the instnace will be freed. */ return OvsWaitDpIoctl(usrParamsCtx->irp, instance->fileObject); } /* * -------------------------------------------------------------------------- * Handler for reading missed pacckets from the driver event queue. This * handler is executed when user modes issues a socket receive on a socket * -------------------------------------------------------------------------- */ NTSTATUS OvsReadPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { #ifdef DBG POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; #endif POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; NTSTATUS status; ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP); /* Should never read events with a dump socket */ ASSERT(instance->dumpState.ovsMsg == NULL); /* Must have an packet queue */ ASSERT(instance->packetQueue != NULL); /* Output buffer has been validated while validating read dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); /* Read a packet from the instance queue */ status = OvsReadDpIoctl(instance->fileObject, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength, replyLen); return status; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/precompsrc.c0000644000000000000000000000013112631676262022772 xustar0030 mtime=1449622706.990440031 30 atime=1456592667.323090897 29 ctime=1456594660.23729067 openvswitch-2.5.0/datapath-windows/ovsext/precompsrc.c0000664000175000017500000000115712631676262024467 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Jhash.h0000644000000000000000000000013212631676262021660 xustar0030 mtime=1449622706.954438766 30 atime=1456592667.311090405 30 ctime=1456594660.197288987 openvswitch-2.5.0/datapath-windows/ovsext/Jhash.h0000664000175000017500000000216012631676262023347 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2012, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __JHASH_H_ #define __JHASH_H_ 1 /* This is the public domain lookup3 hash by Bob Jenkins from * http://burtleburtle.net/bob/c/lookup3.c, modified for style. * * Use the functions in hash.h instead if you can. These are here just for * places where we've exposed a hash function "on the wire" and don't want it * to change. */ uint32_t OvsJhashWords(const uint32_t *, size_t n_word, uint32_t basis); uint32_t OvsJhashBytes(const void *, size_t n_bytes, uint32_t basis); #endif /* __JHASH_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/precomp.h0000644000000000000000000000013112631676262022267 xustar0030 mtime=1449622706.990440031 30 atime=1456592667.323090897 29 ctime=1456594660.23729067 openvswitch-2.5.0/datapath-windows/ovsext/precomp.h0000664000175000017500000000171412631676262023763 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include "Types.h" #include "..\include\OvsDpInterface.h" #include "Util.h" #include "Netlink/NetlinkError.h" #include "Netlink/Netlink.h" #include "Netlink/NetlinkProto.h" #include "..\include\OvsDpInterfaceExt.h" #include "DpInternal.h" openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/ovsext.inf0000644000000000000000000000013212631676262022500 xustar0030 mtime=1449622706.990440031 30 atime=1456592667.319090733 30 ctime=1456594660.233290502 openvswitch-2.5.0/datapath-windows/ovsext/ovsext.inf0000664000175000017500000000436412631676262024177 0ustar00jpettitjpettit00000000000000; ; Copyright (c) VMware. All Rights Reserved. ; [version] Signature = "$Windows NT$" Class = NetService ClassGUID = {4D36E974-E325-11CE-BFC1-08002BE10318} Provider = %OVS% CatalogFile = ovsext.cat DriverVer = 10/10/2013,1.0 [Manufacturer] %OVS%=OVS,NTx86,NTia64,NTamd64 [OVS.NTx86] %OVSExt_Desc%=Install, OVSExt [OVS.NTia64] %OVSExt_Desc%=Install, OVSExt [OVS.NTamd64] %OVSExt_Desc%=Install, OVSExt ;------------------------------------------------------------------------- ; Installation Section ;------------------------------------------------------------------------- [Install] AddReg=Inst_Ndi Characteristics=0x40000 NetCfgInstanceId="{583CC151-73EC-4A6A-8B47-578297AD7623}" Copyfiles = OVSExt.copyfiles.sys [SourceDisksNames] 1=%OVSExt_Desc%,"",, [SourceDisksFiles] OVSExt.sys=1 [DestinationDirs] DefaultDestDir=12 OVSExt.copyfiles.sys=12 [OVSExt.copyfiles.sys] OVSExt.sys,,,2 ;------------------------------------------------------------------------- ; Ndi installation support ;------------------------------------------------------------------------- [Inst_Ndi] HKR, Ndi,Service,,"OVSExt" HKR, Ndi,CoServices,0x00010000,"OVSExt" HKR, Ndi,HelpText,,%OVSExt_HelpText% HKR, Ndi,FilterClass,,"ms_switch_forward" HKR, Ndi,FilterType,0x00010001,0x00000002 HKR, Ndi\Interfaces,UpperRange,,"noupper" HKR, Ndi\Interfaces,LowerRange,,"nolower" HKR, Ndi\Interfaces, FilterMediaTypes,,"vmnetextension" HKR, Ndi,FilterRunType, 0x00010001, 2 ; optional ;------------------------------------------------------------------------- ; Service installation support, common.EventLog here is to demonstrate how to ; write an enent log ;------------------------------------------------------------------------- [Install.Services] AddService=OVSExt,,OVSExt_Service_Inst;, common.EventLog [OVSExt_Service_Inst] DisplayName = %OVSExt_Desc% ServiceType = 1 ;SERVICE_KERNEL_DRIVER StartType = 1 ;SERVICE_SYSTEM_START ErrorControl = 1 ;SERVICE_ERROR_NORMAL ServiceBinary = %12%\OVSExt.sys LoadOrderGroup = NDIS Description = %OVSExt_Desc% AddReg = Common.Params.reg [Install.Remove.Services] DelService=OVSExt,0x200 [Strings] OVS = "Open vSwitch" OVSExt_Desc = "Open vSwitch Extension" OVSExt_HelpText = "Open vSwitch forwarding switch extension" openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Util.h0000644000000000000000000000013212652645507021541 xustar0030 mtime=1454066503.414754588 30 atime=1456592667.323090897 30 ctime=1456594660.225290164 openvswitch-2.5.0/datapath-windows/ovsext/Util.h0000664000175000017500000000723512652645507023240 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __UTIL_H_ #define __UTIL_H_ 1 #define OVS_MEMORY_TAG 'TSVO' #define OVS_FIX_SIZE_NBL_POOL_TAG 'FSVO' #define OVS_VARIABLE_SIZE_NBL_POOL_TAG 'VSVO' #define OVS_NBL_ONLY_POOL_TAG 'OSVO' #define OVS_NET_BUFFER_POOL_TAG 'NSVO' #define OVS_OTHER_POOL_TAG 'MSVO' #define OVS_MDL_POOL_TAG 'BSVO' #define OVS_DATAPATH_POOL_TAG 'DSVO' #define OVS_EVENT_POOL_TAG 'ESVO' #define OVS_FLOW_POOL_TAG 'LSVO' #define OVS_VXLAN_POOL_TAG 'XSVO' #define OVS_IPHELPER_POOL_TAG 'HSVO' #define OVS_OID_POOL_TAG 'ASVO' #define OVS_SWITCH_POOL_TAG 'SSVO' #define OVS_USER_POOL_TAG 'USVO' #define OVS_VPORT_POOL_TAG 'PSVO' #define OVS_STT_POOL_TAG 'RSVO' #define OVS_GRE_POOL_TAG 'GSVO' #define OVS_TUNFLT_POOL_TAG 'WSVO' VOID *OvsAllocateMemory(size_t size); VOID *OvsAllocateMemoryWithTag(size_t size, ULONG tag); VOID *OvsAllocateAlignedMemory(size_t size, UINT16 align); VOID OvsFreeMemory(VOID *ptr); VOID OvsFreeMemoryWithTag(VOID *ptr, ULONG tag); VOID OvsFreeAlignedMemory(VOID *ptr); #define LIST_FORALL(_headPtr, _itemPtr) \ for (_itemPtr = (_headPtr)->Flink; \ _itemPtr != _headPtr; \ _itemPtr = (_itemPtr)->Flink) #define LIST_FORALL_SAFE(_headPtr, _itemPtr, _nextPtr) \ for (_itemPtr = (_headPtr)->Flink, _nextPtr = (_itemPtr)->Flink; \ _itemPtr != _headPtr; \ _itemPtr = _nextPtr, _nextPtr = (_itemPtr)->Flink) #define LIST_FORALL_REVERSE(_headPtr, _itemPtr) \ for (_itemPtr = (_headPtr)->Blink; \ _itemPtr != _headPtr; \ _itemPtr = (_itemPtr)->Blink) #define LIST_FORALL_REVERSE_SAFE(_headPtr, _itemPtr, _nextPtr) \ for (_itemPtr = (_headPtr)->Blink, _nextPtr = (_itemPtr)->Blink; \ _itemPtr != _headPtr; \ _itemPtr = _nextPtr, _nextPtr = (_itemPtr)->Blink) VOID OvsAppendList(PLIST_ENTRY dst, PLIST_ENTRY src); #define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a)) #define ARRAY_SIZE(_x) ((sizeof(_x))/sizeof (_x)[0]) #define OVS_SWITCH_PORT_ID_INVALID (NDIS_SWITCH_PORT_ID)(-1) #ifndef htons #define htons(_x) _byteswap_ushort((USHORT)(_x)) #define ntohs(_x) _byteswap_ushort((USHORT)(_x)) #define htonl(_x) _byteswap_ulong((ULONG)(_x)) #define ntohl(_x) _byteswap_ulong((ULONG)(_x)) #endif #define OVS_INIT_OBJECT_HEADER(_obj, _type, _revision, _size) \ { \ PNDIS_OBJECT_HEADER hdrp = _obj; \ hdrp->Type = _type; \ hdrp->Revision = _revision; \ hdrp->Size = _size; \ } #define BIT16(_x) ((UINT16)0x1 << (_x)) #define BIT32(_x) ((UINT32)0x1 << (_x)) BOOLEAN OvsCompareString(PVOID string1, PVOID string2); #endif /* __UTIL_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/PacketParser.c0000644000000000000000000000013212664352753023204 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.209289493 openvswitch-2.5.0/datapath-windows/ovsext/PacketParser.c0000664000175000017500000002334012664352753024676 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "PacketParser.h" //XXX consider moving to NdisGetDataBuffer. const VOID * OvsGetPacketBytes(const NET_BUFFER_LIST *nbl, UINT32 len, UINT32 srcOffset, VOID *storage) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNET_BUFFER netBuffer = NET_BUFFER_LIST_FIRST_NB(nbl); PMDL currentMdl; BOOLEAN firstMDL = TRUE; ULONG destOffset = 0; VOID *dest = storage; const UINT32 copyLen = len; ULONG packetLen; packetLen = NET_BUFFER_DATA_LENGTH(netBuffer); // Start copy from current MDL currentMdl = NET_BUFFER_CURRENT_MDL(netBuffer); // Data on current MDL may be offset from start of MDL while (destOffset < copyLen && currentMdl) { PUCHAR srcMemory = MmGetSystemAddressForMdlSafe(currentMdl, LowPagePriority); ULONG length = MmGetMdlByteCount(currentMdl); if (!srcMemory) { status = NDIS_STATUS_RESOURCES; break; } if (firstMDL) { ULONG mdlOffset = NET_BUFFER_CURRENT_MDL_OFFSET(netBuffer); srcMemory += mdlOffset; length -= mdlOffset; firstMDL = FALSE; } length = MIN(length, packetLen); packetLen -= length; ASSERT((INT)packetLen >= 0); if (srcOffset >= length) { currentMdl = NDIS_MDL_LINKAGE(currentMdl); srcOffset -= length; continue; } else { srcMemory += srcOffset; length -= srcOffset; srcOffset = 0; } length = min(length, copyLen-destOffset); NdisMoveMemory((PUCHAR)dest+destOffset, srcMemory, length); destOffset += length; currentMdl = NDIS_MDL_LINKAGE(currentMdl); } if (destOffset == copyLen) { ASSERT(status == NDIS_STATUS_SUCCESS); return storage; } return NULL; } NDIS_STATUS OvsParseIPv6(const NET_BUFFER_LIST *packet, OvsFlowKey *key, POVS_PACKET_HDR_INFO layers) { UINT16 ofs = layers->l3Offset; IPv6Hdr ipv6HdrStorage; const IPv6Hdr *nh; UINT32 nextHdr; Ipv6Key *flow= &key->ipv6Key; ofs = layers->l3Offset; nh = OvsGetPacketBytes(packet, sizeof *nh, ofs, &ipv6HdrStorage); if (!nh) { return NDIS_STATUS_FAILURE; } nextHdr = nh->nexthdr; memcpy(&flow->ipv6Src, nh->saddr.s6_addr, 16); memcpy(&flow->ipv6Dst, nh->daddr.s6_addr, 16); flow->nwTos = ((nh->flow_lbl[0] & 0xF0) >> 4) | (nh->priority << 4); flow->ipv6Label = ((nh->flow_lbl[0] & 0x0F) << 16) | (nh->flow_lbl[1] << 8) | nh->flow_lbl[2]; flow->nwTtl = nh->hop_limit; flow->nwProto = SOCKET_IPPROTO_NONE; flow->nwFrag = OVS_FRAG_TYPE_NONE; // Parse extended headers and compute L4 offset ofs += sizeof(IPv6Hdr); for (;;) { if ((nextHdr != SOCKET_IPPROTO_HOPOPTS) && (nextHdr != SOCKET_IPPROTO_ROUTING) && (nextHdr != SOCKET_IPPROTO_DSTOPTS) && (nextHdr != SOCKET_IPPROTO_AH) && (nextHdr != SOCKET_IPPROTO_FRAGMENT)) { /* * It's either a terminal header (e.g., TCP, UDP) or one we * don't understand. In either case, we're done with the * packet, so use it to fill in 'nw_proto'. */ break; } if (nextHdr == SOCKET_IPPROTO_HOPOPTS || nextHdr == SOCKET_IPPROTO_ROUTING || nextHdr == SOCKET_IPPROTO_DSTOPTS || nextHdr == SOCKET_IPPROTO_AH) { IPv6ExtHdr extHdrStorage; const IPv6ExtHdr *extHdr; UINT8 len; extHdr = OvsGetPacketBytes(packet, sizeof *extHdr, ofs, &extHdrStorage); if (!extHdr) { return NDIS_STATUS_FAILURE; } len = extHdr->hdrExtLen; ofs += nextHdr == SOCKET_IPPROTO_AH ? (len + 2) * 4 : (len + 1) * 8; nextHdr = extHdr->nextHeader; if (OvsPacketLenNBL(packet) < ofs) { return NDIS_STATUS_FAILURE; } } else if (nextHdr == SOCKET_IPPROTO_FRAGMENT) { IPv6FragHdr fragHdrStorage; const IPv6FragHdr *fragHdr; fragHdr = OvsGetPacketBytes(packet, sizeof *fragHdr, ofs, &fragHdrStorage); if (!fragHdr) { return NDIS_STATUS_FAILURE; } nextHdr = fragHdr->nextHeader; ofs += sizeof *fragHdr; /* We only process the first fragment. */ if (fragHdr->offlg != htons(0)) { if ((fragHdr->offlg & IP6F_OFF_HOST_ORDER_MASK) == htons(0)) { flow->nwFrag = OVS_FRAG_TYPE_FIRST; } else { flow->nwFrag = OVS_FRAG_TYPE_LATER; nextHdr = SOCKET_IPPROTO_FRAGMENT; break; } } } } flow->nwProto = (UINT8)nextHdr; layers->l4Offset = ofs; return NDIS_STATUS_SUCCESS; } VOID OvsParseTcp(const NET_BUFFER_LIST *packet, L4Key *flow, POVS_PACKET_HDR_INFO layers) { TCPHdr tcpStorage; const TCPHdr *tcp = OvsGetTcp(packet, layers->l4Offset, &tcpStorage); if (tcp) { flow->tpSrc = tcp->source; flow->tpDst = tcp->dest; layers->isTcp = 1; layers->l7Offset = layers->l4Offset + 4 * tcp->doff; } } VOID OvsParseSctp(const NET_BUFFER_LIST *packet, L4Key *flow, POVS_PACKET_HDR_INFO layers) { SCTPHdr sctpStorage; const SCTPHdr *sctp = OvsGetSctp(packet, layers->l4Offset, &sctpStorage); if (sctp) { flow->tpSrc = sctp->source; flow->tpDst = sctp->dest; layers->isSctp = 1; layers->l7Offset = layers->l4Offset + sizeof *sctp; } } VOID OvsParseUdp(const NET_BUFFER_LIST *packet, L4Key *flow, POVS_PACKET_HDR_INFO layers) { UDPHdr udpStorage; const UDPHdr *udp = OvsGetUdp(packet, layers->l4Offset, &udpStorage); if (udp) { flow->tpSrc = udp->source; flow->tpDst = udp->dest; layers->isUdp = 1; if (udp->check == 0) { layers->udpCsumZero = 1; } layers->l7Offset = layers->l4Offset + sizeof *udp; } } NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet, OvsFlowKey *key, POVS_PACKET_HDR_INFO layers) { UINT16 ofs = layers->l4Offset; ICMPHdr icmpStorage; const ICMPHdr *icmp; Icmp6Key *flow = &key->icmp6Key; memset(&flow->ndTarget, 0, sizeof(flow->ndTarget)); memset(flow->arpSha, 0, sizeof(flow->arpSha)); memset(flow->arpTha, 0, sizeof(flow->arpTha)); icmp = OvsGetIcmp(packet, ofs, &icmpStorage); if (!icmp) { return NDIS_STATUS_FAILURE; } ofs += sizeof *icmp; /* * The ICMPv6 type and code fields use the 16-bit transport port * fields, so we need to store them in 16-bit network byte order. */ key->ipv6Key.l4.tpSrc = htons(icmp->type); key->ipv6Key.l4.tpDst = htons(icmp->code); if (icmp->code == 0 && (icmp->type == ND_NEIGHBOR_SOLICIT || icmp->type == ND_NEIGHBOR_ADVERT)) { struct in6_addr ndTargetStorage; const struct in6_addr *ndTarget; ndTarget = OvsGetPacketBytes(packet, sizeof *ndTarget, ofs, &ndTargetStorage); if (!ndTarget) { return NDIS_STATUS_FAILURE; } flow->ndTarget = *ndTarget; while ((UINT32)(ofs + 8) <= OvsPacketLenNBL(packet)) { /* * The minimum size of an option is 8 bytes, which also is * the size of Ethernet link-layer options. */ IPv6NdOptHdr ndOptStorage; const IPv6NdOptHdr *ndOpt; UINT16 optLen; ndOpt = OvsGetPacketBytes(packet, sizeof *ndOpt, ofs, &ndOptStorage); if (!ndOpt) { return NDIS_STATUS_FAILURE; } optLen = ndOpt->len * 8; if (!optLen || (UINT32)(ofs + optLen) > OvsPacketLenNBL(packet)) { goto invalid; } /* * Store the link layer address if the appropriate option is * provided. It is considered an error if the same link * layer option is specified twice. */ if (ndOpt->type == ND_OPT_SOURCE_LINKADDR && optLen == 8) { if (Eth_IsNullAddr(flow->arpSha)) { memcpy(flow->arpSha, ndOpt + 1, ETH_ADDR_LENGTH); } else { goto invalid; } } else if (ndOpt->type == ND_OPT_TARGET_LINKADDR && optLen == 8) { if (Eth_IsNullAddr(flow->arpTha)) { memcpy(flow->arpTha, ndOpt + 1, ETH_ADDR_LENGTH); } else { goto invalid; } } ofs += optLen; } } layers->l7Offset = ofs; return NDIS_STATUS_SUCCESS; invalid: memset(&flow->ndTarget, 0, sizeof(flow->ndTarget)); memset(flow->arpSha, 0, sizeof(flow->arpSha)); memset(flow->arpTha, 0, sizeof(flow->arpTha)); return NDIS_STATUS_FAILURE; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Driver.c0000644000000000000000000000013112631676262022050 xustar0030 mtime=1449622706.938438204 29 atime=1456592667.30709024 30 ctime=1456594660.177288147 openvswitch-2.5.0/datapath-windows/ovsext/Driver.c0000664000175000017500000001455212631676262023550 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Switch.h" #include "User.h" #include "Datapath.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_DRIVER #include "Debug.h" /* Global handles. XXX: Some of them need not be global. */ /* * Maps to DriverObject and FilterDriverContext parameters in the NDIS filter * driver functions. * DriverObject is specified by NDIS. * FilterDriverContext is specified by the filter driver. */ NDIS_HANDLE gOvsExtDriverObject; /* * Maps to NdisFilterHandle parameter in the NDIS filter driver functions. * NdisFilterHandle is returned by NDISFRegisterFilterDriver. */ NDIS_HANDLE gOvsExtDriverHandle; /* * Maps to FilterModuleContext parameter in the NDIS filter driver functions. * FilterModuleContext is a allocated by the driver in the FilterAttach * function. */ extern POVS_SWITCH_CONTEXT gOvsSwitchContext; static PWCHAR ovsExtFriendlyName = L"Open vSwitch Extension"; static PWCHAR ovsExtServiceName = L"OVSExt"; NDIS_STRING ovsExtGuidUC; NDIS_STRING ovsExtFriendlyNameUC; static PWCHAR ovsExtGuidStr = L"{583CC151-73EC-4A6A-8B47-578297AD7623}"; static const GUID ovsExtGuid = { 0x583cc151, 0x73ec, 0x4a6a, {0x8b, 0x47, 0x57, 0x82, 0x97, 0xad, 0x76, 0x23} }; /* Declarations of callback functions for the filter driver. */ DRIVER_UNLOAD OvsExtUnload; FILTER_NET_PNP_EVENT OvsExtNetPnPEvent; FILTER_STATUS OvsExtStatus; FILTER_ATTACH OvsExtAttach; FILTER_DETACH OvsExtDetach; FILTER_RESTART OvsExtRestart; FILTER_PAUSE OvsExtPause; FILTER_SEND_NET_BUFFER_LISTS OvsExtSendNBL; FILTER_SEND_NET_BUFFER_LISTS_COMPLETE OvsExtSendNBLComplete; FILTER_CANCEL_SEND_NET_BUFFER_LISTS OvsExtCancelSendNBL; FILTER_RECEIVE_NET_BUFFER_LISTS OvsExtReceiveNBL; FILTER_RETURN_NET_BUFFER_LISTS OvsExtReturnNBL; FILTER_OID_REQUEST OvsExtOidRequest; FILTER_OID_REQUEST_COMPLETE OvsExtOidRequestComplete; FILTER_CANCEL_OID_REQUEST OvsExtCancelOidRequest; /* * -------------------------------------------------------------------------- * Init/Load function for the OVSEXT filter Driver. * -------------------------------------------------------------------------- */ NTSTATUS DriverEntry(PDRIVER_OBJECT driverObject, PUNICODE_STRING registryPath) { NDIS_STATUS status; NDIS_FILTER_DRIVER_CHARACTERISTICS driverChars; UNREFERENCED_PARAMETER(registryPath); /* Initialize driver associated data structures. */ OvsInit(); gOvsExtDriverObject = driverObject; RtlZeroMemory(&driverChars, sizeof driverChars); driverChars.Header.Type = NDIS_OBJECT_TYPE_FILTER_DRIVER_CHARACTERISTICS; driverChars.Header.Size = sizeof driverChars; driverChars.Header.Revision = NDIS_FILTER_CHARACTERISTICS_REVISION_2; driverChars.MajorNdisVersion = NDIS_FILTER_MAJOR_VERSION; driverChars.MinorNdisVersion = NDIS_FILTER_MINOR_VERSION; driverChars.MajorDriverVersion = 1; driverChars.MinorDriverVersion = 0; driverChars.Flags = 0; RtlInitUnicodeString(&driverChars.ServiceName, ovsExtServiceName); RtlInitUnicodeString(&ovsExtFriendlyNameUC, ovsExtFriendlyName); RtlInitUnicodeString(&ovsExtGuidUC, ovsExtGuidStr); driverChars.FriendlyName = ovsExtFriendlyNameUC; driverChars.UniqueName = ovsExtGuidUC; driverChars.AttachHandler = OvsExtAttach; driverChars.DetachHandler = OvsExtDetach; driverChars.RestartHandler = OvsExtRestart; driverChars.PauseHandler = OvsExtPause; driverChars.SendNetBufferListsHandler = OvsExtSendNBL; driverChars.SendNetBufferListsCompleteHandler = OvsExtSendNBLComplete; driverChars.CancelSendNetBufferListsHandler = OvsExtCancelSendNBL; driverChars.ReceiveNetBufferListsHandler = NULL; driverChars.ReturnNetBufferListsHandler = NULL; driverChars.OidRequestHandler = OvsExtOidRequest; driverChars.OidRequestCompleteHandler = OvsExtOidRequestComplete; driverChars.CancelOidRequestHandler = OvsExtCancelOidRequest; driverChars.DevicePnPEventNotifyHandler = NULL; driverChars.NetPnPEventHandler = OvsExtNetPnPEvent; driverChars.StatusHandler = NULL; driverObject->DriverUnload = OvsExtUnload; status = NdisFRegisterFilterDriver(driverObject, (NDIS_HANDLE)gOvsExtDriverObject, &driverChars, &gOvsExtDriverHandle); if (status != NDIS_STATUS_SUCCESS) { goto cleanup; } /* Create the communication channel for userspace. */ status = OvsCreateDeviceObject(gOvsExtDriverHandle); if (status != NDIS_STATUS_SUCCESS) { goto cleanup; } cleanup: if (status != NDIS_STATUS_SUCCESS){ OvsCleanup(); if (gOvsExtDriverHandle) { NdisFDeregisterFilterDriver(gOvsExtDriverHandle); gOvsExtDriverHandle = NULL; } } return status; } /* * -------------------------------------------------------------------------- * Un-init/Unload function for the OVS intermediate Driver. * -------------------------------------------------------------------------- */ VOID OvsExtUnload(struct _DRIVER_OBJECT *driverObject) { UNREFERENCED_PARAMETER(driverObject); /* Release driver associated data structures. */ OvsCleanup(); OvsDeleteDeviceObject(); NdisFDeregisterFilterDriver(gOvsExtDriverHandle); } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterStatus function. * -------------------------------------------------------------------------- */ VOID OvsExtStatus(NDIS_HANDLE filterModuleContext, PNDIS_STATUS_INDICATION statusIndication) { UNREFERENCED_PARAMETER(statusIndication); POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext; NdisFIndicateStatus(switchObject->NdisFilterHandle, statusIndication); return; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Types.h0000644000000000000000000000013112631676262021726 xustar0029 mtime=1449622706.98243975 30 atime=1456592667.315090569 30 ctime=1456594660.221289997 openvswitch-2.5.0/datapath-windows/ovsext/Types.h0000664000175000017500000000246412631676262023425 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __TYPES_H_ #define __TYPES_H_ 1 /* Defines the userspace specific data types * for files included from user space. */ typedef unsigned long long uint64, uint64_t, ovs_be64, u64; typedef long long int64, int64_t; typedef unsigned int uint32, uint32_t, ovs_be32, u32; typedef unsigned short uint16, uint16_t, ovs_be16, u16; typedef unsigned char uint8, uint8_t, u8; typedef uint64 __u64, __be64; typedef uint32 __u32, __be32; typedef uint16 __u16, __be16; typedef uint8 __u8; /* Defines the userspace specific data types for file * included within kernel only. */ typedef UINT8 BE8; typedef UINT16 BE16; typedef UINT32 BE32; typedef UINT64 BE64; #define ETH_ALEN 6 #define SIZE_MAX MAXUINT32 #endif /* __TYPES_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/TunnelFilter.c0000644000000000000000000000013112631676262023230 xustar0029 mtime=1449622706.98243975 30 atime=1456592667.315090569 30 ctime=1456594660.217289829 openvswitch-2.5.0/datapath-windows/ovsext/TunnelFilter.c0000664000175000017500000015270212631676262024730 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #pragma warning(push) #pragma warning(disable:4201) // unnamed struct/union #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_TUNFLT #include "Debug.h" #include #pragma warning(pop) #include #include #include #include #include "Tunnel.h" #include "Switch.h" #include "Vport.h" #include "Event.h" #include "User.h" #include "Vxlan.h" #define INITGUID #include /* Infinite timeout */ #define INFINITE 0xFFFFFFFF /* The provider name should always match the provider string from the install * file. */ #define OVS_TUNNEL_PROVIDER_NAME L"Open vSwitch" /* The provider description should always contain the OVS service description * string from the install file. */ #define OVS_TUNNEL_PROVIDER_DESC L"Open vSwitch Extension tunnel provider" /* The session name isn't required but it's useful for diagnostics. */ #define OVS_TUNNEL_SESSION_NAME L"OVS tunnel session" /* Maximum number of tunnel threads to be created. */ #define OVS_TUNFLT_MAX_THREADS 8 /* * Callout and sublayer GUIDs */ /* b16b0a6e-2b2a-41a3-8b39-bd3ffc855ff8 */ DEFINE_GUID( OVS_TUNNEL_CALLOUT_V4, 0xb16b0a6e, 0x2b2a, 0x41a3, 0x8b, 0x39, 0xbd, 0x3f, 0xfc, 0x85, 0x5f, 0xf8 ); /* 0104fd7e-c825-414e-94c9-f0d525bbc169 */ DEFINE_GUID( OVS_TUNNEL_SUBLAYER, 0x0104fd7e, 0xc825, 0x414e, 0x94, 0xc9, 0xf0, 0xd5, 0x25, 0xbb, 0xc1, 0x69 ); /* 6fc957d7-14e7-47c7-812b-4668be994ba1 */ DEFINE_GUID( OVS_TUNNEL_PROVIDER_KEY, 0x6fc957d7, 0x14e7, 0x47c7, 0x81, 0x2b, 0x46, 0x68, 0xbe, 0x99, 0x4b, 0xa1 ); /* bfd4814c-9650-4de3-a536-1eedb9e9ba6a */ DEFINE_GUID( OVS_TUNNEL_FILTER_KEY, 0xbfd4814c, 0x9650, 0x4de3, 0xa5, 0x36, 0x1e, 0xed, 0xb9, 0xe9, 0xba, 0x6a ); /* * Callout driver type definitions */ typedef enum _OVS_TUNFLT_OPERATION { OVS_TUN_FILTER_CREATE = 0, OVS_TUN_FILTER_DELETE } OVS_TUNFLT_OPERATION; typedef struct _OVS_TUNFLT_REQUEST { LIST_ENTRY entry; /* Tunnel filter destination port. */ UINT16 port; /* XXX: We also need to specify the tunnel L4 protocol, because there are * different protocols that can use the same destination port.*/ union { /* Tunnel filter identification used for filter deletion. */ UINT64 delID; /* Pointer used to return filter ID to the caller on filter creation. */ PUINT64 addID; } filterID; /* Requested operation to be performed. */ OVS_TUNFLT_OPERATION operation; /* Current I/O request to be completed when requested * operation is finished. */ PIRP irp; /* Callback function called before completing the IRP. */ PFNTunnelVportPendingOp callback; /* Context passed to the callback function. */ PVOID context; } OVS_TUNFLT_REQUEST, *POVS_TUNFLT_REQUEST; typedef struct _OVS_TUNFLT_REQUEST_LIST { /* SpinLock for syncronizing access to the requests list. */ NDIS_SPIN_LOCK spinlock; /* Head of the requests list. */ LIST_ENTRY head; /* Number of requests in the list. This variable is used by * InterlockedCompareExchange function and needs to be aligned * at 32-bit boundaries. */ UINT32 numEntries; } OVS_TUNFLT_REQUEST_LIST, *POVS_TUNFLT_REQUEST_LIST; typedef struct _OVS_TUNFLT_THREAD_CONTEXT { /* Thread identification. */ UINT threadID; /* Thread initialization flag. */ UINT32 isInitialized; /* Thread's engine session handle. */ HANDLE engineSession; /* Reference of the thread object. */ PVOID threadObject; /* Requests queue list. */ OVS_TUNFLT_REQUEST_LIST listRequests; /* Event signaling that there are requests to process. */ KEVENT requestEvent; /* Event for stopping thread execution. */ KEVENT stopEvent; } OVS_TUNFLT_THREAD_CONTEXT, *POVS_TUNFLT_THREAD_CONTEXT; KSTART_ROUTINE OvsTunnelFilterThreadProc; static NTSTATUS OvsTunnelFilterStartThreads(); static NTSTATUS OvsTunnelFilterThreadStart(POVS_TUNFLT_THREAD_CONTEXT threadCtx); static VOID OvsTunnelFilterStopThreads(); static VOID OvsTunnelFilterThreadStop(POVS_TUNFLT_THREAD_CONTEXT threadCtx, BOOLEAN signalEvent); static NTSTATUS OvsTunnelFilterThreadInit(POVS_TUNFLT_THREAD_CONTEXT threadCtx); static VOID OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT threadCtx); static VOID OvsTunnelFilterSetIrpContext(POVS_TUNFLT_REQUEST_LIST listRequests, POVS_TUNFLT_REQUEST request); static VOID OvsTunnelFilterCancelIrp(PDEVICE_OBJECT DeviceObject, PIRP Irp); /* * Callout driver global variables */ /* Pointer to the device object that must be create before we can register our * callout to the base filtering engine. */ static PDEVICE_OBJECT gDeviceObject = NULL; /* Handle to an open session to the filter engine that is used for adding * tunnel's callout. */ static HANDLE gEngineHandle = NULL; /* A pointer to the received handle that is associated with the registration of * the OvsTunnelProviderBfeCallback callback. */ static HANDLE gTunnelProviderBfeHandle = NULL; /* A pointer to the received handle that is associated with the registration of * the OvsTunnelInitBfeCallback callback. */ static HANDLE gTunnelInitBfeHandle = NULL; /* Runtime identifier for tunnel's callout which is retrieved at tunnel * initialization phase when the callout is registered. This ID is then used * for removing the callout object from the system at tunnel * uninitialization phase. */ static UINT32 gCalloutIdV4 = 0; /* Array used for storing tunnel thread's private data. */ static OVS_TUNFLT_THREAD_CONTEXT gTunnelThreadCtx[OVS_TUNFLT_MAX_THREADS] = { 0 }; /* * Callout driver implementation. */ NTSTATUS OvsTunnelEngineOpen(HANDLE *engineSession) { NTSTATUS status = STATUS_SUCCESS; FWPM_SESSION session = { 0 }; /* * Set an infinite wait timeout, so we don't have to handle FWP_E_TIMEOUT * errors while waiting to acquire the transaction lock. */ session.txnWaitTimeoutInMSec = INFINITE; /* The authentication service should always be RPC_C_AUTHN_DEFAULT. */ status = FwpmEngineOpen(NULL, RPC_C_AUTHN_DEFAULT, NULL, &session, engineSession); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to open filtering engine session, status: %x.", status); } return status; } VOID OvsTunnelEngineClose(HANDLE *engineSession) { if (*engineSession) { FwpmEngineClose(*engineSession); *engineSession = NULL; } } VOID OvsTunnelAddSystemProvider(HANDLE engineSession) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN inTransaction = FALSE; FWPM_PROVIDER provider = { 0 }; do { status = FwpmTransactionBegin(engineSession, 0); if (!NT_SUCCESS(status)) { break; } inTransaction = TRUE; memset(&provider, 0, sizeof(provider)); provider.providerKey = OVS_TUNNEL_PROVIDER_KEY; provider.displayData.name = OVS_TUNNEL_PROVIDER_NAME; provider.displayData.description = OVS_TUNNEL_PROVIDER_DESC; /* * Since we always want the provider to be present, it's easiest to add * it as persistent object during driver load. */ provider.flags = FWPM_PROVIDER_FLAG_PERSISTENT; status = FwpmProviderAdd(engineSession, &provider, NULL); if (!NT_SUCCESS(status)) { if (STATUS_FWP_ALREADY_EXISTS != status) { OVS_LOG_ERROR("Failed to add WFP provider, status: %x.", status); break; } } status = FwpmTransactionCommit(engineSession); if (!NT_SUCCESS(status)) { break; } inTransaction = FALSE; } while (inTransaction); if (inTransaction){ FwpmTransactionAbort(engineSession); } } VOID OvsTunnelRemoveSystemProvider(HANDLE engineSession) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN inTransaction = FALSE; do { status = FwpmTransactionBegin(engineSession, 0); if (!NT_SUCCESS(status)) { break; } inTransaction = TRUE; status = FwpmProviderDeleteByKey(engineSession, &OVS_TUNNEL_PROVIDER_KEY); if (!NT_SUCCESS(status)) { break; } status = FwpmTransactionCommit(engineSession); if (!NT_SUCCESS(status)) { break; } inTransaction = FALSE; } while (inTransaction); if (inTransaction){ FwpmTransactionAbort(engineSession); } } NTSTATUS OvsTunnelAddFilter(HANDLE engineSession, PWSTR filterName, const PWSTR filterDesc, USHORT remotePort, FWP_DIRECTION direction, UINT64 context, const GUID *filterKey, const GUID *layerKey, const GUID *calloutKey, UINT64 *filterID) { NTSTATUS status = STATUS_SUCCESS; FWPM_FILTER filter = {0}; FWPM_FILTER_CONDITION filterConditions[3] = {0}; UINT conditionIndex; if (filterKey) { filter.filterKey = *filterKey; } filter.layerKey = *layerKey; filter.displayData.name = (wchar_t*)filterName; filter.displayData.description = (wchar_t*)filterDesc; filter.action.type = FWP_ACTION_CALLOUT_TERMINATING; filter.action.calloutKey = *calloutKey; filter.filterCondition = filterConditions; filter.subLayerKey = OVS_TUNNEL_SUBLAYER; filter.weight.type = FWP_EMPTY; // auto-weight. filter.rawContext = context; conditionIndex = 0; filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_DIRECTION; filterConditions[conditionIndex].matchType = FWP_MATCH_EQUAL; filterConditions[conditionIndex].conditionValue.type = FWP_UINT32; filterConditions[conditionIndex].conditionValue.uint32 = direction; conditionIndex++; filterConditions[conditionIndex].fieldKey = FWPM_CONDITION_IP_LOCAL_PORT; filterConditions[conditionIndex].matchType = FWP_MATCH_EQUAL; filterConditions[conditionIndex].conditionValue.type = FWP_UINT16; filterConditions[conditionIndex].conditionValue.uint16 = remotePort; conditionIndex++; filter.numFilterConditions = conditionIndex; status = FwpmFilterAdd(engineSession, &filter, NULL, filterID); return status; } /* * -------------------------------------------------------------------------- * This function registers callouts for intercepting UDP traffic at WFP * FWPM_LAYER_DATAGRAM_DATA_V4 layer. * -------------------------------------------------------------------------- */ NTSTATUS OvsTunnelRegisterDatagramDataCallouts(const GUID *layerKey, const GUID *calloutKey, VOID *deviceObject, UINT32 *calloutId) { NTSTATUS status = STATUS_SUCCESS; FWPS_CALLOUT sCallout = {0}; FWPM_CALLOUT mCallout = {0}; FWPM_DISPLAY_DATA displayData = {0}; BOOLEAN calloutRegistered = FALSE; sCallout.calloutKey = *calloutKey; sCallout.classifyFn = OvsTunnelClassify; sCallout.notifyFn = OvsTunnelNotify; #if FLOW_CONTEXT /* Currently we don't associate a context with the flow */ sCallout.flowDeleteFn = OvsTunnelFlowDelete; sCallout.flags = FWP_CALLOUT_FLAG_CONDITIONAL_ON_FLOW; #endif status = FwpsCalloutRegister(deviceObject, &sCallout, calloutId); if (!NT_SUCCESS(status)) { goto Exit; } calloutRegistered = TRUE; displayData.name = L"Datagram-Data OVS Callout"; displayData.description = L"Proxies destination address/port for UDP"; mCallout.calloutKey = *calloutKey; mCallout.displayData = displayData; mCallout.applicableLayer = *layerKey; status = FwpmCalloutAdd(gEngineHandle, &mCallout, NULL, NULL); if (!NT_SUCCESS(status)) { if (STATUS_FWP_ALREADY_EXISTS != status) { OVS_LOG_ERROR("Failed to add WFP callout, status: %x.", status); goto Exit; } status = STATUS_SUCCESS; } Exit: if (!NT_SUCCESS(status)){ if (calloutRegistered) { FwpsCalloutUnregisterById(*calloutId); *calloutId = 0; } } return status; } /* * -------------------------------------------------------------------------- * This function registers non-dynamic callouts for intercepting UDP traffic. * Callouts will be removed during un-initializing phase. * -------------------------------------------------------------------------- */ NTSTATUS OvsTunnelRegisterCallouts(VOID *deviceObject) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN inTransaction = FALSE; FWPM_SUBLAYER OvsTunnelSubLayer; status = FwpmTransactionBegin(gEngineHandle, 0); if (!NT_SUCCESS(status)) { goto Exit; } inTransaction = TRUE; RtlZeroMemory(&OvsTunnelSubLayer, sizeof(FWPM_SUBLAYER)); OvsTunnelSubLayer.subLayerKey = OVS_TUNNEL_SUBLAYER; OvsTunnelSubLayer.displayData.name = L"Datagram-Data OVS Sub-Layer"; OvsTunnelSubLayer.displayData.description = L"Sub-Layer for use by Datagram-Data OVS callouts"; OvsTunnelSubLayer.flags = 0; OvsTunnelSubLayer.weight = FWP_EMPTY; /* auto-weight */ status = FwpmSubLayerAdd(gEngineHandle, &OvsTunnelSubLayer, NULL); if (!NT_SUCCESS(status)) { if (STATUS_FWP_ALREADY_EXISTS != status) { OVS_LOG_ERROR("Failed to add WFP sublayer, status: %x.", status); goto Exit; } } /* In order to use this callout a socket must be opened. */ status = OvsTunnelRegisterDatagramDataCallouts(&FWPM_LAYER_DATAGRAM_DATA_V4, &OVS_TUNNEL_CALLOUT_V4, deviceObject, &gCalloutIdV4); if (!NT_SUCCESS(status)) { goto Exit; } status = FwpmTransactionCommit(gEngineHandle); if (!NT_SUCCESS(status)){ goto Exit; } inTransaction = FALSE; Exit: if (!NT_SUCCESS(status)) { if (inTransaction) { FwpmTransactionAbort(gEngineHandle); } } return status; } VOID OvsTunnelUnregisterCallouts() { FwpsCalloutUnregisterById(gCalloutIdV4); FwpmSubLayerDeleteByKey(gEngineHandle, &OVS_TUNNEL_SUBLAYER); FwpmCalloutDeleteById(gEngineHandle, gCalloutIdV4); } VOID OvsTunnelFilterUninitialize(PDRIVER_OBJECT driverObject) { UNREFERENCED_PARAMETER(driverObject); OvsTunnelFilterStopThreads(); OvsTunnelUnregisterCallouts(); OvsTunnelEngineClose(&gEngineHandle); if (gDeviceObject) { IoDeleteDevice(gDeviceObject); } } NTSTATUS OvsTunnelFilterInitialize(PDRIVER_OBJECT driverObject) { NTSTATUS status = STATUS_SUCCESS; UNICODE_STRING deviceName; RtlInitUnicodeString(&deviceName, L"\\Device\\OvsTunnelFilter"); status = IoCreateDevice(driverObject, 0, &deviceName, FILE_DEVICE_NETWORK, 0, FALSE, &gDeviceObject); if (!NT_SUCCESS(status)){ OVS_LOG_ERROR("Failed to create tunnel filter device, status: %x.", status); goto Exit; } status = OvsTunnelFilterStartThreads(); if (!NT_SUCCESS(status)){ goto Exit; } status = OvsTunnelEngineOpen(&gEngineHandle); if (!NT_SUCCESS(status)){ goto Exit; } status = OvsTunnelRegisterCallouts(gDeviceObject); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to register callout, status: %x.", status); } Exit: if (!NT_SUCCESS(status)){ OvsTunnelFilterUninitialize(driverObject); } return status; } /* * -------------------------------------------------------------------------- * This function adds OVS system provider to the system if the BFE (Base * Filtering Engine) is running. * -------------------------------------------------------------------------- */ VOID NTAPI OvsTunnelProviderBfeCallback(PVOID context, FWPM_SERVICE_STATE bfeState) { HANDLE engineSession = NULL; DBG_UNREFERENCED_PARAMETER(context); if (FWPM_SERVICE_RUNNING == bfeState) { OvsTunnelEngineOpen(&engineSession); if (engineSession) { OvsTunnelAddSystemProvider(engineSession); } OvsTunnelEngineClose(&engineSession); } } /* * -------------------------------------------------------------------------- * This function registers the OvsTunnelProviderBfeCallback callback that is * called whenever there is a change to the state of base filtering engine. * -------------------------------------------------------------------------- */ NTSTATUS OvsSubscribeTunnelProviderBfeStateChanges(PVOID deviceObject) { NTSTATUS status = STATUS_SUCCESS; if (!gTunnelProviderBfeHandle) { status = FwpmBfeStateSubscribeChanges(deviceObject, OvsTunnelProviderBfeCallback, NULL, &gTunnelProviderBfeHandle); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR( "Failed to subscribe BFE tunnel provider callback, status: %x.", status); } } return status; } /* * -------------------------------------------------------------------------- * This function unregisters the OvsTunnelProviderBfeCallback callback that * was previously registered by OvsSubscribeTunnelProviderBfeStateChanges * function. * -------------------------------------------------------------------------- */ VOID OvsUnsubscribeTunnelProviderBfeStateChanges() { NTSTATUS status = STATUS_SUCCESS; if (gTunnelProviderBfeHandle) { status = FwpmBfeStateUnsubscribeChanges(gTunnelProviderBfeHandle); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR( "Failed to unsubscribe BFE tunnel provider callback, status: %x.", status); } gTunnelProviderBfeHandle = NULL; } } /* * -------------------------------------------------------------------------- * This function registers the OVS system provider if the BFE (Base Filtering * Engine) is running. * Otherwise, it will register the OvsTunnelProviderBfeCallback callback. * Note: Before calling FwpmBfeStateGet, the callout driver must call the * FwpmBfeStateSubscribeChanges function to register the callback function * to be called whenever the state of the filter engine changes. * * Register WFP system provider call hierarchy: * * * * * --> registers OvsTunnelProviderBfeCallback callback * * --> if BFE is running: * * --> if BFE is running: * * * --> unregisters OvsTunnelProviderBfeCallback callback * * -------------------------------------------------------------------------- */ VOID OvsRegisterSystemProvider(PVOID deviceObject) { NTSTATUS status = STATUS_SUCCESS; HANDLE engineSession = NULL; status = OvsSubscribeTunnelProviderBfeStateChanges(deviceObject); if (NT_SUCCESS(status)) { if (FWPM_SERVICE_RUNNING == FwpmBfeStateGet()) { OvsTunnelEngineOpen(&engineSession); if (engineSession) { OvsTunnelAddSystemProvider(engineSession); } OvsTunnelEngineClose(&engineSession); OvsUnsubscribeTunnelProviderBfeStateChanges(); } } } /* * -------------------------------------------------------------------------- * This function removes the OVS system provider and unregisters the * OvsTunnelProviderBfeCallback callback from BFE (Base Filtering Engine). * * Unregister WFP system provider call hierarchy: * * * * * * --> unregisters OvsTunnelProviderBfeCallback callback * * -------------------------------------------------------------------------- */ VOID OvsUnregisterSystemProvider() { HANDLE engineSession = NULL; OvsTunnelEngineOpen(&engineSession); if (engineSession) { OvsTunnelRemoveSystemProvider(engineSession); } OvsTunnelEngineClose(&engineSession); OvsUnsubscribeTunnelProviderBfeStateChanges(); } /* * -------------------------------------------------------------------------- * This function initializes the tunnel filter if the BFE is running. * -------------------------------------------------------------------------- */ VOID NTAPI OvsTunnelInitBfeCallback(PVOID context, FWPM_SERVICE_STATE bfeState) { NTSTATUS status = STATUS_SUCCESS; PDRIVER_OBJECT driverObject = (PDRIVER_OBJECT) context; if (FWPM_SERVICE_RUNNING == bfeState) { status = OvsTunnelFilterInitialize(driverObject); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR( "Failed to initialize tunnel filter, status: %x.", status); } } } /* * -------------------------------------------------------------------------- * This function registers the OvsTunnelInitBfeCallback callback that is * called whenever there is a change to the state of base filtering engine. * -------------------------------------------------------------------------- */ NTSTATUS OvsSubscribeTunnelInitBfeStateChanges(PDRIVER_OBJECT driverObject, PVOID deviceObject) { NTSTATUS status = STATUS_SUCCESS; if (!gTunnelInitBfeHandle) { status = FwpmBfeStateSubscribeChanges(deviceObject, OvsTunnelInitBfeCallback, driverObject, &gTunnelInitBfeHandle); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR( "Failed to subscribe BFE tunnel init callback, status: %x.", status); } } return status; } /* * -------------------------------------------------------------------------- * This function unregisters the OvsTunnelInitBfeCallback callback that * was previously registered by OvsSubscribeTunnelInitBfeStateChanges * function. * -------------------------------------------------------------------------- */ VOID OvsUnsubscribeTunnelInitBfeStateChanges() { NTSTATUS status = STATUS_SUCCESS; if (gTunnelInitBfeHandle) { status = FwpmBfeStateUnsubscribeChanges(gTunnelInitBfeHandle); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR( "Failed to unsubscribe BFE tunnel init callback, status: %x.", status); } gTunnelInitBfeHandle = NULL; } } /* * -------------------------------------------------------------------------- * This function initializes the OVS tunnel filter if the BFE (Base Filtering * Engine) is running. * Otherwise, it will register the OvsTunnelInitBfeCallback callback. * Note: Before calling FwpmBfeStateGet, the callout driver must call the * FwpmBfeStateSubscribeChanges function to register the callback function * to be called whenever the state of the filter engine changes. * * Initialize OVS tunnel filter call hierarchy: * * * * * --> registers OvsTunnelInitBfeCallback callback * * --> if BFE is running: * * * * * --> if BFE is running: * * * * * * --> unregisters OvsTunnelInitBfeCallback callback * * -------------------------------------------------------------------------- */ NTSTATUS OvsInitTunnelFilter(PDRIVER_OBJECT driverObject, PVOID deviceObject) { NTSTATUS status = STATUS_SUCCESS; if (deviceObject) { status = OvsSubscribeTunnelInitBfeStateChanges(driverObject, deviceObject); if (NT_SUCCESS(status)) { if (FWPM_SERVICE_RUNNING == FwpmBfeStateGet()) { status = OvsTunnelFilterInitialize(driverObject); if (!NT_SUCCESS(status)) { /* XXX: We need to decide what actions to take in case of * failure to initialize tunnel filter. */ ASSERT(status == NDIS_STATUS_SUCCESS); OVS_LOG_ERROR( "Failed to initialize tunnel filter, status: %x.", status); } OvsUnsubscribeTunnelInitBfeStateChanges(); } } } else { status = OvsTunnelFilterInitialize(driverObject); } return status; } /* * -------------------------------------------------------------------------- * This function uninitializes the OVS tunnel filter and unregisters the * OvsTunnelInitBfeCallback callback from BFE. * * Uninitialize OVS tunnel filter call hierarchy: * * * * * * * * * --> unregisters OvsTunnelInitBfeCallback callback * * -------------------------------------------------------------------------- */ VOID OvsUninitTunnelFilter(PDRIVER_OBJECT driverObject) { OvsTunnelFilterUninitialize(driverObject); OvsUnsubscribeTunnelInitBfeStateChanges(); } NTSTATUS OvsTunnelAddFilterEx(HANDLE engineSession, UINT32 filterPort, UINT64 *filterID) { NTSTATUS status = STATUS_SUCCESS; status = OvsTunnelAddFilter(engineSession, L"Datagram-Data OVS Filter (Inbound)", L"address/port for UDP", (USHORT)filterPort, FWP_DIRECTION_INBOUND, 0, NULL, &FWPM_LAYER_DATAGRAM_DATA_V4, &OVS_TUNNEL_CALLOUT_V4, filterID); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to add tunnel filter for port: %d, status: %x.", filterPort, status); } else { OVS_LOG_INFO("Filter added, filter port: %d, filter ID: %d.", filterPort, *filterID); } return status; } NTSTATUS OvsTunnelRemoveFilterEx(HANDLE engineSession, UINT64 filterID) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN error = TRUE; do { if (filterID == 0) { OVS_LOG_INFO("No tunnel filter to remove."); break; } status = FwpmFilterDeleteById(engineSession, filterID); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to remove tunnel with filter ID: %d,\ status: %x.", filterID, status); break; } OVS_LOG_INFO("Filter removed, filter ID: %d.", filterID); error = FALSE; } while (error); return status; } NTSTATUS OvsTunnelFilterExecuteAction(HANDLE engineSession, POVS_TUNFLT_REQUEST request) { NTSTATUS status = STATUS_SUCCESS; switch (request->operation) { case OVS_TUN_FILTER_CREATE: status = OvsTunnelAddFilterEx(engineSession, request->port, request->filterID.addID); break; case OVS_TUN_FILTER_DELETE: status = OvsTunnelRemoveFilterEx(engineSession, request->filterID.delID); break; default: status = STATUS_NOT_SUPPORTED; break; } return status; } /* * -------------------------------------------------------------------------- * This function pops the head request from the queue while holding the * queue lock. If the request has already been cancelled or is about to be * cancelled, the function retrieves the next valid request. * * Returns a pointer to the OVS_TUNFLT_REQUEST_LIST request object retrieved * from the queue. * -------------------------------------------------------------------------- */ POVS_TUNFLT_REQUEST OvsTunnelFilterRequestPop(POVS_TUNFLT_REQUEST_LIST listRequests) { POVS_TUNFLT_REQUEST request = NULL; PLIST_ENTRY link, next, head; NdisAcquireSpinLock(&listRequests->spinlock); if (!IsListEmpty(&listRequests->head)) { head = &listRequests->head; LIST_FORALL_SAFE(head, link, next) { PDRIVER_CANCEL oldCancelRoutine; request = CONTAINING_RECORD(link, OVS_TUNFLT_REQUEST, entry); if (request->irp) { oldCancelRoutine = IoSetCancelRoutine(request->irp, NULL); if (oldCancelRoutine == NULL) { /* * The Cancel routine for the current IRP is running. The * request is to be completed by the Cancel routine. Leave * this request alone and go to the next one. */ continue; } else { /* * The Cancel routine cannot run now and cannot already have * started to run. This request can be processed. */ } } RemoveEntryList(&request->entry); listRequests->numEntries--; break; } } NdisReleaseSpinLock(&listRequests->spinlock); return request; } /* * -------------------------------------------------------------------------- * This function pushes the received request to the queue, marks the IRP as * pending and sets its Cancel routine, while holding the queue lock. * * Returns STATUS_CANCELLED if the IRP has already been cancelled. Otherwise, * STATUS_SUCCESS is returned. * -------------------------------------------------------------------------- */ NTSTATUS OvsTunnelFilterRequestPush(POVS_TUNFLT_REQUEST_LIST listRequests, POVS_TUNFLT_REQUEST request) { NTSTATUS status = STATUS_SUCCESS; PIRP irp = request->irp; PDRIVER_CANCEL oldCancelRoutine; BOOLEAN cancelled = FALSE; NdisAcquireSpinLock(&listRequests->spinlock); if (irp) { /* * Mark the IRP pending to indicate that the request may complete on * a different thread. */ IoMarkIrpPending(irp); /* * Set the Cancel routine for the pending IRP, before checking the * Cancel flag. */ oldCancelRoutine = IoSetCancelRoutine(irp, OvsTunnelFilterCancelIrp); ASSERT(oldCancelRoutine == NULL); if (irp->Cancel) { /* * The IRP has already been cancelled. * Determine wheather the Cancel routine has started to run. */ oldCancelRoutine = IoSetCancelRoutine(irp, NULL); if (oldCancelRoutine) { /* * The I/O Manager has not called the Cancel routine and it * won't be called anymore, because we just set it to NULL. * Return STATUS_CANCELLED and complete the request after * releasing the lock. */ status = STATUS_CANCELLED; cancelled = TRUE; } else { /* * The Cancel routine has already started to run, but it is * blocked while it waits for the queue lock. Release the lock * and return STATUS_SUCCESS to avoid completing the request. * It will be completed in the Cancel routine. */ } } else { /* * The IRP has not been cancelled, so set its context used in the * Cancel routine. */ OvsTunnelFilterSetIrpContext(listRequests, request); } } if (!cancelled) { InsertTailList(&listRequests->head, &(request->entry)); listRequests->numEntries++; } NdisReleaseSpinLock(&listRequests->spinlock); return status; } /* * -------------------------------------------------------------------------- * This function pushes the received request to the corresponding thread * request queue. The arrival of the new request is signaled to the thread, * in order to start processing it. * * Note: * If the thread is not initialized, no operation is performed. * * For a uniform distribution of requests to thread queues, a thread index is * calculated based on the received destination port. * -------------------------------------------------------------------------- */ NTSTATUS OvsTunnelFilterThreadPush(POVS_TUNFLT_REQUEST request) { NTSTATUS status = STATUS_REQUEST_ABORTED; UINT32 count = OVS_TUNFLT_MAX_THREADS; UINT32 threadIndex; threadIndex = request->port % OVS_TUNFLT_MAX_THREADS; while (count--) { if (gTunnelThreadCtx[threadIndex].isInitialized) { status = OvsTunnelFilterRequestPush( &gTunnelThreadCtx[threadIndex].listRequests, request); if (NT_SUCCESS(status)) { KeSetEvent(&gTunnelThreadCtx[threadIndex].requestEvent, IO_NO_INCREMENT, FALSE); } break; } else { OVS_LOG_INFO("OVS tunnel filter thread %d not initialized.", threadIndex); } threadIndex = (threadIndex + 1) % OVS_TUNFLT_MAX_THREADS; } return status; } VOID OvsTunnelFilterCompleteRequest(PIRP irp, PFNTunnelVportPendingOp callback, PVOID context, NTSTATUS status) { UINT32 replyLen = 0; if (callback) { callback(context, status, &replyLen); /* Release the context passed to the callback function. */ OvsFreeMemory(context); } if (irp) { OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status); } } VOID OvsTunnelFilterRequestListProcess(POVS_TUNFLT_THREAD_CONTEXT threadCtx) { POVS_TUNFLT_REQUEST request = NULL; NTSTATUS status = STATUS_SUCCESS; BOOLEAN inTransaction = FALSE; do { if (!InterlockedCompareExchange( (LONG volatile *)&threadCtx->listRequests.numEntries, 0, 0)) { OVS_LOG_INFO("Nothing to do... request list is empty."); break; } status = FwpmTransactionBegin(threadCtx->engineSession, 0); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to start transaction, status: %x.", status); break; } inTransaction = TRUE; while (NULL != (request = OvsTunnelFilterRequestPop(&threadCtx->listRequests))) { status = OvsTunnelFilterExecuteAction(threadCtx->engineSession, request); /* Complete the IRP with the last operation status. */ OvsTunnelFilterCompleteRequest(request->irp, request->callback, request->context, status); OvsFreeMemory(request); request = NULL; } status = FwpmTransactionCommit(threadCtx->engineSession); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to commit transaction, status: %x.", status); break; } inTransaction = FALSE; } while (inTransaction); if (inTransaction) { FwpmTransactionAbort(threadCtx->engineSession); OVS_LOG_ERROR("Failed to execute request, status: %x.\ Transaction aborted.", status); } } /* *---------------------------------------------------------------------------- * System thread routine that processes thread's requests queue. The thread * routine initializes thread's necessary data and waits on two events, * requestEvent and stopEvent. Whenever a request is pushed to the thread's * queue, the requestEvent is signaled and the thread routine starts processing * the arrived requests. When stopEvent is signaled, all subsequent requests * are completed with STATUS_CANCELED, without being added to the thread's * queue, and the routine finishes processing all existing requests from the * queue before uninitializing the thread and exiting. *---------------------------------------------------------------------------- */ _Use_decl_annotations_ VOID OvsTunnelFilterThreadProc(PVOID context) { NTSTATUS status = STATUS_SUCCESS; POVS_TUNFLT_THREAD_CONTEXT threadCtx = (POVS_TUNFLT_THREAD_CONTEXT)context; PKEVENT eventArray[2] = { 0 }; ULONG count = 0; BOOLEAN exit = FALSE; BOOLEAN error = TRUE; OVS_LOG_INFO("Starting OVS Tunnel system thread %d.", threadCtx->threadID); eventArray[0] = &threadCtx->stopEvent; eventArray[1] = &threadCtx->requestEvent; count = ARRAY_SIZE(eventArray); do { status = OvsTunnelFilterThreadInit(threadCtx); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to initialize tunnel filter thread %d.", threadCtx->threadID); break; } do { status = KeWaitForMultipleObjects(count, (PVOID)eventArray, WaitAny, Executive, KernelMode, FALSE, NULL, NULL); switch (status) { case STATUS_WAIT_1: /* Start processing requests. */ OvsTunnelFilterRequestListProcess(threadCtx); break; default: /* Finish processing the remaining requests and exit. */ OvsTunnelFilterRequestListProcess(threadCtx); exit = TRUE; break; } } while (!exit); OvsTunnelFilterThreadUninit(threadCtx); error = FALSE; } while (error); OVS_LOG_INFO("Terminating OVS Tunnel system thread %d.", threadCtx->threadID); PsTerminateSystemThread(STATUS_SUCCESS); }; static NTSTATUS OvsTunnelFilterStartThreads() { NTSTATUS status = STATUS_SUCCESS; for (UINT index = 0; index < OVS_TUNFLT_MAX_THREADS; index++) { gTunnelThreadCtx[index].threadID = index; status = OvsTunnelFilterThreadStart(&gTunnelThreadCtx[index]); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to start tunnel filter thread %d.", index); break; } } return status; } static NTSTATUS OvsTunnelFilterThreadStart(POVS_TUNFLT_THREAD_CONTEXT threadCtx) { NTSTATUS status = STATUS_SUCCESS; HANDLE threadHandle = NULL; BOOLEAN error = TRUE; do { status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL, NULL, OvsTunnelFilterThreadProc, threadCtx); if (!NT_SUCCESS(status)) { OVS_LOG_ERROR("Failed to create tunnel thread, status: %x.", status); break; } ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, KernelMode, &threadCtx->threadObject, NULL); ZwClose(threadHandle); threadHandle = NULL; error = FALSE; } while (error); return status; } static VOID OvsTunnelFilterStopThreads() { /* Signal all threads to stop and ignore all subsequent requests. */ for (UINT index = 0; index < OVS_TUNFLT_MAX_THREADS; index++) { OvsTunnelFilterThreadStop(&gTunnelThreadCtx[index], TRUE); } /* Wait for all threads to finish processing the requests. */ for (UINT index = 0; index < OVS_TUNFLT_MAX_THREADS; index++) { OvsTunnelFilterThreadStop(&gTunnelThreadCtx[index], FALSE); } } static VOID OvsTunnelFilterThreadStop(POVS_TUNFLT_THREAD_CONTEXT threadCtx, BOOLEAN signalEvent) { if (threadCtx->isInitialized) { if (signalEvent) { /* Signal stop thread event. */ OVS_LOG_INFO("Received stop event for OVS Tunnel system thread %d.", threadCtx->threadID); KeSetEvent(&threadCtx->stopEvent, IO_NO_INCREMENT, FALSE); } else { /* Wait for the tunnel thread to finish. */ KeWaitForSingleObject(threadCtx->threadObject, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(threadCtx->threadObject); } } } /* * -------------------------------------------------------------------------- * This function initializes thread's necessary data. Each thread has its own * session object to the BFE that is used for processing the requests from * the thread's queue. * -------------------------------------------------------------------------- */ static NTSTATUS OvsTunnelFilterThreadInit(POVS_TUNFLT_THREAD_CONTEXT threadCtx) { NTSTATUS status = STATUS_SUCCESS; BOOLEAN error = TRUE; do { /* Create thread's engine session object. */ status = OvsTunnelEngineOpen(&threadCtx->engineSession); if (!NT_SUCCESS(status)) { break; } NdisAllocateSpinLock(&threadCtx->listRequests.spinlock); InitializeListHead(&threadCtx->listRequests.head); KeInitializeEvent(&threadCtx->stopEvent, NotificationEvent, FALSE); KeInitializeEvent(&threadCtx->requestEvent, SynchronizationEvent, FALSE); threadCtx->isInitialized = TRUE; error = FALSE; } while (error); return status; } /* * -------------------------------------------------------------------------- * This function uninitializes thread's private data. Thread's engine session * handle is closed and set to NULL. * -------------------------------------------------------------------------- */ static VOID OvsTunnelFilterThreadUninit(POVS_TUNFLT_THREAD_CONTEXT threadCtx) { if (threadCtx->engineSession) { /* Close thread's FWPM session. */ OvsTunnelEngineClose(&threadCtx->engineSession); NdisFreeSpinLock(&threadCtx->listRequests.spinlock); threadCtx->isInitialized = FALSE; } } /* * -------------------------------------------------------------------------- * This function creates a new tunnel filter request and push it to a thread * queue. If the thread stop event is signaled, the request is completed with * STATUS_REQUEST_ABORTED without pushing it to any queue. * -------------------------------------------------------------------------- */ NTSTATUS OvsTunnelFilterQueueRequest(PIRP irp, UINT16 remotePort, UINT64 *filterID, OVS_TUNFLT_OPERATION operation, PFNTunnelVportPendingOp callback, PVOID tunnelContext) { POVS_TUNFLT_REQUEST request = NULL; NTSTATUS status = STATUS_PENDING; NTSTATUS result = STATUS_SUCCESS; BOOLEAN error = TRUE; UINT64 timeout = 0; do { /* Verify if the stop event was signaled. */ if (STATUS_SUCCESS == KeWaitForSingleObject( &gTunnelThreadCtx[0].stopEvent, Executive, KernelMode, FALSE, (LARGE_INTEGER *)&timeout)) { /* The stop event is signaled. Completed the IRP with * STATUS_REQUEST_ABORTED. */ status = STATUS_REQUEST_ABORTED; break; } if (NULL == filterID) { OVS_LOG_ERROR("Invalid request."); status = STATUS_INVALID_PARAMETER; break; } request = (POVS_TUNFLT_REQUEST) OvsAllocateMemoryWithTag(sizeof(*request), OVS_TUNFLT_POOL_TAG); if (NULL == request) { OVS_LOG_ERROR("Failed to allocate list item."); status = STATUS_INSUFFICIENT_RESOURCES; break; } request->port = remotePort; request->operation = operation; switch (operation) { case OVS_TUN_FILTER_CREATE: request->filterID.addID = filterID; break; case OVS_TUN_FILTER_DELETE: request->filterID.delID = *filterID; break; } request->irp = irp; request->callback = callback; request->context = tunnelContext; result = OvsTunnelFilterThreadPush(request); if (!NT_SUCCESS(result)) { status = result; break; } error = FALSE; } while (error); if (error) { OvsTunnelFilterCompleteRequest(irp, callback, tunnelContext, status); if (request) { OvsFreeMemory(request); request = NULL; } } return status; } /* * -------------------------------------------------------------------------- * This function adds a new WFP filter for the received port and returns the * ID of the created WFP filter. * * Note: * All necessary calls to the WFP filtering engine must be running at IRQL = * PASSIVE_LEVEL. Because the function is called at IRQL = DISPATCH_LEVEL, * we register an OVS_TUN_FILTER_CREATE request that will be processed by * the tunnel filter thread routine at IRQL = PASSIVE_LEVEL. * * OVS VXLAN port add call hierarchy: * * * * * * --> if thread STOP event is signalled: * --> Complete request with STATUS_CANCELLED * --> EXIT * * --> add the request to one of tunnel thread queues * * -------------------------------------------------------------------------- */ NTSTATUS OvsTunnelFilterCreate(PIRP irp, UINT16 filterPort, UINT64 *filterID, PFNTunnelVportPendingOp callback, PVOID tunnelContext) { return OvsTunnelFilterQueueRequest(irp, filterPort, filterID, OVS_TUN_FILTER_CREATE, callback, tunnelContext); } /* * -------------------------------------------------------------------------- * This function removes a WFP filter using the received filter ID. * * Note: * All necessary calls to the WFP filtering engine must be running at IRQL = * PASSIVE_LEVEL. Because the function is called at IRQL = DISPATCH_LEVEL, * we register an OVS_TUN_FILTER_DELETE request that will be processed by * the tunnel filter thread routine at IRQL = PASSIVE_LEVEL. * * OVS VXLAN port delete call hierarchy: * * * * * * --> if thread STOP event is signalled: * --> Complete request with STATUS_CANCELLED * --> EXIT * * --> add the request to one of tunnel thread queues * * -------------------------------------------------------------------------- */ NTSTATUS OvsTunnelFilterDelete(PIRP irp, UINT64 filterID, PFNTunnelVportPendingOp callback, PVOID tunnelContext) { return OvsTunnelFilterQueueRequest(irp, 0, &filterID, OVS_TUN_FILTER_DELETE, callback, tunnelContext); } /* * -------------------------------------------------------------------------- * This function sets the context for the IRP. The context is used by the * Cancel routine, in order to identify the request object, corresponding to * the IRP, to be completed and to have access to the queue lock to remove * the request link from the queue. * -------------------------------------------------------------------------- */ VOID OvsTunnelFilterSetIrpContext(POVS_TUNFLT_REQUEST_LIST listRequests, POVS_TUNFLT_REQUEST request) { PIRP irp = request->irp; if (irp) { /* Set the IRP's DriverContext to be used for later. */ irp->Tail.Overlay.DriverContext[0] = (PVOID)request; irp->Tail.Overlay.DriverContext[1] = (PVOID)listRequests; } } /* * -------------------------------------------------------------------------- * This function is the Cancel routine to be called by the I/O Manager in the * case when the IRP is cancelled. * -------------------------------------------------------------------------- */ VOID OvsTunnelFilterCancelIrp(PDEVICE_OBJECT DeviceObject, PIRP irp) { POVS_TUNFLT_REQUEST request = (POVS_TUNFLT_REQUEST)irp->Tail.Overlay.DriverContext[0]; POVS_TUNFLT_REQUEST_LIST listRequests = (POVS_TUNFLT_REQUEST_LIST)irp->Tail.Overlay.DriverContext[1]; DBG_UNREFERENCED_PARAMETER(DeviceObject); /* Release the global cancel spinlock. */ IoReleaseCancelSpinLock(irp->CancelIrql); /* Clear the cancel routine from the IRP. */ IoSetCancelRoutine(irp, NULL); NdisAcquireSpinLock(&listRequests->spinlock); /* Remove the request from the corresponding tunnel filter thread queue. */ RemoveEntryList(&request->entry); listRequests->numEntries--; NdisReleaseSpinLock(&listRequests->spinlock); /* We are done with this IRP, so complete it with STATUS_CANCELLED. */ OvsTunnelFilterCompleteRequest(request->irp, request->callback, request->context, STATUS_CANCELLED); OvsFreeMemory(request); } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Vport.c0000644000000000000000000000013212652645507021731 xustar0030 mtime=1454066503.418754588 30 atime=1456592667.323090897 30 ctime=1456594660.225290164 openvswitch-2.5.0/datapath-windows/ovsext/Vport.c0000664000175000017500000026730412652645507023435 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Datapath.h" #include "Event.h" #include "Gre.h" #include "IpHelper.h" #include "Jhash.h" #include "Oid.h" #include "Stt.h" #include "Switch.h" #include "User.h" #include "Vport.h" #include "Vxlan.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_VPORT #include "Debug.h" #define VPORT_NIC_ENTER(_nic) \ OVS_LOG_TRACE("Enter: PortId: %x, NicIndex: %d", _nic->PortId, \ _nic->NicIndex) #define VPORT_NIC_EXIT(_nic) \ OVS_LOG_TRACE("Exit: PortId: %x, NicIndex: %d", _nic->PortId, \ _nic->NicIndex) #define VPORT_PORT_ENTER(_port) \ OVS_LOG_TRACE("Enter: PortId: %x", _port->PortId) #define VPORT_PORT_EXIT(_port) \ OVS_LOG_TRACE("Exit: PortId: %x", _port->PortId) #define OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC 100 /* Context structure used to pass back and forth information to the tunnel * filter threads. */ typedef struct _OVS_TUNFLT_INIT_CONTEXT { POVS_SWITCH_CONTEXT switchContext; UINT32 outputLength; PVOID outputBuffer; PVOID inputBuffer; POVS_VPORT_ENTRY vport; BOOLEAN hvSwitchPort; BOOLEAN hvDelete; BOOLEAN ovsDelete; } OVS_TUNFLT_INIT_CONTEXT, *POVS_TUNFLT_INIT_CONTEXT; extern POVS_SWITCH_CONTEXT gOvsSwitchContext; static VOID OvsInitVportWithPortParam(POVS_VPORT_ENTRY vport, PNDIS_SWITCH_PORT_PARAMETERS portParam); static VOID OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, PNDIS_SWITCH_NIC_PARAMETERS nicParam); static VOID OvsCopyPortParamsFromVport(POVS_VPORT_ENTRY vport, PNDIS_SWITCH_PORT_PARAMETERS portParam); static __inline VOID OvsWaitActivate(POVS_SWITCH_CONTEXT switchContext, ULONG sleepMicroSec); static NTSTATUS OvsGetExtInfoIoctl(POVS_VPORT_GET vportGet, POVS_VPORT_EXT_INFO extInfo); static NTSTATUS CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info, POVS_MESSAGE msgIn, PVOID outBuffer, UINT32 outBufLen, int dpIfIndex); static POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext, PWSTR wsName, SIZE_T wstrSize); static VOID UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, BOOLEAN newPort); static NTSTATUS OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx, POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, BOOLEAN hvDelete, BOOLEAN ovsDelete); static VOID OvsTunnelVportPendingInit(PVOID context, NTSTATUS status, UINT32 *replyLen); static VOID OvsTunnelVportPendingRemove(PVOID context, NTSTATUS status, UINT32 *replyLen); static NTSTATUS GetNICAlias(GUID *netCfgInstanceId, IF_COUNTED_STRING *portFriendlyName); /* * -------------------------------------------------------------------------- * Creates a Vport entry for a Hyper-V switch port. 'nicIndex' is typically * associated with a NIC than a port. We use it here for the special case * where we need to create a Vport for an external NIC with NicIndex > 0. * -------------------------------------------------------------------------- */ NDIS_STATUS HvCreatePort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParam, NDIS_SWITCH_NIC_INDEX nicIndex) { POVS_VPORT_ENTRY vport; LOCK_STATE_EX lockState; NDIS_STATUS status = NDIS_STATUS_SUCCESS; BOOLEAN newPort = FALSE; VPORT_PORT_ENTER(portParam); NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); /* Lookup by port ID. */ vport = OvsFindVportByPortIdAndNicIndex(switchContext, portParam->PortId, nicIndex); if (vport != NULL) { OVS_LOG_ERROR("Port add failed due to duplicate port name, " "port Id: %u", portParam->PortId); status = STATUS_DATA_NOT_ACCEPTED; goto create_port_done; } /* * Lookup by port name to see if this port with this name had been added * (and deleted) previously. */ vport = OvsFindVportByHvNameW(gOvsSwitchContext, portParam->PortFriendlyName.String, portParam->PortFriendlyName.Length); if (vport && vport->isAbsentOnHv == FALSE) { OVS_LOG_ERROR("Port add failed since a port already exists on " "the specified port Id: %u, ovsName: %s", portParam->PortId, vport->ovsName); status = STATUS_DATA_NOT_ACCEPTED; goto create_port_done; } if (vport != NULL) { ASSERT(vport->isAbsentOnHv); ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID); /* * It should be possible to simply just mark this port as "not deleted" * given that the port Id and the name are the same and also provided * that the other properties that we cache have not changed. */ if (vport->portType != portParam->PortType) { OVS_LOG_INFO("Port add failed due to PortType change, port Id: %u" " old: %u, new: %u", portParam->PortId, vport->portType, portParam->PortType); status = STATUS_DATA_NOT_ACCEPTED; goto create_port_done; } vport->isAbsentOnHv = FALSE; } else { vport = (POVS_VPORT_ENTRY)OvsAllocateVport(); if (vport == NULL) { status = NDIS_STATUS_RESOURCES; goto create_port_done; } newPort = TRUE; } OvsInitVportWithPortParam(vport, portParam); vport->nicIndex = nicIndex; UpdateSwitchCtxWithVport(switchContext, vport, newPort); create_port_done: NdisReleaseRWLock(switchContext->dispatchLock, &lockState); VPORT_PORT_EXIT(portParam); return status; } /* * -------------------------------------------------------------------------- * Function to process updates to a port on the Hyper-Vs witch. * -------------------------------------------------------------------------- */ NDIS_STATUS HvUpdatePort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParam) { POVS_VPORT_ENTRY vport; LOCK_STATE_EX lockState; OVS_VPORT_STATE ovsState; NDIS_SWITCH_NIC_STATE nicState; VPORT_PORT_ENTER(portParam); NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, portParam->PortId, 0); /* * Update properties only for NETDEV ports for supprting PS script */ if (vport == NULL) { goto update_port_done; } /* Store the nic and the OVS states as Nic Create won't be called */ ovsState = vport->ovsState; nicState = vport->nicState; /* * Currently only the port friendly name is being updated * Make sure that no other properties are changed */ ASSERT(portParam->PortId == vport->portId); ASSERT(portParam->PortState == vport->portState); ASSERT(portParam->PortType == vport->portType); /* * Call the set parameters function the handle all properties * change in a single place in case future version supports change of * other properties */ OvsInitVportWithPortParam(vport, portParam); /* Retore the nic and OVS states */ vport->nicState = nicState; vport->ovsState = ovsState; update_port_done: NdisReleaseRWLock(switchContext->dispatchLock, &lockState); VPORT_PORT_EXIT(portParam); /* Must always return success */ return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Function to process teardown of a port on the Hyper-V switch. * -------------------------------------------------------------------------- */ VOID HvTeardownPort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParam) { POVS_VPORT_ENTRY vport; LOCK_STATE_EX lockState; VPORT_PORT_ENTER(portParam); NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, portParam->PortId, 0); if (vport) { /* add assertion here */ vport->portState = NdisSwitchPortStateTeardown; vport->ovsState = OVS_STATE_PORT_TEAR_DOWN; } else { OVS_LOG_WARN("Vport not present."); } NdisReleaseRWLock(switchContext->dispatchLock, &lockState); VPORT_PORT_EXIT(portParam); } /* * -------------------------------------------------------------------------- * Function to process deletion of a port on the Hyper-V switch. * -------------------------------------------------------------------------- */ VOID HvDeletePort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParams) { POVS_VPORT_ENTRY vport; LOCK_STATE_EX lockState; VPORT_PORT_ENTER(portParams); NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, portParams->PortId, 0); /* * XXX: we can only destroy and remove the port if its datapath port * counterpart was deleted. If the datapath port counterpart is present, * we only mark the vport for deletion, so that a netlink command vport * delete will delete the vport. */ if (vport) { OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE); } else { OVS_LOG_WARN("Vport not present."); } NdisReleaseRWLock(switchContext->dispatchLock, &lockState); VPORT_PORT_EXIT(portParams); } /* * -------------------------------------------------------------------------- * Function to process addition of a NIC connection on the Hyper-V switch. * XXX: Posting an event to DPIF is incorrect here. However, it might be useful * to post an event to netdev-windows.c. * -------------------------------------------------------------------------- */ NDIS_STATUS HvCreateNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam) { POVS_VPORT_ENTRY vport; NDIS_STATUS status = NDIS_STATUS_SUCCESS; IF_COUNTED_STRING portFriendlyName = {0}; LOCK_STATE_EX lockState; VPORT_NIC_ENTER(nicParam); /* Wait for lists to be initialized. */ OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC); if (!switchContext->isActivated) { OVS_LOG_WARN("Switch is not activated yet."); /* Veto the creation of nic */ status = NDIS_STATUS_NOT_SUPPORTED; goto done; } if (OvsIsInternalNIC(nicParam->NicType) || OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) { GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName); } NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); /* * There can be one or more NICs for the external port. We create a vport * structure for each such NIC, and each NIC inherits a lot of properties * from the parent external port. */ if (OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) { NDIS_SWITCH_PORT_PARAMETERS portParam; POVS_VPORT_ENTRY virtExtVport = (POVS_VPORT_ENTRY)switchContext->virtualExternalVport; ASSERT(virtExtVport); ASSERT(OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId, nicParam->NicIndex) == NULL); OvsCopyPortParamsFromVport(virtExtVport, &portParam); NdisReleaseRWLock(switchContext->dispatchLock, &lockState); status = HvCreatePort(switchContext, &portParam, nicParam->NicIndex); NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); if (status != NDIS_STATUS_SUCCESS) { goto add_nic_done; } } vport = OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId, nicParam->NicIndex); if (vport == NULL) { OVS_LOG_ERROR("Create NIC without Switch Port," " PortId: %x, NicIndex: %d", nicParam->PortId, nicParam->NicIndex); status = NDIS_STATUS_INVALID_PARAMETER; goto add_nic_done; } OvsInitVportWithNicParam(switchContext, vport, nicParam); if (OvsIsInternalNIC(nicParam->NicType) || OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) { RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName, sizeof portFriendlyName); } add_nic_done: NdisReleaseRWLock(switchContext->dispatchLock, &lockState); done: VPORT_NIC_EXIT(nicParam); OVS_LOG_TRACE("Exit: status %8x.\n", status); return status; } /* * -------------------------------------------------------------------------- * Function to process connection event of a NIC on the Hyper-V switch. * -------------------------------------------------------------------------- */ VOID HvConnectNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam) { LOCK_STATE_EX lockState; POVS_VPORT_ENTRY vport; UINT32 portNo; VPORT_NIC_ENTER(nicParam); /* Wait for lists to be initialized. */ OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC); if (!switchContext->isActivated) { OVS_LOG_WARN("Switch is not activated yet."); goto done; } NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId, nicParam->NicIndex); if (!vport) { OVS_LOG_WARN("Vport not present."); NdisReleaseRWLock(switchContext->dispatchLock, &lockState); ASSERT(0); goto done; } vport->ovsState = OVS_STATE_CONNECTED; vport->nicState = NdisSwitchNicStateConnected; portNo = vport->portNo; NdisReleaseRWLock(switchContext->dispatchLock, &lockState); if (nicParam->NicType == NdisSwitchNicTypeInternal) { OvsInternalAdapterUp(&nicParam->NetCfgInstanceId); } done: VPORT_NIC_EXIT(nicParam); } /* * -------------------------------------------------------------------------- * Function to process updates to a NIC on the Hyper-V switch. * -------------------------------------------------------------------------- */ VOID HvUpdateNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam) { POVS_VPORT_ENTRY vport; LOCK_STATE_EX lockState; UINT32 event = 0; IF_COUNTED_STRING portFriendlyName = {0}; BOOLEAN nameChanged = FALSE; BOOLEAN aliasLookup = FALSE; VPORT_NIC_ENTER(nicParam); /* Wait for lists to be initialized. */ OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC); if (!switchContext->isActivated) { OVS_LOG_WARN("Switch is not activated yet."); goto update_nic_done; } /* GetNICAlias() must be called outside of a lock. */ if (nicParam->NicType == NdisSwitchNicTypeInternal || OvsIsRealExternalNIC(nicParam->NicType, nicParam->NicIndex)) { GetNICAlias(&nicParam->NetCfgInstanceId, &portFriendlyName); aliasLookup = TRUE; } NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId, nicParam->NicIndex); if (vport == NULL) { NdisReleaseRWLock(switchContext->dispatchLock, &lockState); OVS_LOG_WARN("Vport search failed."); goto update_nic_done; } switch (nicParam->NicType) { case NdisSwitchNicTypeExternal: case NdisSwitchNicTypeInternal: RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId, sizeof (GUID)); if (aliasLookup) { if (RtlCompareMemory(&vport->portFriendlyName, &portFriendlyName, vport->portFriendlyName.Length) != vport->portFriendlyName.Length) { RtlCopyMemory(&vport->portFriendlyName, &portFriendlyName, sizeof portFriendlyName); nameChanged = TRUE; } } break; case NdisSwitchNicTypeSynthetic: case NdisSwitchNicTypeEmulated: if (!RtlEqualMemory(vport->vmMacAddress, nicParam->VMMacAddress, sizeof (vport->vmMacAddress))) { event |= OVS_EVENT_MAC_CHANGE; RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress, sizeof (vport->vmMacAddress)); } break; default: ASSERT(0); } if (!RtlEqualMemory(vport->permMacAddress, nicParam->PermanentMacAddress, sizeof (vport->permMacAddress))) { RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress, sizeof (vport->permMacAddress)); event |= OVS_EVENT_MAC_CHANGE; } if (!RtlEqualMemory(vport->currMacAddress, nicParam->CurrentMacAddress, sizeof (vport->currMacAddress))) { RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress, sizeof (vport->currMacAddress)); event |= OVS_EVENT_MAC_CHANGE; } if (vport->mtu != nicParam->MTU) { vport->mtu = nicParam->MTU; event |= OVS_EVENT_MTU_CHANGE; } vport->numaNodeId = nicParam->NumaNodeId; if (nameChanged) { OVS_EVENT_ENTRY event; event.portNo = vport->portNo; event.ovsType = vport->ovsType; event.upcallPid = vport->upcallPid; RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName); event.type = OVS_EVENT_LINK_DOWN; OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE); OvsPostEvent(&event); } NdisReleaseRWLock(switchContext->dispatchLock, &lockState); /* * XXX: Not sure what kind of event to post here. DPIF is not interested in * changes to MAC address. Netdev-windows might be intrested, though. * That said, if the name chagnes, not clear what kind of event to be * posted. We might have to delete the vport, and have userspace recreate * it. */ update_nic_done: VPORT_NIC_EXIT(nicParam); } /* * -------------------------------------------------------------------------- * Function to process disconnect event of a NIC on the Hyper-V switch. * -------------------------------------------------------------------------- */ VOID HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam) { POVS_VPORT_ENTRY vport; LOCK_STATE_EX lockState; BOOLEAN isInternalPort = FALSE; OVS_EVENT_ENTRY event; VPORT_NIC_ENTER(nicParam); /* Wait for lists to be initialized. */ OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC); if (!switchContext->isActivated) { OVS_LOG_WARN("Switch is not activated yet."); goto done; } NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId, nicParam->NicIndex); if (!vport) { OVS_LOG_WARN("Vport not present."); NdisReleaseRWLock(switchContext->dispatchLock, &lockState); goto done; } vport->nicState = NdisSwitchNicStateDisconnected; vport->ovsState = OVS_STATE_NIC_CREATED; if (vport->ovsType == OVS_VPORT_TYPE_INTERNAL) { isInternalPort = TRUE; } event.portNo = vport->portNo; event.ovsType = vport->ovsType; event.upcallPid = vport->upcallPid; RtlCopyMemory(&event.ovsName, &vport->ovsName, sizeof event.ovsName); event.type = OVS_EVENT_LINK_DOWN; /* * Delete the port from the hash tables accessible to userspace. After this * point, userspace should not be able to access this port. */ if (OvsIsRealExternalVport(vport)) { OvsRemoveAndDeleteVport(NULL, switchContext, vport, FALSE, TRUE); OvsPostEvent(&event); } NdisReleaseRWLock(switchContext->dispatchLock, &lockState); if (isInternalPort) { OvsInternalAdapterDown(); } done: VPORT_NIC_EXIT(nicParam); } /* * -------------------------------------------------------------------------- * Function to process delete event of a NIC on the Hyper-V switch. * -------------------------------------------------------------------------- */ VOID HvDeleteNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam) { LOCK_STATE_EX lockState; POVS_VPORT_ENTRY vport; VPORT_NIC_ENTER(nicParam); /* Wait for lists to be initialized. */ OvsWaitActivate(switchContext, OVS_VPORT_DEFAULT_WAIT_TIME_MICROSEC); if (!switchContext->isActivated) { OVS_LOG_WARN("Switch is not activated yet."); goto done; } NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByPortIdAndNicIndex(switchContext, nicParam->PortId, nicParam->NicIndex); if (!vport) { OVS_LOG_WARN("Vport not present."); NdisReleaseRWLock(switchContext->dispatchLock, &lockState); goto done; } vport->nicState = NdisSwitchNicStateUnknown; vport->ovsState = OVS_STATE_PORT_CREATED; if (OvsIsRealExternalVport(vport)) { /* This vport was created in HvCreateNic(). */ OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, FALSE); } NdisReleaseRWLock(switchContext->dispatchLock, &lockState); done: VPORT_NIC_EXIT(nicParam); } /* * OVS Vport related functionality. */ POVS_VPORT_ENTRY OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext, UINT32 portNo) { POVS_VPORT_ENTRY vport; PLIST_ENTRY head, link; UINT32 hash = OvsJhashBytes((const VOID *)&portNo, sizeof(portNo), OVS_HASH_BASIS); head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]); LIST_FORALL(head, link) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink); if (vport->portNo == portNo) { return vport; } } return NULL; } POVS_VPORT_ENTRY OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext, UINT16 dstPort, OVS_VPORT_TYPE ovsPortType) { POVS_VPORT_ENTRY vport; PLIST_ENTRY head, link; UINT32 hash = OvsJhashBytes((const VOID *)&dstPort, sizeof(dstPort), OVS_HASH_BASIS); head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]); LIST_FORALL(head, link) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, tunnelVportLink); if (GetPortFromPriv(vport) == dstPort && vport->ovsType == ovsPortType) { return vport; } } return NULL; } POVS_VPORT_ENTRY OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext, OVS_VPORT_TYPE ovsPortType) { POVS_VPORT_ENTRY vport; PLIST_ENTRY head, link; UINT16 dstPort = 0; UINT32 hash = OvsJhashBytes((const VOID *)&dstPort, sizeof(dstPort), OVS_HASH_BASIS); head = &(switchContext->tunnelVportsArray[hash & OVS_VPORT_MASK]); LIST_FORALL(head, link) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, tunnelVportLink); if (vport->ovsType == ovsPortType) { return vport; } } return NULL; } POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext, PSTR name) { POVS_VPORT_ENTRY vport; PLIST_ENTRY head, link; UINT32 hash; SIZE_T length = strlen(name) + 1; hash = OvsJhashBytes((const VOID *)name, length, OVS_HASH_BASIS); head = &(switchContext->ovsPortNameHashArray[hash & OVS_VPORT_MASK]); LIST_FORALL(head, link) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, ovsNameLink); if (!strcmp(name, vport->ovsName)) { return vport; } } return NULL; } /* OvsFindVportByHvName: "name" is assumed to be null-terminated */ POVS_VPORT_ENTRY OvsFindVportByHvNameW(POVS_SWITCH_CONTEXT switchContext, PWSTR wsName, SIZE_T wstrSize) { POVS_VPORT_ENTRY vport = NULL; PLIST_ENTRY head, link; UINT i; for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) { head = &(switchContext->portIdHashArray[i]); LIST_FORALL(head, link) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink); /* * NOTE about portFriendlyName: * If the string is NULL-terminated, the Length member does not * include the terminating NULL character. */ if (vport->portFriendlyName.Length == wstrSize && RtlEqualMemory(wsName, vport->portFriendlyName.String, vport->portFriendlyName.Length)) { goto Cleanup; } vport = NULL; } } /* * Look in the list of ports that were added from the Hyper-V switch and * deleted. */ if (vport == NULL) { for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) { head = &(switchContext->portNoHashArray[i]); LIST_FORALL(head, link) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink); if (vport->portFriendlyName.Length == wstrSize && RtlEqualMemory(wsName, vport->portFriendlyName.String, vport->portFriendlyName.Length)) { goto Cleanup; } vport = NULL; } } } Cleanup: return vport; } POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext, PSTR name) { POVS_VPORT_ENTRY vport = NULL; /* 'portFriendlyName' is not NUL-terminated. */ SIZE_T length = strlen(name); SIZE_T wstrSize = length * sizeof(WCHAR); UINT i; PWSTR wsName = OvsAllocateMemoryWithTag(wstrSize, OVS_VPORT_POOL_TAG); if (!wsName) { return NULL; } for (i = 0; i < length; i++) { wsName[i] = name[i]; } vport = OvsFindVportByHvNameW(switchContext, wsName, wstrSize); OvsFreeMemoryWithTag(wsName, OVS_VPORT_POOL_TAG); return vport; } POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext, NDIS_SWITCH_PORT_ID portId, NDIS_SWITCH_NIC_INDEX index) { if (switchContext->virtualExternalVport && portId == switchContext->virtualExternalPortId && index == switchContext->virtualExternalVport->nicIndex) { return (POVS_VPORT_ENTRY)switchContext->virtualExternalVport; } else if (switchContext->internalVport && portId == switchContext->internalPortId && index == switchContext->internalVport->nicIndex) { return (POVS_VPORT_ENTRY)switchContext->internalVport; } else { PLIST_ENTRY head, link; POVS_VPORT_ENTRY vport; UINT32 hash; hash = OvsJhashWords((UINT32 *)&portId, 1, OVS_HASH_BASIS); head = &(switchContext->portIdHashArray[hash & OVS_VPORT_MASK]); LIST_FORALL(head, link) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink); if (portId == vport->portId && index == vport->nicIndex) { return vport; } } return NULL; } } POVS_VPORT_ENTRY OvsAllocateVport(VOID) { POVS_VPORT_ENTRY vport; vport = (POVS_VPORT_ENTRY)OvsAllocateMemoryWithTag( sizeof(OVS_VPORT_ENTRY), OVS_VPORT_POOL_TAG); if (vport == NULL) { return NULL; } RtlZeroMemory(vport, sizeof (OVS_VPORT_ENTRY)); vport->ovsState = OVS_STATE_UNKNOWN; vport->isAbsentOnHv = FALSE; vport->portNo = OVS_DPPORT_NUMBER_INVALID; InitializeListHead(&vport->ovsNameLink); InitializeListHead(&vport->portIdLink); InitializeListHead(&vport->portNoLink); return vport; } static VOID OvsInitVportWithPortParam(POVS_VPORT_ENTRY vport, PNDIS_SWITCH_PORT_PARAMETERS portParam) { vport->portType = portParam->PortType; vport->portState = portParam->PortState; vport->portId = portParam->PortId; vport->nicState = NdisSwitchNicStateUnknown; vport->isExternal = FALSE; vport->isBridgeInternal = FALSE; switch (vport->portType) { case NdisSwitchPortTypeExternal: vport->isExternal = TRUE; vport->ovsType = OVS_VPORT_TYPE_NETDEV; break; case NdisSwitchPortTypeInternal: vport->ovsType = OVS_VPORT_TYPE_INTERNAL; break; case NdisSwitchPortTypeSynthetic: case NdisSwitchPortTypeEmulated: vport->ovsType = OVS_VPORT_TYPE_NETDEV; break; } RtlCopyMemory(&vport->hvPortName, &portParam->PortName, sizeof (NDIS_SWITCH_PORT_NAME)); /* For external and internal ports, 'portFriendlyName' is overwritten * later. */ RtlCopyMemory(&vport->portFriendlyName, &portParam->PortFriendlyName, sizeof(NDIS_SWITCH_PORT_FRIENDLYNAME)); switch (vport->portState) { case NdisSwitchPortStateCreated: vport->ovsState = OVS_STATE_PORT_CREATED; break; case NdisSwitchPortStateTeardown: vport->ovsState = OVS_STATE_PORT_TEAR_DOWN; break; case NdisSwitchPortStateDeleted: vport->ovsState = OVS_STATE_PORT_DELETED; break; } } static VOID OvsInitVportWithNicParam(POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, PNDIS_SWITCH_NIC_PARAMETERS nicParam) { ASSERT(vport->portId == nicParam->PortId); ASSERT(vport->ovsState == OVS_STATE_PORT_CREATED); UNREFERENCED_PARAMETER(switchContext); RtlCopyMemory(vport->permMacAddress, nicParam->PermanentMacAddress, sizeof (nicParam->PermanentMacAddress)); RtlCopyMemory(vport->currMacAddress, nicParam->CurrentMacAddress, sizeof (nicParam->CurrentMacAddress)); if (nicParam->NicType == NdisSwitchNicTypeSynthetic || nicParam->NicType == NdisSwitchNicTypeEmulated) { RtlCopyMemory(vport->vmMacAddress, nicParam->VMMacAddress, sizeof (nicParam->VMMacAddress)); RtlCopyMemory(&vport->vmName, &nicParam->VmName, sizeof (nicParam->VmName)); } else { RtlCopyMemory(&vport->netCfgInstanceId, &nicParam->NetCfgInstanceId, sizeof (nicParam->NetCfgInstanceId)); } RtlCopyMemory(&vport->nicName, &nicParam->NicName, sizeof (nicParam->NicName)); vport->mtu = nicParam->MTU; vport->nicState = nicParam->NicState; vport->nicIndex = nicParam->NicIndex; vport->nicType = nicParam->NicType; vport->numaNodeId = nicParam->NumaNodeId; switch (vport->nicState) { case NdisSwitchNicStateCreated: vport->ovsState = OVS_STATE_NIC_CREATED; break; case NdisSwitchNicStateConnected: vport->ovsState = OVS_STATE_CONNECTED; break; case NdisSwitchNicStateDisconnected: vport->ovsState = OVS_STATE_NIC_CREATED; break; case NdisSwitchNicStateDeleted: vport->ovsState = OVS_STATE_PORT_CREATED; break; } } /* * -------------------------------------------------------------------------- * Populates 'portParam' based on 'vport'. * -------------------------------------------------------------------------- */ static VOID OvsCopyPortParamsFromVport(POVS_VPORT_ENTRY vport, PNDIS_SWITCH_PORT_PARAMETERS portParam) { portParam->Flags = 0; portParam->PortId = vport->portId; RtlCopyMemory(&portParam->PortName, &vport->hvPortName, sizeof (NDIS_SWITCH_PORT_NAME)); RtlCopyMemory(&portParam->PortFriendlyName, &vport->portFriendlyName, sizeof(NDIS_SWITCH_PORT_FRIENDLYNAME)); portParam->PortType = vport->portType; portParam->IsValidationPort = FALSE; portParam->PortState = vport->portState; } /* * -------------------------------------------------------------------------- * Initializes a tunnel vport. * -------------------------------------------------------------------------- */ NTSTATUS OvsInitTunnelVport(PVOID userContext, POVS_VPORT_ENTRY vport, OVS_VPORT_TYPE ovsType, UINT16 dstPort) { NTSTATUS status = STATUS_SUCCESS; POVS_USER_PARAMS_CONTEXT usrParamsCtx = (POVS_USER_PARAMS_CONTEXT)userContext; vport->isBridgeInternal = FALSE; vport->ovsType = ovsType; vport->ovsState = OVS_STATE_PORT_CREATED; switch (ovsType) { case OVS_VPORT_TYPE_GRE: status = OvsInitGreTunnel(vport); break; case OVS_VPORT_TYPE_VXLAN: { POVS_TUNFLT_INIT_CONTEXT tunnelContext = NULL; tunnelContext = OvsAllocateMemoryWithTag(sizeof(*tunnelContext), OVS_VPORT_POOL_TAG); if (tunnelContext == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; break; } tunnelContext->inputBuffer = usrParamsCtx->inputBuffer; tunnelContext->outputBuffer = usrParamsCtx->outputBuffer; tunnelContext->outputLength = usrParamsCtx->outputLength; tunnelContext->vport = vport; status = OvsInitVxlanTunnel(usrParamsCtx->irp, vport, dstPort, OvsTunnelVportPendingInit, (PVOID)tunnelContext); if (status != STATUS_PENDING) { OvsFreeMemoryWithTag(tunnelContext, OVS_VPORT_POOL_TAG); tunnelContext = NULL; } break; } case OVS_VPORT_TYPE_STT: status = OvsInitSttTunnel(vport, dstPort); break; default: ASSERT(0); } return status; } /* * -------------------------------------------------------------------------- * Initializes a bridge internal vport ie. a port of type * OVS_VPORT_TYPE_INTERNAL but not present on the Hyper-V switch. * -------------------------------------------------------------------------- */ NTSTATUS OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport) { vport->isBridgeInternal = TRUE; vport->ovsType = OVS_VPORT_TYPE_INTERNAL; /* Mark the status to be connected, since there is no other initialization * for this port. */ vport->ovsState = OVS_STATE_CONNECTED; return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * For external and internal vports 'portFriendlyName' parameter, provided by * Hyper-V, is overwritten with the interface alias name. * -------------------------------------------------------------------------- */ static NTSTATUS GetNICAlias(GUID *netCfgInstanceId, IF_COUNTED_STRING *portFriendlyName) { NTSTATUS status = STATUS_SUCCESS; WCHAR interfaceName[IF_MAX_STRING_SIZE] = { 0 }; NET_LUID interfaceLuid = { 0 }; size_t len = 0; status = ConvertInterfaceGuidToLuid(netCfgInstanceId, &interfaceLuid); if (status == STATUS_SUCCESS) { /* * Must be called from PASSIVE_LEVEL. Resulted in a * STATUS_INVALID_DEVICE_REQUEST if not. */ status = ConvertInterfaceLuidToAlias(&interfaceLuid, interfaceName, IF_MAX_STRING_SIZE + 1); if (status == STATUS_SUCCESS) { RtlStringCbPrintfW(portFriendlyName->String, IF_MAX_STRING_SIZE, L"%s", interfaceName); RtlStringCbLengthW(portFriendlyName->String, IF_MAX_STRING_SIZE, &len); portFriendlyName->Length = (USHORT)len; } else { OVS_LOG_ERROR("Fail to convert interface LUID to alias, status: %x", status); } } else { OVS_LOG_ERROR("Fail to convert interface GUID to LUID, status: %x", status); } return status; } /* * -------------------------------------------------------------------------- * Functionality common to any port on the Hyper-V switch. This function is not * to be called for a port that is not on the Hyper-V switch. * * Inserts the port into 'portIdHashArray' and caches the pointer in the * 'switchContext' if needed. * -------------------------------------------------------------------------- */ static VOID UpdateSwitchCtxWithVport(POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, BOOLEAN newPort) { UINT32 hash; switch (vport->portType) { case NdisSwitchPortTypeExternal: if (vport->nicIndex == 0) { switchContext->virtualExternalPortId = vport->portId; switchContext->virtualExternalVport = vport; } else { switchContext->numPhysicalNics++; } break; case NdisSwitchPortTypeInternal: ASSERT(vport->isBridgeInternal == FALSE); switchContext->internalPortId = vport->portId; switchContext->internalVport = vport; break; case NdisSwitchPortTypeSynthetic: case NdisSwitchPortTypeEmulated: break; } /* * It is important to not insert vport corresponding to virtual external * port into the 'portIdHashArray' since the port should not be exposed to * OVS userspace. */ if (vport->portType == NdisSwitchPortTypeExternal && vport->nicIndex == 0) { return; } /* * NOTE: OvsJhashWords has portId as "1" word. This should be ok, even * though sizeof(NDIS_SWITCH_PORT_ID) = 4, not 2, because the * hyper-v switch seems to use only 2 bytes out of 4. */ hash = OvsJhashWords(&vport->portId, 1, OVS_HASH_BASIS); InsertHeadList(&switchContext->portIdHashArray[hash & OVS_VPORT_MASK], &vport->portIdLink); if (newPort) { switchContext->numHvVports++; } return; } /* * -------------------------------------------------------------------------- * Functionality common to any port added from OVS userspace. * * Inserts the port into 'portNoHashArray', 'ovsPortNameHashArray' and in * 'tunnelVportsArray' if appropriate. * -------------------------------------------------------------------------- */ NDIS_STATUS InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport) { UINT32 hash; switch(vport->ovsType) { case OVS_VPORT_TYPE_GRE: case OVS_VPORT_TYPE_VXLAN: case OVS_VPORT_TYPE_STT: { UINT16 dstPort = GetPortFromPriv(vport); hash = OvsJhashBytes(&dstPort, sizeof(dstPort), OVS_HASH_BASIS); InsertHeadList( &gOvsSwitchContext->tunnelVportsArray[hash & OVS_VPORT_MASK], &vport->tunnelVportLink); switchContext->numNonHvVports++; break; } case OVS_VPORT_TYPE_INTERNAL: if (vport->isBridgeInternal) { switchContext->numNonHvVports++; } default: break; } /* * Insert the port into the hash array of ports: by port number and ovs * and ovs (datapath) port name. * NOTE: OvsJhashWords has portNo as "1" word. This is ok, because the * portNo is stored in 2 bytes only (max port number = MAXUINT16). */ hash = OvsJhashWords(&vport->portNo, 1, OVS_HASH_BASIS); InsertHeadList(&gOvsSwitchContext->portNoHashArray[hash & OVS_VPORT_MASK], &vport->portNoLink); hash = OvsJhashBytes(vport->ovsName, strlen(vport->ovsName) + 1, OVS_HASH_BASIS); InsertHeadList( &gOvsSwitchContext->ovsPortNameHashArray[hash & OVS_VPORT_MASK], &vport->ovsNameLink); return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Provides functionality that is partly complementatry to * InitOvsVportCommon()/UpdateSwitchCtxWithVport(). * * 'hvDelete' indicates if caller is removing the vport as a result of the * port being removed on the Hyper-V switch. * 'ovsDelete' indicates if caller is removing the vport as a result of the * port being removed from OVS userspace. * -------------------------------------------------------------------------- */ NTSTATUS OvsRemoveAndDeleteVport(PVOID usrParamsContext, POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, BOOLEAN hvDelete, BOOLEAN ovsDelete) { POVS_USER_PARAMS_CONTEXT usrParamsCtx = (POVS_USER_PARAMS_CONTEXT)usrParamsContext; BOOLEAN hvSwitchPort = FALSE; BOOLEAN deletedOnOvs = FALSE; BOOLEAN deletedOnHv = FALSE; switch (vport->ovsType) { case OVS_VPORT_TYPE_INTERNAL: if (!vport->isBridgeInternal) { if (hvDelete && vport->isAbsentOnHv == FALSE) { switchContext->internalPortId = 0; switchContext->internalVport = NULL; OvsInternalAdapterDown(); } hvSwitchPort = TRUE; } break; case OVS_VPORT_TYPE_VXLAN: { NTSTATUS status; status = OvsRemoveTunnelVport(usrParamsCtx, switchContext, vport, hvDelete, ovsDelete); if (status != STATUS_SUCCESS) { return status; } } case OVS_VPORT_TYPE_STT: OvsCleanupSttTunnel(vport); break; case OVS_VPORT_TYPE_GRE: OvsCleanupGreTunnel(vport); break; case OVS_VPORT_TYPE_NETDEV: if (vport->isExternal) { if (vport->nicIndex == 0) { /* Such a vport is not part of any of the hash tables, since it * is not exposed to userspace. See Vport.h for explanation. */ ASSERT(hvDelete == TRUE); ASSERT(switchContext->numPhysicalNics == 0); switchContext->virtualExternalPortId = 0; switchContext->virtualExternalVport = NULL; OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG); return STATUS_SUCCESS; } } hvSwitchPort = TRUE; default: break; } /* * 'hvDelete' == TRUE indicates that the port should be removed from the * 'portIdHashArray', while 'ovsDelete' == TRUE indicates that the port * should be removed from 'portNoHashArray' and the 'ovsPortNameHashArray'. * * Both 'hvDelete' and 'ovsDelete' can be set to TRUE by the caller. */ if (vport->isAbsentOnHv == TRUE) { deletedOnHv = TRUE; } if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) { deletedOnOvs = TRUE; } if (hvDelete && !deletedOnHv) { vport->isAbsentOnHv = TRUE; if (vport->isExternal) { ASSERT(vport->nicIndex != 0); ASSERT(switchContext->numPhysicalNics); switchContext->numPhysicalNics--; } /* Remove the port from the relevant lists. */ RemoveEntryList(&vport->portIdLink); InitializeListHead(&vport->portIdLink); deletedOnHv = TRUE; } if (ovsDelete && !deletedOnOvs) { vport->portNo = OVS_DPPORT_NUMBER_INVALID; vport->ovsName[0] = '\0'; /* Remove the port from the relevant lists. */ RemoveEntryList(&vport->ovsNameLink); InitializeListHead(&vport->ovsNameLink); RemoveEntryList(&vport->portNoLink); InitializeListHead(&vport->portNoLink); if (OVS_VPORT_TYPE_VXLAN == vport->ovsType || OVS_VPORT_TYPE_STT == vport->ovsType || OVS_VPORT_TYPE_GRE == vport->ovsType) { RemoveEntryList(&vport->tunnelVportLink); InitializeListHead(&vport->tunnelVportLink); } deletedOnOvs = TRUE; } /* * Deallocate the port if it has been deleted on the Hyper-V switch as well * as OVS userspace. */ if (deletedOnHv && deletedOnOvs) { if (hvSwitchPort) { switchContext->numHvVports--; } else { switchContext->numNonHvVports--; } OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG); } return STATUS_SUCCESS; } static NTSTATUS OvsRemoveTunnelVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx, POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, BOOLEAN hvDelete, BOOLEAN ovsDelete) { POVS_TUNFLT_INIT_CONTEXT tunnelContext = NULL; PIRP irp = NULL; tunnelContext = OvsAllocateMemoryWithTag(sizeof(*tunnelContext), OVS_VPORT_POOL_TAG); if (tunnelContext == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(tunnelContext, sizeof(*tunnelContext)); tunnelContext->switchContext = switchContext; tunnelContext->hvSwitchPort = FALSE; tunnelContext->hvDelete = hvDelete; tunnelContext->ovsDelete = ovsDelete; tunnelContext->vport = vport; if (usrParamsCtx) { tunnelContext->inputBuffer = usrParamsCtx->inputBuffer; tunnelContext->outputBuffer = usrParamsCtx->outputBuffer; tunnelContext->outputLength = usrParamsCtx->outputLength; irp = usrParamsCtx->irp; } return OvsCleanupVxlanTunnel(irp, vport, OvsTunnelVportPendingRemove, tunnelContext); } /* * -------------------------------------------------------------------------- * Enumerates the ports on the Hyper-V switch. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsAddConfiguredSwitchPorts(POVS_SWITCH_CONTEXT switchContext) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; ULONG arrIndex; PNDIS_SWITCH_PORT_PARAMETERS portParam; PNDIS_SWITCH_PORT_ARRAY portArray = NULL; OVS_LOG_TRACE("Enter: switchContext:%p", switchContext); status = OvsGetPortsOnSwitch(switchContext, &portArray); if (status != NDIS_STATUS_SUCCESS) { goto cleanup; } for (arrIndex = 0; arrIndex < portArray->NumElements; arrIndex++) { portParam = NDIS_SWITCH_PORT_AT_ARRAY_INDEX(portArray, arrIndex); if (portParam->IsValidationPort) { continue; } status = HvCreatePort(switchContext, portParam, 0); if (status != STATUS_SUCCESS && status != STATUS_DATA_NOT_ACCEPTED) { break; } } cleanup: if (status != NDIS_STATUS_SUCCESS) { OvsClearAllSwitchVports(switchContext); } OvsFreeSwitchPortsArray(portArray); OVS_LOG_TRACE("Exit: status: %x", status); return status; } /* * -------------------------------------------------------------------------- * Enumerates the NICs on the Hyper-V switch. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsInitConfiguredSwitchNics(POVS_SWITCH_CONTEXT switchContext) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNDIS_SWITCH_NIC_ARRAY nicArray = NULL; ULONG arrIndex; PNDIS_SWITCH_NIC_PARAMETERS nicParam; OVS_LOG_TRACE("Enter: switchContext: %p", switchContext); /* * Now, get NIC list. */ status = OvsGetNicsOnSwitch(switchContext, &nicArray); if (status != NDIS_STATUS_SUCCESS) { goto cleanup; } for (arrIndex = 0; arrIndex < nicArray->NumElements; ++arrIndex) { nicParam = NDIS_SWITCH_NIC_AT_ARRAY_INDEX(nicArray, arrIndex); /* * XXX: Check if the port is configured with a VLAN. Disallow such a * configuration, since we don't support tag-in-tag. * XXX: Check if the port is connected to a VF. Disconnect the VF in * such a case. */ status = HvCreateNic(switchContext, nicParam); if (status == NDIS_STATUS_SUCCESS) { HvConnectNic(switchContext, nicParam); } } cleanup: OvsFreeSwitchNicsArray(nicArray); OVS_LOG_TRACE("Exit: status: %x", status); return status; } /* * -------------------------------------------------------------------------- * Deletes ports added from the Hyper-V switch as well as OVS usersapce. The * function deletes ports in 'portIdHashArray'. This will delete most of the * ports that are in the 'portNoHashArray' as well. Any remaining ports * are deleted by walking the 'portNoHashArray'. * -------------------------------------------------------------------------- */ VOID OvsClearAllSwitchVports(POVS_SWITCH_CONTEXT switchContext) { for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) { PLIST_ENTRY head, link, next; head = &(switchContext->portIdHashArray[hash & OVS_VPORT_MASK]); LIST_FORALL_SAFE(head, link, next) { POVS_VPORT_ENTRY vport; vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portIdLink); OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE); } } /* * Remove 'virtualExternalVport' as well. This port is not part of the * 'portIdHashArray'. */ if (switchContext->virtualExternalVport) { OvsRemoveAndDeleteVport(NULL, switchContext, (POVS_VPORT_ENTRY)switchContext->virtualExternalVport, TRUE, TRUE); } for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) { PLIST_ENTRY head, link, next; head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]); LIST_FORALL_SAFE(head, link, next) { POVS_VPORT_ENTRY vport; vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink); ASSERT(OvsIsTunnelVportType(vport->ovsType) || (vport->ovsType == OVS_VPORT_TYPE_INTERNAL && vport->isBridgeInternal) || vport->isAbsentOnHv == TRUE); OvsRemoveAndDeleteVport(NULL, switchContext, vport, TRUE, TRUE); } } ASSERT(switchContext->virtualExternalVport == NULL); ASSERT(switchContext->internalVport == NULL); } NTSTATUS OvsConvertIfCountedStrToAnsiStr(PIF_COUNTED_STRING wStr, CHAR *str, UINT16 maxStrLen) { ANSI_STRING astr; UNICODE_STRING ustr; NTSTATUS status; UINT32 size; ustr.Buffer = wStr->String; ustr.Length = wStr->Length; ustr.MaximumLength = IF_MAX_STRING_SIZE; astr.Buffer = str; astr.MaximumLength = maxStrLen; astr.Length = 0; size = RtlUnicodeStringToAnsiSize(&ustr); if (size > maxStrLen) { return STATUS_BUFFER_OVERFLOW; } status = RtlUnicodeStringToAnsiString(&astr, &ustr, FALSE); ASSERT(status == STATUS_SUCCESS); if (status != STATUS_SUCCESS) { return status; } ASSERT(astr.Length <= maxStrLen); str[astr.Length] = 0; return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Utility function that populates a 'OVS_VPORT_EXT_INFO' structure for the * specified vport. * -------------------------------------------------------------------------- */ NTSTATUS OvsGetExtInfoIoctl(POVS_VPORT_GET vportGet, POVS_VPORT_EXT_INFO extInfo) { POVS_VPORT_ENTRY vport; size_t len; LOCK_STATE_EX lockState; NTSTATUS status = STATUS_SUCCESS; BOOLEAN doConvert = FALSE; RtlZeroMemory(extInfo, sizeof (POVS_VPORT_EXT_INFO)); NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0); if (vportGet->portNo == 0) { StringCbLengthA(vportGet->name, OVS_MAX_PORT_NAME_LENGTH - 1, &len); vport = OvsFindVportByHvNameA(gOvsSwitchContext, vportGet->name); if (vport == NULL) { /* If the port is not a Hyper-V port and it has been added earlier, * we'll find it in 'ovsPortNameHashArray'. */ vport = OvsFindVportByOvsName(gOvsSwitchContext, vportGet->name); } } else { vport = OvsFindVportByPortNo(gOvsSwitchContext, vportGet->portNo); } if (vport == NULL || (vport->ovsState != OVS_STATE_CONNECTED && vport->ovsState != OVS_STATE_NIC_CREATED)) { NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); if (vportGet->portNo) { OVS_LOG_WARN("vport %u does not exist any more", vportGet->portNo); } else { OVS_LOG_WARN("vport %s does not exist any more", vportGet->name); } status = STATUS_DEVICE_DOES_NOT_EXIST; goto ext_info_done; } extInfo->dpNo = vportGet->dpNo; extInfo->portNo = vport->portNo; RtlCopyMemory(extInfo->macAddress, vport->currMacAddress, sizeof (vport->currMacAddress)); RtlCopyMemory(extInfo->permMACAddress, vport->permMacAddress, sizeof (vport->permMacAddress)); if (vport->ovsType == OVS_VPORT_TYPE_NETDEV) { RtlCopyMemory(extInfo->vmMACAddress, vport->vmMacAddress, sizeof (vport->vmMacAddress)); } extInfo->nicIndex = vport->nicIndex; extInfo->portId = vport->portId; extInfo->type = vport->ovsType; extInfo->mtu = vport->mtu; /* * TO be revisit XXX */ if (vport->ovsState == OVS_STATE_NIC_CREATED) { extInfo->status = OVS_EVENT_CONNECT | OVS_EVENT_LINK_DOWN; } else if (vport->ovsState == OVS_STATE_CONNECTED) { extInfo->status = OVS_EVENT_CONNECT | OVS_EVENT_LINK_UP; } else { extInfo->status = OVS_EVENT_DISCONNECT; } if (extInfo->type == OVS_VPORT_TYPE_NETDEV && (vport->ovsState == OVS_STATE_NIC_CREATED || vport->ovsState == OVS_STATE_CONNECTED)) { doConvert = TRUE; } else { extInfo->vmUUID[0] = 0; extInfo->vifUUID[0] = 0; } NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); if (doConvert) { status = OvsConvertIfCountedStrToAnsiStr(&vport->portFriendlyName, extInfo->name, OVS_MAX_PORT_NAME_LENGTH); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fail to convert NIC name."); extInfo->vmUUID[0] = 0; } status = OvsConvertIfCountedStrToAnsiStr(&vport->vmName, extInfo->vmUUID, OVS_MAX_VM_UUID_LEN); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fail to convert VM name."); extInfo->vmUUID[0] = 0; } status = OvsConvertIfCountedStrToAnsiStr(&vport->nicName, extInfo->vifUUID, OVS_MAX_VIF_UUID_LEN); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fail to convert nic UUID"); extInfo->vifUUID[0] = 0; } /* * for now ignore status */ status = STATUS_SUCCESS; } ext_info_done: return status; } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_WIN_NETDEV_CMD_GET'. * -------------------------------------------------------------------------- */ NTSTATUS OvsGetNetdevCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS status = STATUS_SUCCESS; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; NL_ERROR nlError = NL_ERROR_SUCCESS; OVS_VPORT_GET vportGet; OVS_VPORT_EXT_INFO info; static const NL_POLICY ovsNetdevPolicy[] = { [OVS_WIN_NETDEV_ATTR_NAME] = { .type = NL_A_STRING, .minLen = 2, .maxLen = IFNAMSIZ }, }; PNL_ATTR netdevAttrs[ARRAY_SIZE(ovsNetdevPolicy)]; /* input buffer has been validated while validating transaction dev op. */ ASSERT(usrParamsCtx->inputBuffer != NULL && usrParamsCtx->inputLength > sizeof *msgIn); if (msgOut == NULL || usrParamsCtx->outputLength < sizeof *msgOut) { return STATUS_INVALID_BUFFER_SIZE; } if (!NlAttrParse((PNL_MSG_HDR)msgIn, NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, NlMsgAttrsLen((PNL_MSG_HDR)msgIn), ovsNetdevPolicy, ARRAY_SIZE(ovsNetdevPolicy), netdevAttrs, ARRAY_SIZE(netdevAttrs))) { return STATUS_INVALID_PARAMETER; } vportGet.portNo = 0; RtlCopyMemory(&vportGet.name, NlAttrGet(netdevAttrs[OVS_VPORT_ATTR_NAME]), NlAttrGetSize(netdevAttrs[OVS_VPORT_ATTR_NAME])); status = OvsGetExtInfoIoctl(&vportGet, &info); if (status == STATUS_DEVICE_DOES_NOT_EXIST) { nlError = NL_ERROR_NODEV; goto cleanup; } status = CreateNetlinkMesgForNetdev(&info, msgIn, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength, gOvsSwitchContext->dpNo); if (status == STATUS_SUCCESS) { *replyLen = msgOut->nlMsg.nlmsgLen; } cleanup: if (nlError != NL_ERROR_SUCCESS) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Utility function to construct an OVS_MESSAGE for the specified vport. The * OVS_MESSAGE contains the output of a netdev command. * -------------------------------------------------------------------------- */ static NTSTATUS CreateNetlinkMesgForNetdev(POVS_VPORT_EXT_INFO info, POVS_MESSAGE msgIn, PVOID outBuffer, UINT32 outBufLen, int dpIfIndex) { NL_BUFFER nlBuffer; BOOLEAN ok; PNL_MSG_HDR nlMsg; UINT32 netdevFlags = 0; NlBufInit(&nlBuffer, outBuffer, outBufLen); ok = NlFillOvsMsg(&nlBuffer, msgIn->nlMsg.nlmsgType, NLM_F_MULTI, msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid, msgIn->genlMsg.cmd, msgIn->genlMsg.version, dpIfIndex); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_PORT_NO, info->portNo); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_TYPE, info->type); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailString(&nlBuffer, OVS_WIN_NETDEV_ATTR_NAME, info->name); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailUnspec(&nlBuffer, OVS_WIN_NETDEV_ATTR_MAC_ADDR, (PCHAR)info->macAddress, sizeof (info->macAddress)); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_MTU, info->mtu); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } if (info->status != OVS_EVENT_CONNECT) { netdevFlags = OVS_WIN_NETDEV_IFF_UP; } ok = NlMsgPutTailU32(&nlBuffer, OVS_WIN_NETDEV_ATTR_IF_FLAGS, netdevFlags); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } /* * XXX: add netdev_stats when we have the definition available in the * kernel. */ nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuffer, 0, 0); nlMsg->nlmsgLen = NlBufSize(&nlBuffer); return STATUS_SUCCESS; } static __inline VOID OvsWaitActivate(POVS_SWITCH_CONTEXT switchContext, ULONG sleepMicroSec) { while ((!switchContext->isActivated) && (!switchContext->isActivateFailed)) { /* Wait for the switch to be active and * the list of ports in OVS to be initialized. */ NdisMSleep(sleepMicroSec); } } static NTSTATUS OvsCreateMsgFromVport(POVS_VPORT_ENTRY vport, POVS_MESSAGE msgIn, PVOID outBuffer, UINT32 outBufLen, int dpIfIndex) { NL_BUFFER nlBuffer; OVS_VPORT_FULL_STATS vportStats; BOOLEAN ok; PNL_MSG_HDR nlMsg; NlBufInit(&nlBuffer, outBuffer, outBufLen); ok = NlFillOvsMsg(&nlBuffer, msgIn->nlMsg.nlmsgType, NLM_F_MULTI, msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid, msgIn->genlMsg.cmd, msgIn->genlMsg.version, dpIfIndex); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailU32(&nlBuffer, OVS_VPORT_ATTR_PORT_NO, vport->portNo); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailU32(&nlBuffer, OVS_VPORT_ATTR_TYPE, vport->ovsType); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } ok = NlMsgPutTailString(&nlBuffer, OVS_VPORT_ATTR_NAME, vport->ovsName); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } /* * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath, * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set, * it means we have an array of pids, instead of a single pid. * ATM we assume we have one pid only. */ ok = NlMsgPutTailU32(&nlBuffer, OVS_VPORT_ATTR_UPCALL_PID, vport->upcallPid); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } /*stats*/ vportStats.rxPackets = vport->stats.rxPackets; vportStats.rxBytes = vport->stats.rxBytes; vportStats.txPackets = vport->stats.txPackets; vportStats.txBytes = vport->stats.txBytes; vportStats.rxErrors = vport->errStats.rxErrors; vportStats.txErrors = vport->errStats.txErrors; vportStats.rxDropped = vport->errStats.rxDropped; vportStats.txDropped = vport->errStats.txDropped; ok = NlMsgPutTailUnspec(&nlBuffer, OVS_VPORT_ATTR_STATS, (PCHAR)&vportStats, sizeof(OVS_VPORT_FULL_STATS)); if (!ok) { return STATUS_INVALID_BUFFER_SIZE; } /* * XXX: when vxlan udp dest port becomes configurable, we will also need * to add vport options */ nlMsg = (PNL_MSG_HDR)NlBufAt(&nlBuffer, 0, 0); nlMsg->nlmsgLen = NlBufSize(&nlBuffer); return STATUS_SUCCESS; } static NTSTATUS OvsGetVportDumpNext(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { POVS_MESSAGE msgIn; POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; LOCK_STATE_EX lockState; UINT32 i = OVS_MAX_VPORT_ARRAY_SIZE; /* * XXX: this function shares some code with other dump command(s). * In the future, we will need to refactor the dump functions */ ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP); if (instance->dumpState.ovsMsg == NULL) { ASSERT(FALSE); return STATUS_INVALID_DEVICE_STATE; } /* Output buffer has been validated while validating read dev op. */ ASSERT(usrParamsCtx->outputBuffer != NULL); msgIn = instance->dumpState.ovsMsg; /* * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath, * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set, * it means we have an array of pids, instead of a single pid. * ATM we assume we have one pid only. */ NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0); if (gOvsSwitchContext->numHvVports > 0 || gOvsSwitchContext->numNonHvVports > 0) { /* inBucket: the bucket, used for lookup */ UINT32 inBucket = instance->dumpState.index[0]; /* inIndex: index within the given bucket, used for lookup */ UINT32 inIndex = instance->dumpState.index[1]; /* the bucket to be used for the next dump operation */ UINT32 outBucket = 0; /* the index within the outBucket to be used for the next dump */ UINT32 outIndex = 0; for (i = inBucket; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) { PLIST_ENTRY head, link; head = &(gOvsSwitchContext->portNoHashArray[i]); POVS_VPORT_ENTRY vport = NULL; outIndex = 0; LIST_FORALL(head, link) { /* * if one or more dumps were previously done on this same bucket, * inIndex will be > 0, so we'll need to reply with the * inIndex + 1 vport from the bucket. */ if (outIndex >= inIndex) { vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink); ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID); OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength, gOvsSwitchContext->dpNo); ++outIndex; break; } ++outIndex; } if (vport) { break; } /* * if no vport was found above, check the next bucket, beginning * with the first (i.e. index 0) elem from within that bucket */ inIndex = 0; } outBucket = i; /* XXX: what about NLMSG_DONE (as msg type)? */ instance->dumpState.index[0] = outBucket; instance->dumpState.index[1] = outIndex; } NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); /* if i < OVS_MAX_VPORT_ARRAY_SIZE => vport was found */ if (i < OVS_MAX_VPORT_ARRAY_SIZE) { POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; *replyLen = msgOut->nlMsg.nlmsgLen; } else { /* * if i >= OVS_MAX_VPORT_ARRAY_SIZE => vport was not found => * it's dump done */ *replyLen = 0; /* Free up the dump state, since there's no more data to continue. */ FreeUserDumpState(instance); } return STATUS_SUCCESS; } static NTSTATUS OvsGetVport(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS status = STATUS_SUCCESS; LOCK_STATE_EX lockState; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; POVS_VPORT_ENTRY vport = NULL; NL_ERROR nlError = NL_ERROR_SUCCESS; PCHAR portName = NULL; UINT32 portNameLen = 0; UINT32 portNumber = OVS_DPPORT_NUMBER_INVALID; static const NL_POLICY ovsVportPolicy[] = { [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE }, [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .minLen = 2, .maxLen = IFNAMSIZ, .optional = TRUE}, }; PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)]; /* input buffer has been validated while validating write dev op. */ ASSERT(usrParamsCtx->inputBuffer != NULL); if (!NlAttrParse((PNL_MSG_HDR)msgIn, NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, NlMsgAttrsLen((PNL_MSG_HDR)msgIn), ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy), vportAttrs, ARRAY_SIZE(vportAttrs))) { return STATUS_INVALID_PARAMETER; } /* Output buffer has been validated while validating transact dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, 0); if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) { portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]); portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]); /* the port name is expected to be null-terminated */ ASSERT(portName[portNameLen - 1] == '\0'); vport = OvsFindVportByOvsName(gOvsSwitchContext, portName); } else if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) { portNumber = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]); vport = OvsFindVportByPortNo(gOvsSwitchContext, portNumber); } else { nlError = NL_ERROR_INVAL; NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); goto Cleanup; } if (!vport) { nlError = NL_ERROR_NODEV; NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); goto Cleanup; } status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength, gOvsSwitchContext->dpNo); NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); *replyLen = msgOut->nlMsg.nlmsgLen; Cleanup: if (nlError != NL_ERROR_SUCCESS) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_VPORT_CMD_GET'. * * The function handles the initial call to setup the dump state, as well as * subsequent calls to continue dumping data. * -------------------------------------------------------------------------- */ NTSTATUS OvsGetVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { *replyLen = 0; switch (usrParamsCtx->devOp) { case OVS_WRITE_DEV_OP: return OvsSetupDumpStart(usrParamsCtx); case OVS_READ_DEV_OP: return OvsGetVportDumpNext(usrParamsCtx, replyLen); case OVS_TRANSACTION_DEV_OP: return OvsGetVport(usrParamsCtx, replyLen); default: return STATUS_INVALID_DEVICE_REQUEST; } } static UINT32 OvsComputeVportNo(POVS_SWITCH_CONTEXT switchContext) { /* we are not allowed to create the port OVS_DPPORT_NUMBER_LOCAL */ for (ULONG i = OVS_DPPORT_NUMBER_LOCAL + 1; i < MAXUINT16; ++i) { POVS_VPORT_ENTRY vport; vport = OvsFindVportByPortNo(switchContext, i); if (!vport) { return i; } } return OVS_DPPORT_NUMBER_INVALID; } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_VPORT_CMD_NEW'. * -------------------------------------------------------------------------- */ NTSTATUS OvsNewVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NDIS_STATUS status = STATUS_SUCCESS; LOCK_STATE_EX lockState; NL_ERROR nlError = NL_ERROR_SUCCESS; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; POVS_VPORT_ENTRY vport = NULL; PCHAR portName; ULONG portNameLen; UINT32 portType; BOOLEAN vportAllocated = FALSE, vportInitialized = FALSE; static const NL_POLICY ovsVportPolicy[] = { [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE }, [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32, .optional = FALSE }, [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ, .optional = FALSE}, [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC, .optional = FALSE }, [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = TRUE }, }; PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)]; /* input buffer has been validated while validating write dev op. */ ASSERT(usrParamsCtx->inputBuffer != NULL); /* Output buffer has been validated while validating transact dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); if (!NlAttrParse((PNL_MSG_HDR)msgIn, NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, NlMsgAttrsLen((PNL_MSG_HDR)msgIn), ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy), vportAttrs, ARRAY_SIZE(vportAttrs))) { return STATUS_INVALID_PARAMETER; } portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]); portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]); portType = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_TYPE]); /* we are expecting null terminated strings to be passed */ ASSERT(portName[portNameLen - 1] == '\0'); NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0); vport = OvsFindVportByOvsName(gOvsSwitchContext, portName); if (vport) { nlError = NL_ERROR_EXIST; goto Cleanup; } if (portType == OVS_VPORT_TYPE_NETDEV) { /* External ports can also be looked up like VIF ports. */ vport = OvsFindVportByHvNameA(gOvsSwitchContext, portName); } else { ASSERT(OvsIsTunnelVportType(portType) || portType == OVS_VPORT_TYPE_INTERNAL); vport = (POVS_VPORT_ENTRY)OvsAllocateVport(); if (vport == NULL) { nlError = NL_ERROR_NOMEM; goto Cleanup; } vportAllocated = TRUE; if (OvsIsTunnelVportType(portType)) { UINT16 transportPortDest = 0; switch (portType) { case OVS_VPORT_TYPE_GRE: break; case OVS_VPORT_TYPE_VXLAN: transportPortDest = VXLAN_UDP_PORT; break; case OVS_VPORT_TYPE_STT: transportPortDest = STT_TCP_PORT; break; default: nlError = NL_ERROR_INVAL; goto Cleanup; } if (vportAttrs[OVS_VPORT_ATTR_OPTIONS]) { PNL_ATTR attr = NlAttrFindNested(vportAttrs[OVS_VPORT_ATTR_OPTIONS], OVS_TUNNEL_ATTR_DST_PORT); if (attr) { transportPortDest = NlAttrGetU16(attr); } } status = OvsInitTunnelVport(usrParamsCtx, vport, portType, transportPortDest); nlError = NlMapStatusToNlErr(status); } else { OvsInitBridgeInternalVport(vport); } vportInitialized = TRUE; if (nlError == NL_ERROR_SUCCESS) { vport->ovsState = OVS_STATE_CONNECTED; vport->nicState = NdisSwitchNicStateConnected; /* * Allow the vport to be deleted, because there is no * corresponding hyper-v switch part. */ vport->isAbsentOnHv = TRUE; } else { goto Cleanup; } } if (!vport) { nlError = NL_ERROR_INVAL; goto Cleanup; } if (vport->portNo != OVS_DPPORT_NUMBER_INVALID) { nlError = NL_ERROR_EXIST; goto Cleanup; } if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) { /* * XXX: when we implement the limit for ovs port number to be * MAXUINT16, we'll need to check the port number received from the * userspace. */ vport->portNo = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]); } else { vport->portNo = OvsComputeVportNo(gOvsSwitchContext); if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) { nlError = NL_ERROR_NOMEM; goto Cleanup; } } /* The ovs port name must be uninitialized. */ ASSERT(vport->ovsName[0] == '\0'); ASSERT(portNameLen <= OVS_MAX_PORT_NAME_LENGTH); RtlCopyMemory(vport->ovsName, portName, portNameLen); /* if we don't have options, then vport->portOptions will be NULL */ vport->portOptions = vportAttrs[OVS_VPORT_ATTR_OPTIONS]; /* * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath, * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set, * it means we have an array of pids, instead of a single pid. * ATM we assume we have one pid only. */ vport->upcallPid = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]); status = InitOvsVportCommon(gOvsSwitchContext, vport); ASSERT(status == STATUS_SUCCESS); status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength, gOvsSwitchContext->dpNo); *replyLen = msgOut->nlMsg.nlmsgLen; Cleanup: NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); if ((nlError != NL_ERROR_SUCCESS) && (nlError != NL_ERROR_PENDING)) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; if (vport && vportAllocated == TRUE) { if (vportInitialized == TRUE) { if (OvsIsTunnelVportType(portType)) { switch (vport->ovsType) { case OVS_VPORT_TYPE_VXLAN: OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL); break; case OVS_VPORT_TYPE_STT: OvsCleanupSttTunnel(vport); break; default: ASSERT(!"Invalid tunnel port type"); } } } OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG); } NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_VPORT_CMD_SET'. * -------------------------------------------------------------------------- */ NTSTATUS OvsSetVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NDIS_STATUS status = STATUS_SUCCESS; LOCK_STATE_EX lockState; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; POVS_VPORT_ENTRY vport = NULL; NL_ERROR nlError = NL_ERROR_SUCCESS; static const NL_POLICY ovsVportPolicy[] = { [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE }, [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32, .optional = TRUE }, [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ, .optional = TRUE }, [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC, .optional = TRUE }, [OVS_VPORT_ATTR_STATS] = { .type = NL_A_UNSPEC, .minLen = sizeof(OVS_VPORT_FULL_STATS), .maxLen = sizeof(OVS_VPORT_FULL_STATS), .optional = TRUE }, [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = TRUE }, }; PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)]; ASSERT(usrParamsCtx->inputBuffer != NULL); if (!NlAttrParse((PNL_MSG_HDR)msgIn, NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, NlMsgAttrsLen((PNL_MSG_HDR)msgIn), ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy), vportAttrs, ARRAY_SIZE(vportAttrs))) { return STATUS_INVALID_PARAMETER; } /* Output buffer has been validated while validating transact dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0); if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) { PSTR portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]); #ifdef DBG UINT32 portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]); #endif /* the port name is expected to be null-terminated */ ASSERT(portName[portNameLen - 1] == '\0'); vport = OvsFindVportByOvsName(gOvsSwitchContext, portName); } else if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) { vport = OvsFindVportByPortNo(gOvsSwitchContext, NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO])); } if (!vport) { nlError = NL_ERROR_NODEV; goto Cleanup; } /* * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath, * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set, * it means we have an array of pids, instead of a single pid. * Currently, we support only one pid. */ if (vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]) { vport->upcallPid = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]); } if (vportAttrs[OVS_VPORT_ATTR_TYPE]) { OVS_VPORT_TYPE type = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_TYPE]); if (type != vport->ovsType) { nlError = NL_ERROR_INVAL; goto Cleanup; } } if (vportAttrs[OVS_VPORT_ATTR_OPTIONS]) { OVS_LOG_ERROR("Vport options not supported"); nlError = NL_ERROR_NOTSUPP; goto Cleanup; } status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength, gOvsSwitchContext->dpNo); *replyLen = msgOut->nlMsg.nlmsgLen; Cleanup: NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); if (nlError != NL_ERROR_SUCCESS) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_VPORT_CMD_DEL'. * -------------------------------------------------------------------------- */ NTSTATUS OvsDeleteVportCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NDIS_STATUS status = STATUS_SUCCESS; LOCK_STATE_EX lockState; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; POVS_VPORT_ENTRY vport = NULL; NL_ERROR nlError = NL_ERROR_SUCCESS; PSTR portName = NULL; UINT32 portNameLen = 0; static const NL_POLICY ovsVportPolicy[] = { [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE }, [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ, .optional = TRUE }, }; PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)]; ASSERT(usrParamsCtx->inputBuffer != NULL); if (!NlAttrParse((PNL_MSG_HDR)msgIn, NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, NlMsgAttrsLen((PNL_MSG_HDR)msgIn), ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy), vportAttrs, ARRAY_SIZE(vportAttrs))) { return STATUS_INVALID_PARAMETER; } /* Output buffer has been validated while validating transact dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); NdisAcquireRWLockWrite(gOvsSwitchContext->dispatchLock, &lockState, 0); if (vportAttrs[OVS_VPORT_ATTR_NAME] != NULL) { portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]); portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]); /* the port name is expected to be null-terminated */ ASSERT(portName[portNameLen - 1] == '\0'); vport = OvsFindVportByOvsName(gOvsSwitchContext, portName); } else if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) { vport = OvsFindVportByPortNo(gOvsSwitchContext, NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO])); } if (!vport) { nlError = NL_ERROR_NODEV; goto Cleanup; } status = OvsCreateMsgFromVport(vport, msgIn, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength, gOvsSwitchContext->dpNo); *replyLen = msgOut->nlMsg.nlmsgLen; /* * Mark the port as deleted from OVS userspace. If the port does not exist * on the Hyper-V switch, it gets deallocated. Otherwise, it stays. */ status = OvsRemoveAndDeleteVport(usrParamsCtx, gOvsSwitchContext, vport, FALSE, TRUE); if (status) { nlError = NlMapStatusToNlErr(status); } Cleanup: NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); if ((nlError != NL_ERROR_SUCCESS) && (nlError != NL_ERROR_PENDING)) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } return (status == STATUS_PENDING) ? STATUS_PENDING : STATUS_SUCCESS; } static VOID OvsTunnelVportPendingRemove(PVOID context, NTSTATUS status, UINT32 *replyLen) { POVS_TUNFLT_INIT_CONTEXT tunnelContext = (POVS_TUNFLT_INIT_CONTEXT) context; POVS_SWITCH_CONTEXT switchContext = tunnelContext->switchContext; POVS_VPORT_ENTRY vport = tunnelContext->vport; POVS_MESSAGE msgIn = (POVS_MESSAGE)tunnelContext->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)tunnelContext->outputBuffer; NL_ERROR nlError = NlMapStatusToNlErr(status); LOCK_STATE_EX lockState; NdisAcquireRWLockWrite(switchContext->dispatchLock, &lockState, 0); if (msgIn && msgOut) { /* Check the received status to reply to the caller. */ if (STATUS_SUCCESS == status) { OvsCreateMsgFromVport(vport, msgIn, msgOut, tunnelContext->outputLength, switchContext->dpNo); *replyLen = msgOut->nlMsg.nlmsgLen; } else { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR)msgOut; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } } ASSERT(vport->isAbsentOnHv == TRUE); ASSERT(vport->portNo != OVS_DPPORT_NUMBER_INVALID); /* Remove the port from the relevant lists. */ switchContext->numNonHvVports--; RemoveEntryList(&vport->ovsNameLink); RemoveEntryList(&vport->portNoLink); RemoveEntryList(&vport->tunnelVportLink); if (vport->priv) { OvsFreeMemoryWithTag(vport->priv, OVS_VXLAN_POOL_TAG); vport->priv = NULL; } OvsFreeMemoryWithTag(vport, OVS_VPORT_POOL_TAG); NdisReleaseRWLock(switchContext->dispatchLock, &lockState); } static VOID OvsTunnelVportPendingInit(PVOID context, NTSTATUS status, UINT32 *replyLen) { POVS_TUNFLT_INIT_CONTEXT tunnelContext = (POVS_TUNFLT_INIT_CONTEXT) context; POVS_VPORT_ENTRY vport = tunnelContext->vport; POVS_MESSAGE msgIn = (POVS_MESSAGE)tunnelContext->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)tunnelContext->outputBuffer; PCHAR portName; ULONG portNameLen = 0; UINT32 portType = 0; NL_ERROR nlError = NL_ERROR_SUCCESS; BOOLEAN error = TRUE; do { if (!NT_SUCCESS(status)) { nlError = NlMapStatusToNlErr(status); break; } static const NL_POLICY ovsVportPolicy[] = { [OVS_VPORT_ATTR_PORT_NO] = { .type = NL_A_U32, .optional = TRUE }, [OVS_VPORT_ATTR_TYPE] = { .type = NL_A_U32, .optional = FALSE }, [OVS_VPORT_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ, .optional = FALSE }, [OVS_VPORT_ATTR_UPCALL_PID] = { .type = NL_A_UNSPEC, .optional = FALSE }, [OVS_VPORT_ATTR_OPTIONS] = { .type = NL_A_NESTED, .optional = TRUE }, }; PNL_ATTR vportAttrs[ARRAY_SIZE(ovsVportPolicy)]; /* input buffer has been validated while validating write dev op. */ ASSERT(msgIn != NULL); /* Output buffer has been validated while validating transact dev op. */ ASSERT(msgOut != NULL && tunnelContext->outputLength >= sizeof *msgOut); if (!NlAttrParse((PNL_MSG_HDR)msgIn, NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, NlMsgAttrsLen((PNL_MSG_HDR)msgIn), ovsVportPolicy, ARRAY_SIZE(ovsVportPolicy), vportAttrs, ARRAY_SIZE(vportAttrs))) { nlError = NL_ERROR_INVAL; break; } portName = NlAttrGet(vportAttrs[OVS_VPORT_ATTR_NAME]); portNameLen = NlAttrGetSize(vportAttrs[OVS_VPORT_ATTR_NAME]); portType = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_TYPE]); if (vport->portNo != OVS_DPPORT_NUMBER_INVALID) { nlError = NL_ERROR_EXIST; break; } vport->ovsState = OVS_STATE_CONNECTED; vport->nicState = NdisSwitchNicStateConnected; /* * Allow the vport to be deleted, because there is no * corresponding hyper-v switch part. */ vport->isAbsentOnHv = TRUE; if (vportAttrs[OVS_VPORT_ATTR_PORT_NO] != NULL) { /* * XXX: when we implement the limit for OVS port number to be * MAXUINT16, we'll need to check the port number received from the * userspace. */ vport->portNo = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_PORT_NO]); } else { vport->portNo = OvsComputeVportNo(gOvsSwitchContext); if (vport->portNo == OVS_DPPORT_NUMBER_INVALID) { nlError = NL_ERROR_NOMEM; break; } } /* The ovs port name must be uninitialized. */ ASSERT(vport->ovsName[0] == '\0'); ASSERT(portNameLen <= OVS_MAX_PORT_NAME_LENGTH); RtlCopyMemory(vport->ovsName, portName, portNameLen); /* if we don't have options, then vport->portOptions will be NULL */ vport->portOptions = vportAttrs[OVS_VPORT_ATTR_OPTIONS]; /* * XXX: when we implement OVS_DP_ATTR_USER_FEATURES in datapath, * we'll need to check the OVS_DP_F_VPORT_PIDS flag: if it is set, * it means we have an array of pids, instead of a single pid. * ATM we assume we have one pid only. */ vport->upcallPid = NlAttrGetU32(vportAttrs[OVS_VPORT_ATTR_UPCALL_PID]); status = InitOvsVportCommon(gOvsSwitchContext, vport); ASSERT(status == STATUS_SUCCESS); OvsCreateMsgFromVport(vport, msgIn, msgOut, tunnelContext->outputLength, gOvsSwitchContext->dpNo); *replyLen = msgOut->nlMsg.nlmsgLen; error = FALSE; } while (error); if (error) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) msgOut; OvsCleanupVxlanTunnel(NULL, vport, NULL, NULL); OvsFreeMemory(vport); NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Debug.h0000644000000000000000000000013112631676262021650 xustar0030 mtime=1449622706.938438204 29 atime=1456592667.30709024 30 ctime=1456594660.177288147 openvswitch-2.5.0/datapath-windows/ovsext/Debug.h0000664000175000017500000000560112631676262023343 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __DEBUG_H_ #define __DEBUG_H_ 1 #define OVS_DBG_INIT BIT32(0) #define OVS_DBG_SWITCH BIT32(1) #define OVS_DBG_VPORT BIT32(2) #define OVS_DBG_FLOW BIT32(3) #define OVS_DBG_QOS BIT32(4) #define OVS_DBG_USER BIT32(5) #define OVS_DBG_EXECUTE BIT32(6) #define OVS_DBG_EVENT BIT32(7) #define OVS_DBG_DISPATCH BIT32(8) #define OVS_DBG_OID BIT32(9) #define OVS_DBG_STATUS BIT32(10) #define OVS_DBG_CHECKSUM BIT32(11) #define OVS_DBG_VXLAN BIT32(12) #define OVS_DBG_GRE BIT32(13) #define OVS_DBG_ACTION BIT32(14) #define OVS_DBG_DATAPATH BIT32(15) #define OVS_DBG_PROPERTY BIT32(16) #define OVS_DBG_IPHELPER BIT32(17) #define OVS_DBG_BUFMGMT BIT32(18) #define OVS_DBG_OTHERS BIT32(19) #define OVS_DBG_NETLINK BIT32(20) #define OVS_DBG_TUNFLT BIT32(21) #define OVS_DBG_STT BIT32(22) #define OVS_DBG_RESERVED BIT32(31) //Please add above OVS_DBG_RESERVED. #define OVS_DBG_ERROR DPFLTR_ERROR_LEVEL #define OVS_DBG_WARN DPFLTR_WARNING_LEVEL #define OVS_DBG_TRACE DPFLTR_TRACE_LEVEL #define OVS_DBG_INFO DPFLTR_INFO_LEVEL #define OVS_DBG_LOUD (DPFLTR_INFO_LEVEL + 1) VOID OvsLog(UINT32 level, UINT32 flag, CHAR *funcName, UINT32 line, CHAR *format, ...); #define OVS_LOG_LOUD(_format, ...) \ OvsLog(OVS_DBG_LOUD, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__) #define OVS_LOG_INFO(_format, ...) \ OvsLog(OVS_DBG_INFO, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__) #define OVS_LOG_TRACE(_format, ...) \ OvsLog(OVS_DBG_TRACE, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__) #define OVS_LOG_ERROR(_format, ...) \ OvsLog(OVS_DBG_ERROR, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__) #define OVS_LOG_WARN(_format, ...) \ OvsLog(OVS_DBG_WARN, OVS_DBG_MOD, __FUNCTION__, __LINE__, _format, __VA_ARGS__) #if DBG #define OVS_VERIFY_IRQL(_x) \ if (KeGetCurrentIrql() != (KIRQL)_x) { \ OVS_LOG_WARN("expected IRQL %u, actual IRQL: %u", \ _x, KeGetCurrentIrql()); \ } #define OVS_VERIFY_IRQL_LE(_x) \ if (KeGetCurrentIrql() > (KIRQL)_x) { \ OVS_LOG_WARN("expected IRQL <= %u, actual IRQL: %u", \ _x, KeGetCurrentIrql()); \ } #else #define OVS_VERIFY_IRQL(_x) #define OVS_VERIFY_IRQL_LE(_x) #endif #endif /* __DEBUG_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/PacketParser.h0000644000000000000000000000013212664352753023211 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.213289661 openvswitch-2.5.0/datapath-windows/ovsext/PacketParser.h0000664000175000017500000001060412664352753024702 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __PACKET_PARSER_H_ #define __PACKET_PARSER_H_ 1 #include "precomp.h" #include "NetProto.h" const VOID* OvsGetPacketBytes(const NET_BUFFER_LIST *_pNB, UINT32 len, UINT32 SrcOffset, VOID *storage); NDIS_STATUS OvsParseIPv6(const NET_BUFFER_LIST *packet, OvsFlowKey *key, POVS_PACKET_HDR_INFO layers); VOID OvsParseTcp(const NET_BUFFER_LIST *packet, L4Key *flow, POVS_PACKET_HDR_INFO layers); VOID OvsParseUdp(const NET_BUFFER_LIST *packet, L4Key *flow, POVS_PACKET_HDR_INFO layers); VOID OvsParseSctp(const NET_BUFFER_LIST *packet, L4Key *flow, POVS_PACKET_HDR_INFO layers); NDIS_STATUS OvsParseIcmpV6(const NET_BUFFER_LIST *packet, OvsFlowKey *key, POVS_PACKET_HDR_INFO layers); static __inline ULONG OvsPacketLenNBL(const NET_BUFFER_LIST *_pNB) { INT length = 0; NET_BUFFER *nb; nb = NET_BUFFER_LIST_FIRST_NB(_pNB); ASSERT(nb); while(nb) { length += NET_BUFFER_DATA_LENGTH(nb); nb = NET_BUFFER_NEXT_NB(nb); } return length; } /* * Returns the ctl field from the TCP header in 'packet', or 0 if the field * can't be read. The caller must have ensured that 'packet' contains a TCP * header. * * We can't just use TCPHdr, from netProto.h, for this because that * breaks the flags down into individual bit-fields. We can't even use * offsetof because that will try to take the address of a bit-field, * which C does not allow. */ static UINT16 OvsGetTcpCtl(const NET_BUFFER_LIST *packet, // IN const POVS_PACKET_HDR_INFO layers) // IN { #define TCP_CTL_OFS 12 // Offset of "ctl" field in TCP header. #define TCP_FLAGS(CTL) ((CTL) & 0x3f) // Obtain TCP flags from CTL. const UINT16 *ctl; UINT16 storage; ctl = OvsGetPacketBytes(packet, sizeof *ctl, layers->l4Offset + TCP_CTL_OFS, &storage); return ctl ? *ctl : 0; } static UINT8 OvsGetTcpFlags(const NET_BUFFER_LIST *packet, // IN const OvsFlowKey *key, // IN const POVS_PACKET_HDR_INFO layers) // IN { UNREFERENCED_PARAMETER(key); // should be removed later if (layers->isTcp) { return TCP_FLAGS(OvsGetTcpCtl(packet, layers)); } else { return 0; } } static const EtherArp * OvsGetArp(const NET_BUFFER_LIST *packet, UINT32 ofs, EtherArp *storage) { return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage); } static const IPHdr * OvsGetIp(const NET_BUFFER_LIST *packet, UINT32 ofs, IPHdr *storage) { const IPHdr *ip = OvsGetPacketBytes(packet, sizeof *ip, ofs, storage); if (ip) { int ipLen = ip->ihl * 4; if (ipLen >= sizeof *ip && OvsPacketLenNBL(packet) >= ofs + ipLen) { return ip; } } return NULL; } static const TCPHdr * OvsGetTcp(const NET_BUFFER_LIST *packet, UINT32 ofs, TCPHdr *storage) { const TCPHdr *tcp = OvsGetPacketBytes(packet, sizeof *tcp, ofs, storage); if (tcp) { int tcpLen = tcp->doff * 4; if (tcpLen >= sizeof *tcp && OvsPacketLenNBL(packet) >= ofs + tcpLen) { return tcp; } } return NULL; } static const UDPHdr * OvsGetUdp(const NET_BUFFER_LIST *packet, UINT32 ofs, UDPHdr *storage) { return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage); } static const SCTPHdr * OvsGetSctp(const NET_BUFFER_LIST *packet, UINT32 ofs, SCTPHdr *storage) { return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage); } static const ICMPHdr * OvsGetIcmp(const NET_BUFFER_LIST *packet, UINT32 ofs, ICMPHdr *storage) { return OvsGetPacketBytes(packet, sizeof *storage, ofs, storage); } #endif /* __PACKET_PARSER_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Tunnel.c0000644000000000000000000000013112631676262022062 xustar0029 mtime=1449622706.97843961 30 atime=1456592667.315090569 30 ctime=1456594660.217289829 openvswitch-2.5.0/datapath-windows/ovsext/Tunnel.c0000664000175000017500000002660012631676262023557 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * OvsTunnel.c * WFP Classified callback function and Action code for injecting a packet to the vswitch */ #include "precomp.h" #pragma warning(push) #pragma warning(disable:4201) // unnamed struct/union #include #pragma warning(pop) #pragma warning( push ) #pragma warning( disable:4127 ) #include #include "Tunnel.h" #include "Switch.h" #include "Vport.h" #include "Event.h" #include "User.h" #include "Vxlan.h" #include "PacketIO.h" #include "NetProto.h" #include "Flow.h" extern POVS_SWITCH_CONTEXT gOvsSwitchContext; static NTSTATUS OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl, OVS_TUNNEL_PENDED_PACKET *packet); VOID OvsAcquireDatapathRead(OVS_DATAPATH *datapath, LOCK_STATE_EX *lockState, BOOLEAN dispatch); VOID OvsAcquireDatapathWrite(OVS_DATAPATH *datapath, LOCK_STATE_EX *lockState, BOOLEAN dispatch); VOID OvsReleaseDatapath(OVS_DATAPATH *datapath, LOCK_STATE_EX *lockState); NTSTATUS OvsTunnelNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType, const GUID *filterKey, const FWPS_FILTER *filter) { UNREFERENCED_PARAMETER(notifyType); UNREFERENCED_PARAMETER(filterKey); UNREFERENCED_PARAMETER(filter); return STATUS_SUCCESS; } static NTSTATUS OvsTunnelAnalyzePacket(OVS_TUNNEL_PENDED_PACKET *packet) { NTSTATUS status = STATUS_SUCCESS; UINT32 packetLength = 0; ULONG bytesCopied = 0; NET_BUFFER_LIST *copiedNBL = NULL; NET_BUFFER *netBuffer; NDIS_STATUS ndisStatus; /* * For inbound net buffer list, we can assume it contains only one * net buffer (unless it was an re-assembeled fragments). in both cases * the first net buffer should include all headers, we assert if the retreat fails */ netBuffer = NET_BUFFER_LIST_FIRST_NB(packet->netBufferList); /* Drop the packet from the host stack */ packet->classifyOut->actionType = FWP_ACTION_BLOCK; packet->classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE; /* Adjust the net buffer list offset to the start of the IP header */ ndisStatus = NdisRetreatNetBufferDataStart(netBuffer, packet->ipHeaderSize + packet->transportHeaderSize, 0, NULL); ASSERT(ndisStatus == NDIS_STATUS_SUCCESS); /* Single NBL element for WFP */ ASSERT(packet->netBufferList->Next == NULL); /* Note that the copy will inherit the original net buffer list's offset */ packetLength = NET_BUFFER_DATA_LENGTH(netBuffer); copiedNBL = OvsAllocateVariableSizeNBL(gOvsSwitchContext, packetLength, OVS_DEFAULT_HEADROOM_SIZE); if (copiedNBL == NULL) { goto analyzeDone; } status = NdisCopyFromNetBufferToNetBuffer(NET_BUFFER_LIST_FIRST_NB(copiedNBL), 0, packetLength, netBuffer, 0, &bytesCopied); if (status != NDIS_STATUS_SUCCESS || packetLength != bytesCopied) { goto analyzeFreeNBL; } status = OvsInjectPacketThroughActions(copiedNBL, packet); goto analyzeDone; /* Undo the adjustment on the original net buffer list */ analyzeFreeNBL: OvsCompleteNBL(gOvsSwitchContext, copiedNBL, TRUE); analyzeDone: NdisAdvanceNetBufferDataStart(netBuffer, packet->transportHeaderSize + packet->ipHeaderSize, FALSE, NULL); return status; } /* * -------------------------------------------------------------------------- * This is the classifyFn function of the datagram-data callout. It * allocates a packet structure to store the classify and meta data and * it references the net buffer list for out-of-band modification and * re-injection. The packet structure will be queued to the global packet * queue. The worker thread will then be signaled, if idle, to process * the queue. * -------------------------------------------------------------------------- */ VOID OvsTunnelClassify(const FWPS_INCOMING_VALUES *inFixedValues, const FWPS_INCOMING_METADATA_VALUES *inMetaValues, VOID *layerData, const VOID *classifyContext, const FWPS_FILTER *filter, UINT64 flowContext, FWPS_CLASSIFY_OUT *classifyOut) { OVS_TUNNEL_PENDED_PACKET packetStorage; OVS_TUNNEL_PENDED_PACKET *packet = &packetStorage; FWP_DIRECTION direction; UNREFERENCED_PARAMETER(classifyContext); UNREFERENCED_PARAMETER(filter); UNREFERENCED_PARAMETER(flowContext); ASSERT(layerData != NULL); /* We don't have the necessary right to alter the packet flow */ if ((classifyOut->rights & FWPS_RIGHT_ACTION_WRITE) == 0) { /* XXX TBD revisit protect against other filters owning this packet */ ASSERT(FALSE); goto Exit; } RtlZeroMemory(packet, sizeof(OVS_TUNNEL_PENDED_PACKET)); /* classifyOut cannot be accessed from a different thread context */ packet->classifyOut = classifyOut; if (inFixedValues->layerId == FWPS_LAYER_DATAGRAM_DATA_V4) { direction = inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_DIRECTION].\ value.uint32; } else { ASSERT(inFixedValues->layerId == FWPS_LAYER_DATAGRAM_DATA_V6); direction = inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V6_DIRECTION].\ value.uint32; } packet->netBufferList = layerData; ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, FWPS_METADATA_FIELD_COMPARTMENT_ID)); ASSERT(direction == FWP_DIRECTION_INBOUND); ASSERT(FWPS_IS_METADATA_FIELD_PRESENT( inMetaValues, FWPS_METADATA_FIELD_IP_HEADER_SIZE)); ASSERT(FWPS_IS_METADATA_FIELD_PRESENT( inMetaValues, FWPS_METADATA_FIELD_TRANSPORT_HEADER_SIZE)); packet->ipHeaderSize = inMetaValues->ipHeaderSize; packet->transportHeaderSize = inMetaValues->transportHeaderSize; ASSERT(inFixedValues->incomingValue[FWPS_FIELD_DATAGRAM_DATA_V4_IP_PROTOCOL].value.uint8 == IPPROTO_UDP ); OvsTunnelAnalyzePacket(packet); Exit: ; } static NTSTATUS OvsInjectPacketThroughActions(PNET_BUFFER_LIST pNbl, OVS_TUNNEL_PENDED_PACKET *packet) { NTSTATUS status = STATUS_SUCCESS; OvsIPv4TunnelKey tunnelKey; NET_BUFFER *pNb; ULONG sendCompleteFlags = 0; BOOLEAN dispatch; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; LOCK_STATE_EX lockState, dpLockState; LIST_ENTRY missedPackets; OvsCompletionList completionList; KIRQL irql; ULONG SendFlags = NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP; OVS_DATAPATH *datapath = NULL; ASSERT(gOvsSwitchContext); datapath = &gOvsSwitchContext->datapath; /* Fill the tunnel key */ status = OvsSlowPathDecapVxlan(pNbl, &tunnelKey); if(!NT_SUCCESS(status)) { goto dropit; } pNb = NET_BUFFER_LIST_FIRST_NB(pNbl); NdisAdvanceNetBufferDataStart(pNb, packet->transportHeaderSize + packet->ipHeaderSize + sizeof(VXLANHdr), FALSE, NULL); /* Most likely (always) dispatch irql */ irql = KeGetCurrentIrql(); /* dispatch is used for datapath lock as well */ dispatch = (irql == DISPATCH_LEVEL) ? NDIS_RWL_AT_DISPATCH_LEVEL : 0; if (dispatch) { sendCompleteFlags |= NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL; } InitializeListHead(&missedPackets); OvsInitCompletionList(&completionList, gOvsSwitchContext, sendCompleteFlags); { POVS_VPORT_ENTRY vport; UINT32 portNo; OVS_PACKET_HDR_INFO layers; OvsFlowKey key; UINT64 hash; PNET_BUFFER curNb; OvsFlow *flow; fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(pNbl); /* * XXX WFP packets contain a single NBL structure. * Reassembeled packet "may" have multiple NBs, however, a simple test shows * that the packet still has a single NB (after reassemble) * We still need to check if the Ethernet header of the innet packet is in a single MD */ curNb = NET_BUFFER_LIST_FIRST_NB(pNbl); ASSERT(curNb->Next == NULL); NdisAcquireRWLockRead(gOvsSwitchContext->dispatchLock, &lockState, dispatch); /* Lock the flowtable for the duration of accessing the flow */ OvsAcquireDatapathRead(datapath, &dpLockState, NDIS_RWL_AT_DISPATCH_LEVEL); SendFlags |= NDIS_SEND_FLAGS_DISPATCH_LEVEL; vport = OvsFindTunnelVportByDstPort(gOvsSwitchContext, htons(tunnelKey.dst_port), OVS_VPORT_TYPE_VXLAN); if (vport == NULL){ status = STATUS_UNSUCCESSFUL; goto unlockAndDrop; } ASSERT(vport->ovsType == OVS_VPORT_TYPE_VXLAN); portNo = vport->portNo; status = OvsExtractFlow(pNbl, portNo, &key, &layers, &tunnelKey); if (status != NDIS_STATUS_SUCCESS) { goto unlockAndDrop; } flow = OvsLookupFlow(datapath, &key, &hash, FALSE); if (flow) { OvsFlowUsed(flow, pNbl, &layers); datapath->hits++; OvsActionsExecute(gOvsSwitchContext, &completionList, pNbl, portNo, SendFlags, &key, &hash, &layers, flow->actions, flow->actionsLen); OvsReleaseDatapath(datapath, &dpLockState); } else { POVS_PACKET_QUEUE_ELEM elem; datapath->misses++; elem = OvsCreateQueueNlPacket(NULL, 0, OVS_PACKET_CMD_MISS, vport, &key, pNbl, curNb, TRUE, &layers); if (elem) { /* Complete the packet since it was copied to user buffer. */ InsertTailList(&missedPackets, &elem->link); OvsQueuePackets(&missedPackets, 1); } else { status = STATUS_INSUFFICIENT_RESOURCES; } goto unlockAndDrop; } NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); } return status; unlockAndDrop: OvsReleaseDatapath(datapath, &dpLockState); NdisReleaseRWLock(gOvsSwitchContext->dispatchLock, &lockState); dropit: pNbl = OvsCompleteNBL(gOvsSwitchContext, pNbl, TRUE); ASSERT(pNbl == NULL); return status; } #pragma warning(pop) openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/PacketIO.h0000644000000000000000000000013212631676262022262 xustar0030 mtime=1449622706.966439188 30 atime=1456592667.311090405 30 ctime=1456594660.209289493 openvswitch-2.5.0/datapath-windows/ovsext/PacketIO.h0000664000175000017500000000440212631676262023752 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __PACKETIO_H_ #define __PACKETIO_H_ 1 typedef union _OVS_PACKET_HDR_INFO OVS_PACKET_HDR_INFO; /* * Data structures and utility functions to help manage a list of packets to be * completed (dropped). */ typedef struct OvsCompletionList { PNET_BUFFER_LIST dropNbl; PNET_BUFFER_LIST *dropNblNext; POVS_SWITCH_CONTEXT switchContext; ULONG sendCompleteFlags; } OvsCompletionList; VOID OvsInitCompletionList(OvsCompletionList *completionList, POVS_SWITCH_CONTEXT switchContext, ULONG sendCompleteFlags); VOID OvsAddPktCompletionList(OvsCompletionList *completionList, BOOLEAN incoming, NDIS_SWITCH_PORT_ID sourcePort, PNET_BUFFER_LIST netBufferList, UINT32 netBufferListCount, PNDIS_STRING filterReason); /* * Functions related to packet processing. */ VOID OvsSendNBLIngress(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST netBufferLists, ULONG sendFlags); NDIS_STATUS OvsActionsExecute(POVS_SWITCH_CONTEXT switchContext, OvsCompletionList *completionList, PNET_BUFFER_LIST curNbl, UINT32 srcVportNo, ULONG sendFlags, OvsFlowKey *key, UINT64 *hash, OVS_PACKET_HDR_INFO *layers, const PNL_ATTR actions, int actionsLen); VOID OvsLookupFlowOutput(POVS_SWITCH_CONTEXT switchContext, VOID *compList, PNET_BUFFER_LIST curNbl); #endif /* __PACKETIO_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/TunnelIntf.h0000644000000000000000000000013112631676262022710 xustar0029 mtime=1449622706.98243975 30 atime=1456592667.315090569 30 ctime=1456594660.221289997 openvswitch-2.5.0/datapath-windows/ovsext/TunnelIntf.h0000664000175000017500000000306312631676262024403 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __TUNNEL_INTF_H_ #define __TUNNEL_INTF_H_ 1 typedef VOID(*PFNTunnelVportPendingOp)(PVOID context, NTSTATUS status, UINT32 *replyLen); /* Tunnel callout driver load/unload functions */ NTSTATUS OvsInitTunnelFilter(PDRIVER_OBJECT driverObject, PVOID deviceObject); VOID OvsUninitTunnelFilter(PDRIVER_OBJECT driverObject); VOID OvsRegisterSystemProvider(PVOID deviceObject); VOID OvsUnregisterSystemProvider(); NTSTATUS OvsTunnelFilterCreate(PIRP irp, UINT16 filterPort, UINT64 *filterID, PFNTunnelVportPendingOp callback, PVOID context); NTSTATUS OvsTunnelFilterDelete(PIRP irp, UINT64 filterID, PFNTunnelVportPendingOp callback, PVOID context); #endif /* __TUNNEL_INTF_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/DpInternal.h0000644000000000000000000000013212664352753022665 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.177288147 openvswitch-2.5.0/datapath-windows/ovsext/DpInternal.h0000664000175000017500000002217012664352753024357 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __DP_INTERNAL_H_ #define __DP_INTERNAL_H_ 1 #include #define IFNAMSIZ IF_NAMESIZE #include "../ovsext/Netlink/Netlink.h" #define OVS_DP_NUMBER ((uint32_t) 0) typedef __declspec(align(8)) uint64_t Ovs64AlignedU64; typedef __declspec(align(8)) ovs_be64 Ovs64AlignedBe64; #pragma pack(push, 1) #define OVS_MAX_PORT_NAME_LENGTH IFNAMSIZ typedef struct _OVS_VPORT_GET { uint32_t dpNo; uint32_t portNo; char name[OVS_MAX_PORT_NAME_LENGTH]; } OVS_VPORT_GET, *POVS_VPORT_GET; #define OVS_MAX_VM_UUID_LEN 128 #define OVS_MAX_VIF_UUID_LEN 128 typedef struct _OVS_VPORT_EXT_INFO { uint32_t dpNo; uint32_t portNo; uint8_t macAddress[ETH_ADDR_LEN]; uint8_t permMACAddress[ETH_ADDR_LEN]; uint8_t vmMACAddress[ETH_ADDR_LEN]; uint16_t nicIndex; uint32_t portId; uint32_t type; uint32_t mtu; char name[OVS_MAX_PORT_NAME_LENGTH]; uint32_t status; char vmUUID[OVS_MAX_VM_UUID_LEN]; char vifUUID[OVS_MAX_VIF_UUID_LEN]; } OVS_VPORT_EXT_INFO, *POVS_VPORT_EXT_INFO; /* Flows. */ #define OVSWIN_VLAN_CFI 0x1000 /* Used for OvsFlowKey's dlType member for frames that have no Ethernet type, * that is, pure 802.2 frames. */ #define OVSWIN_DL_TYPE_NONE 0x5ff typedef struct L4Key { ovs_be16 tpSrc; /* TCP/UDP/SCTP source port. */ ovs_be16 tpDst; /* TCP/UDP/SCTP destination port. */ } L4Key; typedef struct Ipkey { ovs_be32 nwSrc; /* IPv4 source address. */ ovs_be32 nwDst; /* IPv4 destination address. */ uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */ uint8_t nwTos; /* IP ToS (including DSCP and ECN). */ uint8_t nwTtl; /* IP TTL/Hop Limit. */ uint8_t nwFrag; /* FLOW_FRAG_* flags. */ L4Key l4; } IpKey; /* Size of 16 byte. */ typedef struct ArpKey { ovs_be32 nwSrc; /* IPv4 source address. */ ovs_be32 nwDst; /* IPv4 destination address. */ uint8_t arpSha[6]; /* ARP/ND source hardware address. */ uint8_t arpTha[6]; /* ARP/ND target hardware address. */ uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */ uint8_t pad[3]; } ArpKey; /* Size of 24 byte. */ typedef struct Ipv6Key { struct in6_addr ipv6Src; /* IPv6 source address. */ struct in6_addr ipv6Dst; /* IPv6 destination address. */ ovs_be32 ipv6Label; /* IPv6 flow label. */ uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */ uint8_t nwTos; /* IP ToS (including DSCP and ECN). */ uint8_t nwTtl; /* IP TTL/Hop Limit. */ uint8_t nwFrag; /* FLOW_FRAG_* flags. */ L4Key l4; uint32_t pad; } Ipv6Key; /* Size of 48 byte. */ typedef struct Icmp6Key { struct in6_addr ipv6Src; /* IPv6 source address. */ struct in6_addr ipv6Dst; /* IPv6 destination address. */ ovs_be32 ipv6Label; /* IPv6 flow label. */ uint8_t nwProto; /* IP protocol or low 8 bits of ARP opcode. */ uint8_t nwTos; /* IP ToS (including DSCP and ECN). */ uint8_t nwTtl; /* IP TTL/Hop Limit. */ uint8_t nwFrag; /* FLOW_FRAG_* flags. */ L4Key l4; uint8_t arpSha[6]; /* ARP/ND source hardware address. */ uint8_t arpTha[6]; /* ARP/ND target hardware address. */ struct in6_addr ndTarget; /* IPv6 neighbor discovery (ND) target. */ } Icmp6Key; /* Size of 72 byte. */ typedef struct L2Key { uint32_t inPort; /* Port number of input port. */ union { struct { uint16_t offset; uint16_t keyLen; }; uint32_t val; }; uint8_t dlSrc[6]; /* Ethernet source address. */ uint8_t dlDst[6]; /* Ethernet destination address. */ ovs_be16 vlanTci; /* If 802.1Q, TCI | VLAN_CFI; otherwise 0. */ ovs_be16 dlType; /* Ethernet frame type. */ } L2Key; /* Size of 24 byte. */ /* Number of packet attributes required to store OVS tunnel key. */ #define NUM_PKT_ATTR_REQUIRED 3 typedef union OvsIPv4TunnelKey { struct { ovs_be32 dst; ovs_be32 src; ovs_be64 tunnelId; uint16_t flags; uint8_t tos; uint8_t ttl; union { uint32_t pad; struct { ovs_be16 dst_port; uint16_t flow_hash; }; }; }; uint64_t attr[NUM_PKT_ATTR_REQUIRED]; } OvsIPv4TunnelKey; typedef __declspec(align(8)) struct OvsFlowKey { OvsIPv4TunnelKey tunKey; /* 24 bytes */ L2Key l2; /* 24 bytes */ union { IpKey ipKey; /* size 16 */ ArpKey arpKey; /* size 24 */ Ipv6Key ipv6Key; /* size 48 */ Icmp6Key icmp6Key; /* size 72 */ }; } OvsFlowKey; #define OVS_WIN_TUNNEL_KEY_SIZE (sizeof (OvsIPv4TunnelKey)) #define OVS_L2_KEY_SIZE (sizeof (L2Key)) #define OVS_IP_KEY_SIZE (sizeof (IpKey)) #define OVS_IPV6_KEY_SIZE (sizeof (Ipv6Key)) #define OVS_ARP_KEY_SIZE (sizeof (ArpKey)) #define OVS_ICMPV6_KEY_SIZE (sizeof (Icmp6Key)) typedef struct OvsFlowStats { Ovs64AlignedU64 packetCount; Ovs64AlignedU64 byteCount; uint32_t used; uint8_t tcpFlags; } OvsFlowStats; typedef struct OvsFlowInfo { OvsFlowKey key; struct OvsFlowStats stats; uint32_t actionsLen; PNL_ATTR actions; } OvsFlowInfo; enum GetFlags { FLOW_GET_KEY = 0x00000001, FLOW_GET_STATS = 0x00000010, FLOW_GET_ACTIONS = 0x00000100, }; typedef struct OvsFlowDumpInput { uint32_t dpNo; uint32_t position[2]; /* Offset hint to the start of flow dump. */ /* 0 - index of the hash table. * 1 - nth element in the hash table index. */ uint32_t getFlags; /* Information to get in addition to keys. */ uint32_t actionsLen; } OvsFlowDumpInput; typedef struct OvsFlowDumpOutput { /* Hint for the next flow dump operation. */ uint32_t position[2]; /* #flows (currently 0 or 1). In case the buffer is too small to output all * actions, this field indicates actual size needed to dump all actions. */ uint32_t n; OvsFlowInfo flow; } OvsFlowDumpOutput; typedef struct OvsFlowGetInput { uint32_t dpNo; OvsFlowKey key; uint32_t getFlags; /* Information to get in addition to keys. */ uint32_t actionsLen; /* Sizeof of buffer for actions. */ } OvsFlowGetInput; typedef struct OvsFlowGetOutput { OvsFlowInfo info; /* Variable length. */ } OvsFlowGetOutput; typedef enum OvsFlowPutFlags { OVSWIN_FLOW_PUT_CREATE = 1 << 0, OVSWIN_FLOW_PUT_MODIFY = 1 << 1, OVSWIN_FLOW_PUT_DELETE = 1 << 2, OVSWIN_FLOW_PUT_CLEAR = 1 << 3 } OvsFlowPutFlags; typedef struct OvsFlowPut { uint32_t dpNo; uint32_t actionsLen; OvsFlowKey key; uint32_t flags; PNL_ATTR actions; } OvsFlowPut; #define OVS_MIN_PACKET_SIZE 60 typedef struct _OVS_PACKET_INFO { uint32_t totalLen; uint32_t userDataLen; uint32_t packetLen; uint32_t queue; uint32_t inPort; uint32_t cmd; OvsIPv4TunnelKey tunnelKey; uint8_t *payload; /* Includes user data defined as chain of netlink attributes followed by the * packet data. */ uint8_t data[0]; } OVS_PACKET_INFO, *POVS_PACKET_INFO; typedef struct OvsPacketExecute { uint32_t dpNo; uint32_t inPort; uint32_t packetLen; uint32_t actionsLen; PCHAR packetBuf; PNL_ATTR actions; } OvsPacketExecute; typedef struct _OVS_EVENT_SUBSCRIBE { uint32_t cookie; uint32_t dpNo; uint32_t subscribe; uint32_t mask; } OVS_EVENT_SUBSCRIBE, *POVS_EVENT_SUBSCRIBE; typedef struct _OVS_EVENT_POLL { uint32_t cookie; uint32_t dpNo; } OVS_EVENT_POLL, *POVS_EVENT_POLL; enum { OVS_EVENT_CONNECT = ((uint32_t)0x1 << 0), OVS_EVENT_DISCONNECT = ((uint32_t)0x1 << 1), OVS_EVENT_LINK_UP = ((uint32_t)0x1 << 2), OVS_EVENT_LINK_DOWN = ((uint32_t)0x1 << 3), OVS_EVENT_MAC_CHANGE = ((uint32_t)0x1 << 4), OVS_EVENT_MTU_CHANGE = ((uint32_t)0x1 << 5), OVS_EVENT_MASK_ALL = 0x3f, }; typedef struct _OVS_EVENT_ENTRY { UINT32 portNo; OVS_VPORT_TYPE ovsType; UINT32 upcallPid; CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH]; UINT32 type; } OVS_EVENT_ENTRY, *POVS_EVENT_ENTRY; typedef struct _OVS_EVENT_STATUS { uint32_t numberEntries; OVS_EVENT_ENTRY eventEntries[0]; } OVS_EVENT_STATUS, *POVS_EVENT_STATUS; #pragma pack(pop) #endif /* __DP_INTERNAL_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/BufferMgmt.h0000644000000000000000000000013212664352753022663 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.170815194 30 ctime=1456594660.169287811 openvswitch-2.5.0/datapath-windows/ovsext/BufferMgmt.h0000664000175000017500000001172712664352753024363 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __BUFFER_MGMT_H_ #define __BUFFER_MGMT_H_ 1 #define MEM_ALIGN MEMORY_ALLOCATION_ALIGNMENT #define MEM_ALIGN_SIZE(_x) ((MEM_ALIGN - 1 + (_x))/MEM_ALIGN * MEM_ALIGN) #define OVS_CTX_MAGIC 0xabcd #define OVS_DEFAULT_NBL_CONTEXT_SIZE MEM_ALIGN_SIZE(64) #define OVS_DEFAULT_NBL_CONTEXT_FILL \ (OVS_DEFAULT_NBL_CONTEXT_SIZE - sizeof (OVS_BUFFER_CONTEXT)) #define OVS_DEFAULT_DATA_SIZE 256 #define OVS_DEFAULT_HEADROOM_SIZE 128 #define OVS_FIX_NBL_DATA_SIZE (OVS_DEFAULT_DATA_SIZE + OVS_DEFAULT_HEADROOM_SIZE) /* Default we copy 18 bytes, to make sure ethernet header and vlan is in * continuous buffer */ #define OVS_DEFAULT_COPY_SIZE 18 enum { OVS_BUFFER_NEED_COMPLETE = BIT16(0), OVS_BUFFER_PRIVATE_MDL = BIT16(1), OVS_BUFFER_PRIVATE_DATA = BIT16(2), OVS_BUFFER_PRIVATE_NET_BUFFER = BIT16(3), OVS_BUFFER_PRIVATE_FORWARD_CONTEXT = BIT16(4), OVS_BUFFER_PRIVATE_CONTEXT = BIT16(5), OVS_BUFFER_FROM_FIX_SIZE_POOL = BIT16(6), OVS_BUFFER_FROM_ZERO_SIZE_POOL = BIT16(7), OVS_BUFFER_FROM_NBL_ONLY_POOL = BIT16(8), OVS_BUFFER_RECV_BUFFER = BIT16(9), OVS_BUFFER_SEND_BUFFER = BIT16(10), OVS_BUFFER_FRAGMENT = BIT16(11), }; typedef union _OVS_BUFFER_CONTEXT { struct { UINT16 magic; UINT16 flags; UINT32 srcPortNo; UINT32 refCount; union { UINT32 origDataLength; UINT32 dataOffsetDelta; }; }; UINT64 value[MEM_ALIGN_SIZE(16) >> 3]; } OVS_BUFFER_CONTEXT, *POVS_BUFFER_CONTEXT; typedef struct _OVS_NBL_POOL { NDIS_SWITCH_CONTEXT ndisContext; NDIS_HANDLE ndisHandle; NDIS_HANDLE fixSizePool; // data size of 256 NDIS_HANDLE zeroSizePool; // no data, NBL + NB + Context NDIS_HANDLE nblOnlyPool; // NBL + context for clone NDIS_HANDLE nbPool; // NB for clone #ifdef DBG LONG fixNBLCount; LONG zeroNBLCount; LONG nblOnlyCount; LONG nbCount; LONG sysNBLCount; LONG fragNBLCount; #endif } OVS_NBL_POOL, *POVS_NBL_POOL; NDIS_STATUS OvsInitBufferPool(PVOID context); VOID OvsCleanupBufferPool(PVOID context); PNET_BUFFER_LIST OvsAllocateFixSizeNBL(PVOID context, UINT32 size, UINT32 headRoom); PNET_BUFFER_LIST OvsAllocateVariableSizeNBL(PVOID context, UINT32 size, UINT32 headRoom); POVS_BUFFER_CONTEXT OvsInitExternalNBLContext(PVOID context, PNET_BUFFER_LIST nbl, BOOLEAN isRecv); PNET_BUFFER_LIST OvsPartialCopyNBL(PVOID context, PNET_BUFFER_LIST nbl, UINT32 copySize, UINT32 headRoom, BOOLEAN copyNblInfo); PNET_BUFFER_LIST OvsPartialCopyToMultipleNBLs(PVOID context, PNET_BUFFER_LIST nbl, UINT32 copySize, UINT32 headRoom, BOOLEAN copyNblInfo); PNET_BUFFER_LIST OvsFullCopyNBL(PVOID context, PNET_BUFFER_LIST nbl, UINT32 headRoom, BOOLEAN copyNblInfo); PNET_BUFFER_LIST OvsTcpSegmentNBL(PVOID context, PNET_BUFFER_LIST nbl, POVS_PACKET_HDR_INFO hdrInfo, UINT32 MSS, UINT32 headRoom); PNET_BUFFER_LIST OvsAllocateNBLFromBuffer(PVOID context, PVOID buffer, ULONG length); PNET_BUFFER_LIST OvsFullCopyToMultipleNBLs(PVOID context, PNET_BUFFER_LIST nbl, UINT32 headRoom, BOOLEAN copyNblInfo); PNET_BUFFER_LIST OvsCompleteNBL(PVOID context, PNET_BUFFER_LIST nbl, BOOLEAN updateRef); NDIS_STATUS OvsSetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 portNo); NDIS_STATUS OvsGetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 *portNo); #endif /* __BUFFER_MGMT_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Vxlan.c0000644000000000000000000000013212664352753021710 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594660.229290333 openvswitch-2.5.0/datapath-windows/ovsext/Vxlan.c0000664000175000017500000005346212664352753023412 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Atomic.h" #include "NetProto.h" #include "Switch.h" #include "Vport.h" #include "Flow.h" #include "Vxlan.h" #include "IpHelper.h" #include "Checksum.h" #include "User.h" #include "PacketIO.h" #include "Flow.h" #include "PacketParser.h" #pragma warning( push ) #pragma warning( disable:4127 ) #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_VXLAN #include "Debug.h" /* Helper macro to check if a VXLAN ID is valid. */ #define VXLAN_ID_IS_VALID(vxlanID) (0 < (vxlanID) && (vxlanID) <= 0xffffff) #define VXLAN_TUNNELID_TO_VNI(_tID) (UINT32)(((UINT64)(_tID)) >> 40) #define VXLAN_VNI_TO_TUNNELID(_vni) (((UINT64)(_vni)) << 40) #define IP_DF_NBO 0x0040 #define VXLAN_DEFAULT_TTL 64 #define VXLAN_MULTICAST_TTL 64 #define VXLAN_DEFAULT_INSTANCE_ID 1 /* Move to a header file */ extern POVS_SWITCH_CONTEXT gOvsSwitchContext; /* *---------------------------------------------------------------------------- * This function verifies if the VXLAN tunnel already exists, in order to * avoid sending a duplicate request to the WFP base filtering engine. *---------------------------------------------------------------------------- */ static BOOLEAN OvsIsTunnelFilterCreated(POVS_SWITCH_CONTEXT switchContext, UINT16 udpPortDest) { for (UINT hash = 0; hash < OVS_MAX_VPORT_ARRAY_SIZE; hash++) { PLIST_ENTRY head, link, next; head = &(switchContext->portNoHashArray[hash & OVS_VPORT_MASK]); LIST_FORALL_SAFE(head, link, next) { POVS_VPORT_ENTRY vport = NULL; POVS_VXLAN_VPORT vxlanPort = NULL; vport = CONTAINING_RECORD(link, OVS_VPORT_ENTRY, portNoLink); vxlanPort = (POVS_VXLAN_VPORT)vport->priv; if (vxlanPort) { if ((udpPortDest == vxlanPort->dstPort)) { /* The VXLAN tunnel was already created. */ return TRUE; } } } } return FALSE; } /* *---------------------------------------------------------------------------- * This function allocates and initializes the OVS_VXLAN_VPORT. The function * also creates a WFP tunnel filter for the necessary destination port. The * tunnel filter create request is passed to the tunnel filter threads that * will complete the request at a later time when IRQL is lowered to * PASSIVE_LEVEL. * * udpDestPort: the vxlan is set as payload to a udp frame. If the destination * port of an udp frame is udpDestPort, we understand it to be vxlan. *---------------------------------------------------------------------------- */ NTSTATUS OvsInitVxlanTunnel(PIRP irp, POVS_VPORT_ENTRY vport, UINT16 udpDestPort, PFNTunnelVportPendingOp callback, PVOID tunnelContext) { NTSTATUS status = STATUS_SUCCESS; POVS_VXLAN_VPORT vxlanPort = NULL; vxlanPort = OvsAllocateMemoryWithTag(sizeof (*vxlanPort), OVS_VXLAN_POOL_TAG); if (vxlanPort == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(vxlanPort, sizeof(*vxlanPort)); vxlanPort->dstPort = udpDestPort; vport->priv = (PVOID)vxlanPort; if (!OvsIsTunnelFilterCreated(gOvsSwitchContext, udpDestPort)) { status = OvsTunnelFilterCreate(irp, udpDestPort, &vxlanPort->filterID, callback, tunnelContext); } else { status = STATUS_OBJECT_NAME_EXISTS; } return status; } /* *---------------------------------------------------------------------------- * This function releases the OVS_VXLAN_VPORT. The function also deletes the * WFP tunnel filter previously created. The tunnel filter delete request is * passed to the tunnel filter threads that will complete the request at a * later time when IRQL is lowered to PASSIVE_LEVEL. *---------------------------------------------------------------------------- */ NTSTATUS OvsCleanupVxlanTunnel(PIRP irp, POVS_VPORT_ENTRY vport, PFNTunnelVportPendingOp callback, PVOID tunnelContext) { NTSTATUS status = STATUS_SUCCESS; POVS_VXLAN_VPORT vxlanPort = NULL; if (vport->ovsType != OVS_VPORT_TYPE_VXLAN || vport->priv == NULL) { return STATUS_SUCCESS; } vxlanPort = (POVS_VXLAN_VPORT)vport->priv; if (vxlanPort->filterID != 0) { status = OvsTunnelFilterDelete(irp, vxlanPort->filterID, callback, tunnelContext); } else { OvsFreeMemoryWithTag(vport->priv, OVS_VXLAN_POOL_TAG); vport->priv = NULL; } return status; } /* *---------------------------------------------------------------------------- * OvsDoEncapVxlan * Encapsulates the packet. *---------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsDoEncapVxlan(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, POVS_FWD_INFO fwdInfo, POVS_PACKET_HDR_INFO layers, POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST *newNbl) { NDIS_STATUS status; PNET_BUFFER curNb; PMDL curMdl; PUINT8 bufferStart; EthHdr *ethHdr; IPHdr *ipHdr; UDPHdr *udpHdr; VXLANHdr *vxlanHdr; POVS_VXLAN_VPORT vportVxlan; UINT32 headRoom = OvsGetVxlanTunHdrSize(); UINT32 packetLength; ULONG mss = 0; /* * XXX: the assumption currently is that the NBL is owned by OVS, and * headroom has already been allocated as part of allocating the NBL and * MDL. */ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); packetLength = NET_BUFFER_DATA_LENGTH(curNb); if (layers->isTcp) { NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; tsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpLargeSendNetBufferListInfo); switch (tsoInfo.Transmit.Type) { case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: mss = tsoInfo.LsoV1Transmit.MSS; break; case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: mss = tsoInfo.LsoV2Transmit.MSS; break; default: OVS_LOG_ERROR("Unknown LSO transmit type:%d", tsoInfo.Transmit.Type); } OVS_LOG_TRACE("MSS %u packet len %u", mss, packetLength); if (mss) { OVS_LOG_TRACE("l4Offset %d", layers->l4Offset); *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers, mss, headRoom); if (*newNbl == NULL) { OVS_LOG_ERROR("Unable to segment NBL"); return NDIS_STATUS_FAILURE; } /* Clear out LSO flags after this point */ NET_BUFFER_LIST_INFO(*newNbl, TcpLargeSendNetBufferListInfo) = 0; } } vportVxlan = (POVS_VXLAN_VPORT) GetOvsVportPriv(vport); ASSERT(vportVxlan); /* If we didn't split the packet above, make a copy now */ if (*newNbl == NULL) { *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom, FALSE /*NBL info*/); if (*newNbl == NULL) { OVS_LOG_ERROR("Unable to copy NBL"); return NDIS_STATUS_FAILURE; } /* * To this point we do not have VXLAN offloading. * Apply defined checksums */ curNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); curMdl = NET_BUFFER_CURRENT_MDL(curNb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); if (!bufferStart) { status = NDIS_STATUS_RESOURCES; goto ret_error; } NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); if (layers->isIPv4) { IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); if (csumInfo.Transmit.IpHeaderChecksum) { ip->check = 0; ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); } if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, IPPROTO_TCP, csumLength); tcp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, IPPROTO_UDP, csumLength); udp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } } else if (layers->isIPv6) { IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, (UINT32 *) &ip->daddr, IPPROTO_TCP, csumLength); tcp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, (UINT32 *) &ip->daddr, IPPROTO_UDP, csumLength); udp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } } /* Clear out TcpIpChecksumNetBufferListInfo flag */ NET_BUFFER_LIST_INFO(*newNbl, TcpIpChecksumNetBufferListInfo) = 0; } curNbl = *newNbl; for (curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curNb != NULL; curNb = curNb->Next) { status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL); if (status != NDIS_STATUS_SUCCESS) { goto ret_error; } curMdl = NET_BUFFER_CURRENT_MDL(curNb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); if (!bufferStart) { status = NDIS_STATUS_RESOURCES; goto ret_error; } bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); if (NET_BUFFER_NEXT_NB(curNb)) { OVS_LOG_TRACE("nb length %u next %u", NET_BUFFER_DATA_LENGTH(curNb), NET_BUFFER_DATA_LENGTH(curNb->Next)); } /* L2 header */ ethHdr = (EthHdr *)bufferStart; ASSERT(((PCHAR)&fwdInfo->dstMacAddr + sizeof fwdInfo->dstMacAddr) == (PCHAR)&fwdInfo->srcMacAddr); NdisMoveMemory(ethHdr->Destination, fwdInfo->dstMacAddr, sizeof ethHdr->Destination + sizeof ethHdr->Source); ethHdr->Type = htons(ETH_TYPE_IPV4); /* IP header */ ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); ipHdr->ihl = sizeof *ipHdr / 4; ipHdr->version = IPPROTO_IPV4; ipHdr->tos = tunKey->tos; ipHdr->tot_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof *ethHdr); ipHdr->id = (uint16)atomic_add64(&vportVxlan->ipId, NET_BUFFER_DATA_LENGTH(curNb)); ipHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ? IP_DF_NBO : 0; ipHdr->ttl = tunKey->ttl ? tunKey->ttl : VXLAN_DEFAULT_TTL; ipHdr->protocol = IPPROTO_UDP; ASSERT(tunKey->dst == fwdInfo->dstIpAddr); ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0); ipHdr->saddr = fwdInfo->srcIpAddr; ipHdr->daddr = fwdInfo->dstIpAddr; ipHdr->check = 0; ipHdr->check = IPChecksum((UINT8 *)ipHdr, sizeof *ipHdr, 0); /* UDP header */ udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr); udpHdr->source = htons(tunKey->flow_hash | MAXINT16); udpHdr->dest = htons(vportVxlan->dstPort); udpHdr->len = htons(NET_BUFFER_DATA_LENGTH(curNb) - headRoom + sizeof *udpHdr + sizeof *vxlanHdr); udpHdr->check = 0; /* VXLAN header */ vxlanHdr = (VXLANHdr *)((PCHAR)udpHdr + sizeof *udpHdr); vxlanHdr->flags1 = 0; vxlanHdr->locallyReplicate = 0; vxlanHdr->flags2 = 0; vxlanHdr->reserved1 = 0; if (tunKey->flags | OVS_TNL_F_KEY) { vxlanHdr->vxlanID = VXLAN_TUNNELID_TO_VNI(tunKey->tunnelId); vxlanHdr->instanceID = 1; } vxlanHdr->reserved2 = 0; } return STATUS_SUCCESS; ret_error: OvsCompleteNBL(switchContext, *newNbl, TRUE); *newNbl = NULL; return status; } /* *---------------------------------------------------------------------------- * OvsEncapVxlan -- * Encapsulates the packet if L2/L3 for destination resolves. Otherwise, * enqueues a callback that does encapsulatation after resolution. *---------------------------------------------------------------------------- */ NDIS_STATUS OvsEncapVxlan(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, PNET_BUFFER_LIST *newNbl) { NTSTATUS status; OVS_FWD_INFO fwdInfo; status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); if (status != STATUS_SUCCESS) { OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); // return NDIS_STATUS_PENDING; /* * XXX: Don't know if the completionList will make any sense when * accessed in the callback. Make sure the caveats are known. * * XXX: This code will work once we are able to grab locks in the * callback. */ return NDIS_STATUS_FAILURE; } return OvsDoEncapVxlan(vport, curNbl, tunKey, &fwdInfo, layers, switchContext, newNbl); } /* *---------------------------------------------------------------------------- * OvsCalculateUDPChecksum * Calculate UDP checksum *---------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsCalculateUDPChecksum(PNET_BUFFER_LIST curNbl, PNET_BUFFER curNb, IPHdr *ipHdr, UDPHdr *udpHdr, UINT32 packetLength) { NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; UINT16 checkSum; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); /* Next check if UDP checksum has been calculated. */ if (!csumInfo.Receive.UdpChecksumSucceeded) { UINT32 l4Payload; checkSum = udpHdr->check; l4Payload = packetLength - sizeof(EthHdr) - ipHdr->ihl * 4; udpHdr->check = 0; udpHdr->check = IPPseudoChecksum((UINT32 *)&ipHdr->saddr, (UINT32 *)&ipHdr->daddr, IPPROTO_UDP, (UINT16)l4Payload); udpHdr->check = CalculateChecksumNB(curNb, (UINT16)l4Payload, sizeof(EthHdr) + ipHdr->ihl * 4); if (checkSum != udpHdr->check) { OVS_LOG_TRACE("UDP checksum incorrect."); return NDIS_STATUS_INVALID_PACKET; } } csumInfo.Receive.UdpChecksumSucceeded = 1; NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = csumInfo.Value; return NDIS_STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsDecapVxlan * Decapsulates to tunnel header in 'curNbl' and puts into 'tunKey'. *---------------------------------------------------------------------------- */ NDIS_STATUS OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, PNET_BUFFER_LIST *newNbl) { PNET_BUFFER curNb; PMDL curMdl; EthHdr *ethHdr; IPHdr *ipHdr; UDPHdr *udpHdr; VXLANHdr *vxlanHdr; UINT32 tunnelSize = 0, packetLength = 0; PUINT8 bufferStart; NDIS_STATUS status; /* Check the length of the UDP payload */ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); packetLength = NET_BUFFER_DATA_LENGTH(curNb); tunnelSize = OvsGetVxlanTunHdrSize(); if (packetLength <= tunnelSize) { return NDIS_STATUS_INVALID_LENGTH; } /* * Create a copy of the NBL so that we have all the headers in one MDL. */ *newNbl = OvsPartialCopyNBL(switchContext, curNbl, tunnelSize + OVS_DEFAULT_COPY_SIZE, 0, TRUE /*copy NBL info */); if (*newNbl == NULL) { return NDIS_STATUS_RESOURCES; } /* XXX: Handle VLAN header. */ curNbl = *newNbl; curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curMdl = NET_BUFFER_CURRENT_MDL(curNb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority) + NET_BUFFER_CURRENT_MDL_OFFSET(curNb); if (!bufferStart) { status = NDIS_STATUS_RESOURCES; goto dropNbl; } ethHdr = (EthHdr *)bufferStart; /* XXX: Handle IP options. */ ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); tunKey->src = ipHdr->saddr; tunKey->dst = ipHdr->daddr; tunKey->tos = ipHdr->tos; tunKey->ttl = ipHdr->ttl; tunKey->pad = 0; udpHdr = (UDPHdr *)((PCHAR)ipHdr + sizeof *ipHdr); /* Validate if NIC has indicated checksum failure. */ status = OvsValidateUDPChecksum(curNbl, udpHdr->check == 0); if (status != NDIS_STATUS_SUCCESS) { goto dropNbl; } /* Calculate and verify UDP checksum if NIC didn't do it. */ if (udpHdr->check != 0) { status = OvsCalculateUDPChecksum(curNbl, curNb, ipHdr, udpHdr, packetLength); if (status != NDIS_STATUS_SUCCESS) { goto dropNbl; } } vxlanHdr = (VXLANHdr *)((PCHAR)udpHdr + sizeof *udpHdr); if (vxlanHdr->instanceID) { tunKey->flags = OVS_TNL_F_KEY; tunKey->tunnelId = VXLAN_VNI_TO_TUNNELID(vxlanHdr->vxlanID); } else { tunKey->flags = 0; tunKey->tunnelId = 0; } /* Clear out the receive flag for the inner packet. */ NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0; NdisAdvanceNetBufferDataStart(curNb, tunnelSize, FALSE, NULL); return NDIS_STATUS_SUCCESS; dropNbl: OvsCompleteNBL(switchContext, *newNbl, TRUE); *newNbl = NULL; return status; } NDIS_STATUS OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet, OvsIPv4TunnelKey *tunnelKey) { NDIS_STATUS status = NDIS_STATUS_FAILURE; UDPHdr udpStorage; const UDPHdr *udp; VXLANHdr *VxlanHeader; VXLANHdr VxlanHeaderBuffer; struct IPHdr ip_storage; const struct IPHdr *nh; OVS_PACKET_HDR_INFO layers; layers.value = 0; do { nh = OvsGetIp(packet, layers.l3Offset, &ip_storage); if (nh) { layers.l4Offset = layers.l3Offset + nh->ihl * 4; } else { break; } /* make sure it's a VXLAN packet */ udp = OvsGetUdp(packet, layers.l4Offset, &udpStorage); if (udp) { layers.l7Offset = layers.l4Offset + sizeof *udp; } else { break; } VxlanHeader = (VXLANHdr *)OvsGetPacketBytes(packet, sizeof(*VxlanHeader), layers.l7Offset, &VxlanHeaderBuffer); if (VxlanHeader) { tunnelKey->src = nh->saddr; tunnelKey->dst = nh->daddr; tunnelKey->ttl = nh->ttl; tunnelKey->tos = nh->tos; if (VxlanHeader->instanceID) { tunnelKey->flags = OVS_TNL_F_KEY; tunnelKey->tunnelId = VXLAN_VNI_TO_TUNNELID(VxlanHeader->vxlanID); } else { tunnelKey->flags = 0; tunnelKey->tunnelId = 0; } } else { break; } status = NDIS_STATUS_SUCCESS; } while(FALSE); return status; } #pragma warning( pop ) openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Flow.h0000644000000000000000000000013212652645507021533 xustar0030 mtime=1454066503.402754588 30 atime=1456592667.311090405 30 ctime=1456594660.189288653 openvswitch-2.5.0/datapath-windows/ovsext/Flow.h0000664000175000017500000000630512652645507023227 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __FLOW_H_ #define __FLOW_H_ 1 #include "precomp.h" #include "Switch.h" #include "User.h" #include "NetProto.h" #include "Datapath.h" typedef struct _OvsFlow { LIST_ENTRY ListEntry; // In Datapath's flowTable. OvsFlowKey key; UINT64 hash; UINT32 actionsLen; UINT8 tcpFlags; UINT64 used; UINT64 packetCount; UINT64 byteCount; UINT32 userActionsLen; // used for flow query UINT32 actionBufferLen; // used for flow reuse NL_ATTR actions[1]; } OvsFlow; typedef struct _OvsLayers { UINT32 l3Ofs; // IPv4, IPv6, ARP, or other L3 header. UINT32 l4Ofs; // TCP, UDP, SCTP, ICMP, ICMPv6, or other L4 header. UINT32 l7Ofs; // L4 protocol's payload. } OvsLayers; extern UINT64 ovsUserTimestampDelta; extern UINT64 ovsTimeIncrementPerTick; NDIS_STATUS OvsDeleteFlowTable(OVS_DATAPATH *datapath); NDIS_STATUS OvsAllocateFlowTable(OVS_DATAPATH *datapath, POVS_SWITCH_CONTEXT switchContext); NDIS_STATUS OvsExtractFlow(const NET_BUFFER_LIST *pkt, UINT32 inPort, OvsFlowKey *flow, POVS_PACKET_HDR_INFO layers, OvsIPv4TunnelKey *tunKey); OvsFlow *OvsLookupFlow(OVS_DATAPATH *datapath, const OvsFlowKey *key, UINT64 *hash, BOOLEAN hashValid); UINT64 OvsHashFlow(const OvsFlowKey *key); VOID OvsFlowUsed(OvsFlow *flow, const NET_BUFFER_LIST *pkt, const POVS_PACKET_HDR_INFO layers); NTSTATUS OvsDumpFlowIoctl(PVOID inputBuffer, UINT32 inputLength, PVOID outputBuffer, UINT32 outputLength, UINT32 *replyLen); NTSTATUS OvsPutFlowIoctl(PVOID inputBuffer, UINT32 inputLength, struct OvsFlowStats *stats); NTSTATUS OvsGetFlowIoctl(PVOID inputBuffer, PVOID outputBuffer); NTSTATUS OvsFlushFlowIoctl(UINT32 dpNo); NTSTATUS OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); NTSTATUS OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); NTSTATUS MapFlowKeyToNlKey(PNL_BUFFER nlBuf, OvsFlowKey *flowKey, UINT16 keyType, UINT16 tunKeyType); NTSTATUS MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, OvsIPv4TunnelKey *tunKey, UINT16 tunKeyType); UINT32 OvsFlowKeyAttrSize(void); UINT32 OvsTunKeyAttrSize(void); /* Flags for tunneling */ #define OVS_TNL_F_DONT_FRAGMENT (1 << 0) #define OVS_TNL_F_CSUM (1 << 1) #define OVS_TNL_F_KEY (1 << 2) #endif /* __FLOW_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Jhash.c0000644000000000000000000000013212631676262021653 xustar0030 mtime=1449622706.954438766 30 atime=1456592667.311090405 30 ctime=1456594660.197288987 openvswitch-2.5.0/datapath-windows/ovsext/Jhash.c0000664000175000017500000000647112631676262023353 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2012, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" static __inline UINT32 GetUnalignedU32(const UINT32 *p_) { const UINT8 *p = (const UINT8 *)p_; return ntohl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); } /* This is the public domain lookup3 hash by Bob Jenkins from * http://burtleburtle.net/bob/c/lookup3.c, modified for style. */ static __inline UINT32 JhashRot(UINT32 x, INT k) { return (x << k) | (x >> (32 - k)); } static __inline VOID JhashMix(UINT32 *a, UINT32 *b, UINT32 *c) { *a -= *c; *a ^= JhashRot(*c, 4); *c += *b; *b -= *a; *b ^= JhashRot(*a, 6); *a += *c; *c -= *b; *c ^= JhashRot(*b, 8); *b += *a; *a -= *c; *a ^= JhashRot(*c, 16); *c += *b; *b -= *a; *b ^= JhashRot(*a, 19); *a += *c; *c -= *b; *c ^= JhashRot(*b, 4); *b += *a; } static __inline VOID JhashFinal(UINT32 *a, UINT32 *b, UINT32 *c) { *c ^= *b; *c -= JhashRot(*b, 14); *a ^= *c; *a -= JhashRot(*c, 11); *b ^= *a; *b -= JhashRot(*a, 25); *c ^= *b; *c -= JhashRot(*b, 16); *a ^= *c; *a -= JhashRot(*c, 4); *b ^= *a; *b -= JhashRot(*a, 14); *c ^= *b; *c -= JhashRot(*b, 24); } /* Returns the Jenkins hash of the 'n' 32-bit words at 'p', starting from * 'basis'. 'p' must be properly aligned. * * Use hash_words() instead, unless you're computing a hash function whose * value is exposed "on the wire" so we don't want to change it. */ UINT32 OvsJhashWords(const UINT32 *p, SIZE_T n, UINT32 basis) { UINT32 a, b, c; a = b = c = 0xdeadbeef + (((UINT32) n) << 2) + basis; while (n > 3) { a += p[0]; b += p[1]; c += p[2]; JhashMix(&a, &b, &c); n -= 3; p += 3; } switch (n) { case 3: c += p[2]; /* fall through */ case 2: b += p[1]; /* fall through */ case 1: a += p[0]; JhashFinal(&a, &b, &c); /* fall through */ case 0: break; } return c; } /* Returns the Jenkins hash of the 'n' bytes at 'p', starting from 'basis'. * * Use hash_bytes() instead, unless you're computing a hash function whose * value is exposed "on the wire" so we don't want to change it. */ UINT32 OvsJhashBytes(const VOID *p_, SIZE_T n, UINT32 basis) { const UINT32 *p = p_; UINT32 a, b, c; a = b = c = 0xdeadbeef + (UINT32)n + basis; while (n >= 12) { a += GetUnalignedU32(p); b += GetUnalignedU32(p + 1); c += GetUnalignedU32(p + 2); JhashMix(&a, &b, &c); n -= 12; p += 3; } if (n) { UINT32 tmp[3]; tmp[0] = tmp[1] = tmp[2] = 0; memcpy(tmp, p, n); a += tmp[0]; b += tmp[1]; c += tmp[2]; JhashFinal(&a, &b, &c); } return c; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Netlink0000644000000000000000000000013212664357344022004 xustar0030 mtime=1456594660.205289325 30 atime=1456594661.705352384 30 ctime=1456594660.205289325 openvswitch-2.5.0/datapath-windows/ovsext/Netlink/0000775000175000017500000000000012664357344023551 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/datapath-windows/ovsext/Netlink/PaxHeaders.69223/NetlinkProto.h0000644000000000000000000000013212631676262024657 xustar0030 mtime=1449622706.962439047 30 atime=1456592667.311090405 30 ctime=1456594660.205289325 openvswitch-2.5.0/datapath-windows/ovsext/Netlink/NetlinkProto.h0000664000175000017500000000704112631676262026351 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2010, 2011, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NETLINK_PROTO_H_ #define __NETLINK_PROTO_H_ 1 /* Netlink protocol definitions. * * Netlink is a message framing format described in RFC 3549 and used heavily * in Linux to access the network stack. Open vSwitch uses AF_NETLINK sockets * for this purpose on Linux. On Windows platform too, Open vSwitch uses * netlink message format for userspace-kernelspace communication. * * This header provides access to the Netlink message framing definitions * regardless of platform. */ #include "Types.h" #define BUILD_ASSERT(EXPR) \ typedef char AssertOnCompileFailed[(EXPR) ? 1: -1] #define BUILD_ASSERT_DECL(EXPR) BUILD_ASSERT(EXPR) /* Returns X / Y, rounding up. X must be nonnegative to round correctly. */ #define DIV_ROUND_UP(X, Y) (((X) + ((Y) - 1)) / (Y)) /* Returns X rounded up to the nearest multiple of Y. */ #define ROUND_UP(X, Y) (DIV_ROUND_UP(X, Y) * (Y)) /* Returns the least number that, when added to X, yields a multiple of Y. */ #define PAD_SIZE(X, Y) (ROUND_UP(X, Y) - (X)) /* Netlink message */ /* nlmsg_flags bits. */ #define NLM_F_REQUEST 0x001 #define NLM_F_MULTI 0x002 #define NLM_F_ACK 0x004 #define NLM_F_ECHO 0x008 #define NLM_F_ROOT 0x100 #define NLM_F_MATCH 0x200 #define NLM_F_EXCL 0x200 #define NLM_F_ATOMIC 0x400 #define NLM_F_CREATE 0x400 #define NLM_F_DUMP (NLM_F_ROOT | NLM_F_MATCH) /* nlmsg_type values. */ #define NLMSG_NOOP 1 #define NLMSG_ERROR 2 #define NLMSG_DONE 3 #define NLMSG_OVERRUN 4 #define NLMSG_MIN_TYPE 0x10 #define MAX_LINKS 32 #define NLMSG_ALIGNTO 4 #define NLMSG_ALIGN(SIZE) ROUND_UP(SIZE, NLMSG_ALIGNTO) #define NLA_ALIGNTO 4 #define NLA_ALIGN(SIZE) ROUND_UP(SIZE, NLA_ALIGNTO) typedef struct ovs_header OVS_HDR, *POVS_HDR; typedef struct _NL_MSG_HDR { UINT32 nlmsgLen; UINT16 nlmsgType; UINT16 nlmsgFlags; UINT32 nlmsgSeq; UINT32 nlmsgPid; } NL_MSG_HDR, *PNL_MSG_HDR; BUILD_ASSERT_DECL(sizeof(NL_MSG_HDR) == 16); typedef struct _NlMsgErr { INT error; NL_MSG_HDR nlMsg; } NL_MSG_ERR, *PNL_MSG_ERR; BUILD_ASSERT_DECL(sizeof(NL_MSG_ERR) == 20); typedef struct _GENL_MSG_HDR { UINT8 cmd; UINT8 version; UINT16 reserved; } GENL_MSG_HDR, *PGENL_MSG_HDR; BUILD_ASSERT_DECL(sizeof(GENL_MSG_HDR) == 4); /* Netlink attributes */ typedef struct _NL_ATTR { UINT16 nlaLen; UINT16 nlaType; } NL_ATTR, *PNL_ATTR; BUILD_ASSERT_DECL(sizeof(NL_ATTR) == 4); #ifndef NLA_TYPE_MASK #define NLA_F_NESTED (1 << 15) #define NLA_F_NET_BYTEORDER (1 << 14) #define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) #endif #define NLMSG_HDRLEN ((INT) NLMSG_ALIGN(sizeof(NL_MSG_HDR))) #define GENL_HDRLEN NLMSG_ALIGN(sizeof(GENL_MSG_HDR)) #define OVS_HDRLEN NLMSG_ALIGN(sizeof(OVS_HDR)) #define NLA_HDRLEN ((INT) NLA_ALIGN(sizeof(NL_ATTR))) #endif /* NetlinProto.h */ openvswitch-2.5.0/datapath-windows/ovsext/Netlink/PaxHeaders.69223/NetlinkBuf.c0000644000000000000000000000013212631676262024263 xustar0030 mtime=1449622706.962439047 30 atime=1456592667.311090405 30 ctime=1456594660.201289156 openvswitch-2.5.0/datapath-windows/ovsext/Netlink/NetlinkBuf.c0000664000175000017500000002331012631676262025752 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* ========================================================================== * This is a simple buffer mangement framework specific for netlink protocol. * The name could be confused with ovsext/BufferMgmt.c. Ovsext/BufferMgmt.c * deals with buffer mgmt for NBLs. Where as this framework deals with * management of buffer that holds a netlink message. * * This framework provides APIs for putting/accessing data in a buffer. These * APIs are used by driver's netlink protocol implementation. * * We can see this framework as a subset of ofpbuf in ovs userspace. * * This framework is NOT a generic buffer management framework (ofpbuf * is a generic buffer mgmt framework) and provides only the functioanlities * which would be useful for netlink protocol. Some of the key features are: * * a. It DOES NOT support automatic buffer reallocation. * i. A netlink input/output message is a static buffer. * b. The unused space is at the tail. * c. There is no notion of headdroom. * ========================================================================== */ #include #include #include #include #include #include #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_NETLINK #include "Debug.h" #include "NetlinkBuf.h" /* Returns used space in the buffer */ #define NL_BUF_USED_SPACE(_buf) (_buf->bufLen - \ _buf->bufRemLen) /* Validates that offset is within buffer boundaries and will not * create holes in the buffer.*/ #define NL_BUF_IS_VALID_OFFSET(_buf, _offset) (_offset <= \ NL_BUF_TAIL_OFFSET(_buf) ? 1 : 0) /* Validates if new data of size _size can be added at offset _offset. * This macor assumes that offset validation has been done.*/ #define NL_BUF_CAN_ADD(_buf, _size, _offset) (((_offset + _size <= \ _buf->bufLen) && (_size \ <= _buf->bufRemLen)) ? \ 1 : 0) /* Returns the offset of tail wrt buffer head */ #define NL_BUF_TAIL_OFFSET(_buf) (_buf->tail - _buf->head) static __inline VOID _NlBufCopyAtTailUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len); static __inline VOID _NlBufCopyAtOffsetUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset); /* * -------------------------------------------------------------------------- * NlBufInit -- * * Initializes NL_BUF with buffer pointer and length. * -------------------------------------------------------------------------- */ VOID NlBufInit(PNL_BUFFER nlBuf, PCHAR base, UINT32 size) { ASSERT(nlBuf); nlBuf->head = nlBuf->tail = base; nlBuf->bufLen = nlBuf->bufRemLen = size; } /* * -------------------------------------------------------------------------- * NlBufDeInit -- * * Resets the buffer variables to NULL. * -------------------------------------------------------------------------- */ VOID NlBufDeInit(PNL_BUFFER nlBuf) { ASSERT(nlBuf); nlBuf->head = nlBuf->tail = NULL; nlBuf->bufLen = nlBuf->bufRemLen = 0; } /* * -------------------------------------------------------------------------- * NlBufCopyAtTail -- * * Copies the data to the tail end of the buffer. * -------------------------------------------------------------------------- */ BOOLEAN NlBufCopyAtTail(PNL_BUFFER nlBuf, PCHAR data, UINT32 len) { BOOLEAN ret = TRUE; ASSERT(nlBuf); /* Check if we have enough space */ if (!NL_BUF_CAN_ADD(nlBuf, len, NL_BUF_TAIL_OFFSET(nlBuf))) { ret = FALSE; goto done; } _NlBufCopyAtTailUnsafe(nlBuf, data, len); done: return ret; } /* * -------------------------------------------------------------------------- * NlBufCopyAtHead -- * * Copies the data to the head of the buffer. * It can be seen as special case of NlBufCopyAtOffset with input * offset zero. * -------------------------------------------------------------------------- */ BOOLEAN NlBufCopyAtHead(PNL_BUFFER nlBuf, PCHAR data, UINT32 len) { BOOLEAN ret = TRUE; ASSERT(nlBuf); /* Check if we have enough space */ if (!NL_BUF_CAN_ADD(nlBuf, len, 0)) { ret = FALSE; goto done; } if (nlBuf->head == nlBuf->tail) { /* same as inserting in tail */ _NlBufCopyAtTailUnsafe(nlBuf, data, len); goto done; } _NlBufCopyAtOffsetUnsafe(nlBuf, data, len, 0); done: return ret; } /* * -------------------------------------------------------------------------- * NlBufCopyAtOffset -- * * Inserts data at input offset in the buffer. * If the offset is earlier then tail end then it first creates * space of size input length at input offset by moving the existing * data forward. * -------------------------------------------------------------------------- */ BOOLEAN NlBufCopyAtOffset(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset) { PCHAR dest = NULL; BOOLEAN ret = TRUE; ASSERT(nlBuf); /* Check if input offset is valid and has enough space */ if ((!NL_BUF_IS_VALID_OFFSET(nlBuf, offset)) || (!NL_BUF_CAN_ADD(nlBuf, len, offset))) { ret = FALSE; goto done; } dest = nlBuf->head + offset; if (dest == nlBuf->tail) { /* same as inserting in tail */ _NlBufCopyAtTailUnsafe(nlBuf, data, len); goto done; } _NlBufCopyAtOffsetUnsafe(nlBuf, data, len, offset); done: return ret; } /* * -------------------------------------------------------------------------- * NlBufCopyAtTailUninit -- * * Memsets the buffer portion of length len at tail end with zero. * -------------------------------------------------------------------------- */ PCHAR NlBufCopyAtTailUninit(PNL_BUFFER nlBuf, UINT32 len) { PCHAR ret; ret = nlBuf->tail; if ((NlBufCopyAtTail(nlBuf, NULL, len)) == FALSE) { ret = NULL; } return ret; } /* * -------------------------------------------------------------------------- * NlBufCopyAtHeadUninit -- * * Memsets the buffer portion of length len at head with zero. * -------------------------------------------------------------------------- */ PCHAR NlBufCopyAtHeadUninit(PNL_BUFFER nlBuf, UINT32 len) { PCHAR ret = NULL; if ((NlBufCopyAtHead(nlBuf, NULL, len)) == FALSE) { goto done; } ret = nlBuf->head; done: return ret; } /* * -------------------------------------------------------------------------- * NlBufCopyAtOffsetUninit -- * * Memsets the buffer portion of length len at head with zero. * * If the offset is earlier then tail end then it first creates * space of size input length at input offset by moving the existing * data forward. * -------------------------------------------------------------------------- */ PCHAR NlBufCopyAtOffsetUninit(PNL_BUFFER nlBuf, UINT32 len, UINT32 offset) { PCHAR ret = NULL; if ((NlBufCopyAtOffset(nlBuf, NULL, len, offset)) == FALSE) { goto done; } ret = nlBuf->head + offset; done: return ret; } /* * -------------------------------------------------------------------------- * NlBufAt -- * * Returns pointer to buffer at input offset. * bufLen is used to verify that expected data length * is within valid boundaries. Here by boundaries we mean * within head and tail. * -------------------------------------------------------------------------- */ PCHAR NlBufAt(PNL_BUFFER nlBuf, UINT32 offset, UINT32 bufLen) { PCHAR ret = NULL; ASSERT(nlBuf); if ((!NL_BUF_IS_VALID_OFFSET(nlBuf, offset))) { goto done; } /* Check if requested buffer is within head and tail */ if ((offset + bufLen) > NL_BUF_USED_SPACE(nlBuf)) { goto done; } ret = nlBuf->head + offset; done: return ret; } /* *_Unsafe functions does not do any validation. */ /* * -------------------------------------------------------------------------- * _NlBufCopyAtTailUnsafe -- * * Helper function for NlBufCopyAtTail. * -------------------------------------------------------------------------- */ static __inline VOID _NlBufCopyAtTailUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len) { if (data) { RtlCopyMemory(nlBuf->tail, data, len); } else { RtlZeroMemory(nlBuf->tail, len); } nlBuf->tail += len; nlBuf->bufRemLen -= len; } /* * -------------------------------------------------------------------------- * _NlBufCopyAtOffsetUnsafe -- * * Helper function for NlBufCopyAtOffset. * -------------------------------------------------------------------------- */ static __inline VOID _NlBufCopyAtOffsetUnsafe(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset) { PCHAR dest = NULL; dest = nlBuf->head + offset; RtlMoveMemory(dest+len, dest, NL_BUF_USED_SPACE(nlBuf) - offset); if (data) { RtlCopyMemory(dest, data, len); } else { RtlZeroMemory(dest, len); } nlBuf->tail += len; nlBuf->bufRemLen -= len; } openvswitch-2.5.0/datapath-windows/ovsext/Netlink/PaxHeaders.69223/NetlinkBuf.h0000644000000000000000000000013212631676262024270 xustar0030 mtime=1449622706.962439047 30 atime=1456592667.311090405 30 ctime=1456594660.201289156 openvswitch-2.5.0/datapath-windows/ovsext/Netlink/NetlinkBuf.h0000664000175000017500000000430212631676262025757 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NETLINK_BUF_H_ #define __NETLINK_BUF_H_ 1 typedef struct _NL_BUF { PCHAR head; /* start address of the buffer */ PCHAR tail; /* first empty byte of the buffer */ UINT32 bufLen; /* original length of buffer */ UINT32 bufRemLen; /* remaining length of buffer */ } NL_BUFFER, *PNL_BUFFER; VOID NlBufInit(PNL_BUFFER nlBuf, PCHAR base, UINT32 size); VOID NlBufDeInit(PNL_BUFFER nlBuf); BOOLEAN NlBufCopyAtTail(PNL_BUFFER nlBuf, PCHAR data, UINT32 len); BOOLEAN NlBufCopyAtHead(PNL_BUFFER nlBuf, PCHAR data, UINT32 len); BOOLEAN NlBufCopyAtOffset(PNL_BUFFER nlBuf, PCHAR data, UINT32 len, UINT32 offset); PCHAR NlBufCopyAtTailUninit(PNL_BUFFER nlBuf, UINT32 len); PCHAR NlBufCopyAtHeadUninit(PNL_BUFFER nlBuf, UINT32 len); PCHAR NlBufCopyAtOffsetUninit(PNL_BUFFER nlBuf, UINT32 len, UINT32 offset); PCHAR NlBufAt(PNL_BUFFER nlBuf, UINT32 offset, UINT32 len); /* * -------------------------------------------------------------------------- * NlBufSize -- * * Returns the used size of buffer. * -------------------------------------------------------------------------- */ static __inline UINT32 NlBufSize(PNL_BUFFER nlBuf) { ASSERT(nlBuf); return (nlBuf->bufLen - nlBuf->bufRemLen); } /* * -------------------------------------------------------------------------- * NlBufRemLen -- * * Returns the unused size of buffer. * -------------------------------------------------------------------------- */ static __inline UINT32 NlBufRemLen(PNL_BUFFER nlBuf) { ASSERT(nlBuf); return (nlBuf->bufRemLen); } #endif /* __NETLINK_BUF_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/Netlink/PaxHeaders.69223/Netlink.c0000644000000000000000000000013212631676262023626 xustar0030 mtime=1449622706.962439047 30 atime=1456592667.311090405 30 ctime=1456594660.197288987 openvswitch-2.5.0/datapath-windows/ovsext/Netlink/Netlink.c0000664000175000017500000010042612631676262025321 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "NetlinkProto.h" #include "Netlink.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_NETLINK #include "Debug.h" /* ========================================================================== * This file provides simple netlink get, put and validation APIs. * Most of the code is on similar lines as userspace netlink implementation. * * TODO: Convert these methods to inline. * ========================================================================== */ /* * --------------------------------------------------------------------------- * Prepare netlink message headers. This API adds * NL_MSG_HDR + GENL_HDR + OVS_HDR to the tail of input NLBuf. * Attributes should be added by caller. * --------------------------------------------------------------------------- */ BOOLEAN NlFillOvsMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType, UINT16 nlmsgFlags, UINT32 nlmsgSeq, UINT32 nlmsgPid, UINT8 genlCmd, UINT8 genlVer, UINT32 dpNo) { BOOLEAN writeOk; OVS_MESSAGE msgOut; UINT32 offset = NlBufSize(nlBuf); /* To keep compiler happy for release build. */ UNREFERENCED_PARAMETER(offset); ASSERT(NlBufAt(nlBuf, offset, 0) != 0); msgOut.nlMsg.nlmsgType = nlmsgType; msgOut.nlMsg.nlmsgFlags = nlmsgFlags; msgOut.nlMsg.nlmsgSeq = nlmsgSeq; msgOut.nlMsg.nlmsgPid = nlmsgPid; msgOut.nlMsg.nlmsgLen = sizeof(struct _OVS_MESSAGE); msgOut.genlMsg.cmd = genlCmd; msgOut.genlMsg.version = genlVer; msgOut.genlMsg.reserved = 0; msgOut.ovsHdr.dp_ifindex = dpNo; writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut), sizeof (struct _OVS_MESSAGE)); return writeOk; } /* * --------------------------------------------------------------------------- * Prepare NL_MSG_HDR only. This API appends a NL_MSG_HDR to the tail of * input NlBuf. * --------------------------------------------------------------------------- */ BOOLEAN NlFillNlHdr(PNL_BUFFER nlBuf, UINT16 nlmsgType, UINT16 nlmsgFlags, UINT32 nlmsgSeq, UINT32 nlmsgPid) { BOOLEAN writeOk; NL_MSG_HDR msgOut; UINT32 offset = NlBufSize(nlBuf); /* To keep compiler happy for release build. */ UNREFERENCED_PARAMETER(offset); ASSERT(NlBufAt(nlBuf, offset, 0) != 0); msgOut.nlmsgType = nlmsgType; msgOut.nlmsgFlags = nlmsgFlags; msgOut.nlmsgSeq = nlmsgSeq; msgOut.nlmsgPid = nlmsgPid; msgOut.nlmsgLen = sizeof(struct _NL_MSG_HDR); writeOk = NlMsgPutTail(nlBuf, (PCHAR)(&msgOut), sizeof(struct _NL_MSG_HDR)); return writeOk; } /* * --------------------------------------------------------------------------- * Prepare a 'OVS_MESSAGE_ERROR' message. * --------------------------------------------------------------------------- */ VOID NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgError, UINT errorCode) { NL_BUFFER nlBuffer; ASSERT(errorCode != NL_ERROR_PENDING); NlBufInit(&nlBuffer, (PCHAR)msgError, sizeof *msgError); NlFillNlHdr(&nlBuffer, NLMSG_ERROR, 0, msgIn->nlMsg.nlmsgSeq, msgIn->nlMsg.nlmsgPid); msgError->errorMsg.error = errorCode; msgError->errorMsg.nlMsg = msgIn->nlMsg; msgError->nlMsg.nlmsgLen = sizeof(OVS_MESSAGE_ERROR); } /* * --------------------------------------------------------------------------- * Adds Netlink Header to the NL_BUF. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg) { if ((NlBufCopyAtOffset(buf, (PCHAR)nlMsg, NLMSG_HDRLEN, 0))) { return TRUE; } return FALSE; } /* * --------------------------------------------------------------------------- * Adds Genl Header to the NL_BUF. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg) { if ((NlBufCopyAtOffset(buf, (PCHAR)genlMsg, GENL_HDRLEN, NLMSG_HDRLEN))) { return TRUE; } return FALSE; } /* * --------------------------------------------------------------------------- * Adds OVS Header to the NL_BUF. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr) { if ((NlBufCopyAtOffset(buf, (PCHAR)ovsHdr, OVS_HDRLEN, GENL_HDRLEN + NLMSG_HDRLEN))) { return TRUE; } return FALSE; } /* * --------------------------------------------------------------------------- * Adds data of length 'len' to the tail end of NL_BUF. * Refer nl_msg_put for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len) { len = NLMSG_ALIGN(len); if (NlBufCopyAtTail(buf, data, len)) { return TRUE; } return FALSE; } /* * --------------------------------------------------------------------------- * memsets length 'len' at tail end of NL_BUF. * Refer nl_msg_put_uninit for more details. * --------------------------------------------------------------------------- */ PCHAR NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len) { len = NLMSG_ALIGN(len); return NlBufCopyAtTailUninit(buf, len); } /* * --------------------------------------------------------------------------- * Adds an attribute to the tail end of buffer. It does * not copy the attribute payload. * Refer nl_msg_put_unspec_uninit for more details. * --------------------------------------------------------------------------- */ PCHAR NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len) { PCHAR ret = NULL; UINT16 totalLen = NLA_HDRLEN + len; PNL_ATTR nla = (PNL_ATTR)(NlMsgPutTailUninit(buf, totalLen)); if (!nla) { goto done; } ret = (PCHAR)(nla + 1); nla->nlaLen = totalLen; nla->nlaType = type; done: return ret; } /* * --------------------------------------------------------------------------- * Adds an attribute to the tail end of buffer. It copies attribute * payload as well. * Refer nl_msg_put_unspec for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len) { BOOLEAN ret = TRUE; PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, len); if (!nlaData) { ret = FALSE; goto done; } RtlCopyMemory(nlaData, data, len); done: return ret; } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and no payload at the tail end of buffer. * Refer nl_msg_put_flag for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type) { BOOLEAN ret = TRUE; PCHAR nlaData = NlMsgPutTailUnspecUninit(buf, type, 0); if (!nlaData) { ret = FALSE; } return ret; } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 8 bit payload at the tail end of buffer. * Refer nl_msg_put_u8 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value) { return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 16 bit payload at the tail end of buffer. * Refer nl_msg_put_u16 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value) { return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 32 bit payload at the tail end of buffer. * Refer nl_msg_put_u32 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value) { return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 64 bit payload at the tail end of buffer. * Refer nl_msg_put_u64 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value) { return (NlMsgPutTailUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and string payload. * Refer nl_msg_put_string for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value) { size_t strLen = strlen(value) + 1; #ifdef DBG /* Attribute length should come within 16 bits (NL_ATTR). * Not a likely case, hence validation only in debug mode. */ if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) { return FALSE; } #endif /* typecast to keep compiler happy */ return (NlMsgPutTailUnspec(buf, type, value, (UINT16)strLen)); } /* * --------------------------------------------------------------------------- * Adds data of length 'len' to the head of NL_BUF. * Refer nl_msg_push for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len) { len = NLMSG_ALIGN(len); if (NlBufCopyAtHead(buf, data, len)) { return TRUE; } return FALSE; } /* * --------------------------------------------------------------------------- * memsets length 'len' at head of NL_BUF. * Refer nl_msg_push_uninit for more details. * --------------------------------------------------------------------------- */ PCHAR NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len) { len = NLMSG_ALIGN(len); return NlBufCopyAtHeadUninit(buf, len); } /* * --------------------------------------------------------------------------- * Adds an attribute to the head of buffer. It does * not copy the attribute payload. * Refer nl_msg_push_unspec_uninit for more details. * --------------------------------------------------------------------------- */ PCHAR NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len) { PCHAR ret = NULL; UINT16 totalLen = NLA_HDRLEN + len; PNL_ATTR nla = (PNL_ATTR)(NlMsgPutHeadUninit(buf, totalLen)); if (!nla) { goto done; } ret = (PCHAR)(nla + 1); nla->nlaLen = totalLen; nla->nlaType = type; done: return ret; } /* * --------------------------------------------------------------------------- * Adds an attribute to the head of buffer. It copies attribute * payload as well. * Refer nl_msg_push_unspec for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len) { BOOLEAN ret = TRUE; PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, len); if (!nlaData) { ret = FALSE; goto done; } RtlCopyMemory(nlaData, data, len); done: return ret; } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and no payload at the head of buffer. * Refer nl_msg_push_flag for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type) { BOOLEAN ret = TRUE; PCHAR nlaData = NlMsgPutHeadUnspecUninit(buf, type, 0); if (!nlaData) { ret = FALSE; } return ret; } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 8 bit payload at the head of buffer. * Refer nl_msg_push_u8 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value) { return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 16 bit payload at the head of buffer. * Refer nl_msg_push_u16 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value) { return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 32 bit payload at the head of buffer. * Refer nl_msg_push_u32 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value) { return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and 64 bit payload at the head of buffer. * Refer nl_msg_push_u64 for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value) { return (NlMsgPutHeadUnspec(buf, type, (PCHAR)(&value), sizeof(value))); } /* * --------------------------------------------------------------------------- * Adds an attribute of 'type' and string payload. * Refer nl_msg_push_string for more details. * --------------------------------------------------------------------------- */ BOOLEAN NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value) { size_t strLen = strlen(value) + 1; #ifdef DBG /* Attribute length should come within 16 bits (NL_ATTR). * Not a likely case, hence validation only in debug mode. */ if ((strLen + PAD_SIZE(strLen, NLA_ALIGNTO)) > MAXUINT16) { return FALSE; } #endif /* typecast to keep compiler happy */ return (NlMsgPutHeadUnspec(buf, type, value, (UINT16)strLen)); } /* * --------------------------------------------------------------------------- * Adds the header for nested netlink attributes. It * returns the offset of this header. If addition of header fails * then returned value of offset will be zero. * Refer nl_msg_start_nested for more details. * --------------------------------------------------------------------------- */ UINT32 NlMsgStartNested(PNL_BUFFER buf, UINT16 type) { UINT32 offset = NlBufSize(buf); PCHAR nlaData = NULL; nlaData = NlMsgPutTailUnspecUninit(buf, type, 0); if (!nlaData) { /* Value zero must be reated as error by the caller. * This is because an attribute can never be added * at offset zero, it will always come after NL_MSG_HDR, * GENL_HDR and OVS_HEADER. */ offset = 0; } return offset; } /* * --------------------------------------------------------------------------- * Finalizes the nested netlink attribute by updating the nla_len. * offset should be the one returned by NlMsgStartNested. * Refer nl_msg_end_nested for more details. * --------------------------------------------------------------------------- */ VOID NlMsgEndNested(PNL_BUFFER buf, UINT32 offset) { PNL_ATTR attr = (PNL_ATTR)(NlBufAt(buf, offset, sizeof *attr)); /* Typecast to keep compiler happy. * Attribute length would never exceed MAX UINT16.*/ attr->nlaLen = (UINT16)(NlBufSize(buf) - offset); } /* * -------------------------------------------------------------------------- * Appends a nested Netlink attribute of the given 'type', with the 'size' * bytes of content starting at 'data', to 'msg'. * Refer nl_msg_put_nested for more details. * -------------------------------------------------------------------------- */ BOOLEAN NlMsgPutNested(PNL_BUFFER buf, UINT16 type, const PVOID data, UINT32 size) { UINT32 offset = NlMsgStartNested(buf, type); BOOLEAN ret = FALSE; ASSERT(offset); ret = NlMsgPutTail(buf, data, size); ASSERT(ret); NlMsgEndNested(buf, offset); return ret; } /* Accessing netlink message payload */ /* * --------------------------------------------------------------------------- * Netlink message accessing the payload. * --------------------------------------------------------------------------- */ PVOID NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset) { return ((PCHAR)nlh + offset); } /* * --------------------------------------------------------------------------- * Returns the size of netlink message. * --------------------------------------------------------------------------- */ UINT32 NlMsgSize(const PNL_MSG_HDR nlh) { return nlh->nlmsgLen; } /* * --------------------------------------------------------------------------- * Aligns the size of Netlink message. * --------------------------------------------------------------------------- */ VOID NlMsgAlignSize(const PNL_MSG_HDR nlh) { nlh->nlmsgLen = NLMSG_ALIGN(nlh->nlmsgLen); return; } /* * --------------------------------------------------------------------------- * Sets the size of Netlink message. * --------------------------------------------------------------------------- */ VOID NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen) { nlh->nlmsgLen = msgLen; } /* * --------------------------------------------------------------------------- * Returns pointer to nlmsg payload. * --------------------------------------------------------------------------- */ PCHAR NlHdrPayload(const PNL_MSG_HDR nlh) { return ((PCHAR)nlh + NLMSG_HDRLEN); } /* * --------------------------------------------------------------------------- * Returns length of nlmsg payload. * --------------------------------------------------------------------------- */ UINT32 NlHdrPayloadLen(const PNL_MSG_HDR nlh) { return nlh->nlmsgLen - NLMSG_HDRLEN; } /* * --------------------------------------------------------------------------- * Returns pointer to nlmsg attributes. * --------------------------------------------------------------------------- */ PNL_ATTR NlMsgAttrs(const PNL_MSG_HDR nlh) { return (PNL_ATTR) (NlHdrPayload(nlh) + GENL_HDRLEN + OVS_HDRLEN); } /* * --------------------------------------------------------------------------- * Returns size of to nlmsg attributes. * --------------------------------------------------------------------------- */ UINT32 NlMsgAttrsLen(const PNL_MSG_HDR nlh) { return NlHdrPayloadLen(nlh) - GENL_HDRLEN - OVS_HDRLEN; } /* Netlink message parse. */ /* * --------------------------------------------------------------------------- * Returns next netlink message in the stream. * --------------------------------------------------------------------------- */ PNL_MSG_HDR NlMsgNext(const PNL_MSG_HDR nlh) { return (PNL_MSG_HDR)((PCHAR)nlh + NLMSG_ALIGN(nlh->nlmsgLen)); } /* * --------------------------------------------------------------------------- * Netlink Attr helper APIs. * --------------------------------------------------------------------------- */ INT NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen) { return (maxlen >= sizeof *nla && nla->nlaLen >= sizeof *nla && nla->nlaLen <= maxlen); } /* * --------------------------------------------------------------------------- * Returns alligned length of the attribute. * --------------------------------------------------------------------------- */ UINT32 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen) { UINT32 len = NLA_ALIGN(nla->nlaLen); return len <= maxlen ? len : nla->nlaLen; } /* * --------------------------------------------------------------------------- * Default minimum payload size for each type of attribute. * --------------------------------------------------------------------------- */ UINT32 NlAttrMinLen(NL_ATTR_TYPE type) { switch (type) { case NL_A_NO_ATTR: return 0; case NL_A_UNSPEC: return 0; case NL_A_U8: return 1; case NL_A_U16: return 2; case NL_A_U32: return 4; case NL_A_U64: return 8; case NL_A_STRING: return 1; case NL_A_FLAG: return 0; case NL_A_NESTED: return 0; case N_NL_ATTR_TYPES: default: OVS_LOG_WARN("Unsupprted attribute type: %d", type); ASSERT(0); } /* To keep compiler happy */ return 0; } /* * --------------------------------------------------------------------------- * Default maximum payload size for each type of attribute. * --------------------------------------------------------------------------- */ UINT32 NlAttrMaxLen(NL_ATTR_TYPE type) { switch (type) { case NL_A_NO_ATTR: return SIZE_MAX; case NL_A_UNSPEC: return SIZE_MAX; case NL_A_U8: return 1; case NL_A_U16: return 2; case NL_A_U32: return 4; case NL_A_U64: return 8; case NL_A_STRING: return MAXUINT16; case NL_A_FLAG: return SIZE_MAX; case NL_A_NESTED: return SIZE_MAX; case N_NL_ATTR_TYPES: default: OVS_LOG_WARN("Unsupprted attribute type: %d", type); ASSERT(0); } /* To keep compiler happy */ return 0; } /* Netlink attribute iteration. */ /* * --------------------------------------------------------------------------- * Returns the next attribute. * --------------------------------------------------------------------------- */ PNL_ATTR NlAttrNext(const PNL_ATTR nla) { return (PNL_ATTR)((UINT8 *)nla + NLA_ALIGN(nla->nlaLen)); } /* * -------------------------------------------------------------------------- * Returns the bits of 'nla->nlaType' that are significant for determining * its type. * -------------------------------------------------------------------------- */ UINT16 NlAttrType(const PNL_ATTR nla) { return nla->nlaType & NLA_TYPE_MASK; } /* * -------------------------------------------------------------------------- * Returns the netlink attribute data. * -------------------------------------------------------------------------- */ PVOID NlAttrData(const PNL_ATTR nla) { return ((PCHAR)nla + NLA_HDRLEN); } /* * --------------------------------------------------------------------------- * Returns the number of bytes in the payload of attribute 'nla'. * --------------------------------------------------------------------------- */ UINT32 NlAttrGetSize(const PNL_ATTR nla) { return nla->nlaLen - NLA_HDRLEN; } /* * --------------------------------------------------------------------------- * Returns the first byte in the payload of attribute 'nla'. * --------------------------------------------------------------------------- */ const PVOID NlAttrGet(const PNL_ATTR nla) { ASSERT(nla->nlaLen >= NLA_HDRLEN); return nla + 1; } /* * --------------------------------------------------------------------------- * Asserts that 'nla''s payload is at least 'size' bytes long, and returns the * first byte of the payload. * --------------------------------------------------------------------------- */ const PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size) { UNREFERENCED_PARAMETER(size); ASSERT(nla->nlaLen >= NLA_HDRLEN + size); return nla + 1; } /* * --------------------------------------------------------------------------- * Returns the 64-bit network byte order value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 8 bytes long. * --------------------------------------------------------------------------- */ BE64 NlAttrGetBe64(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, BE64); } /* * --------------------------------------------------------------------------- * Returns the 32-bit network byte order value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 4 bytes long. * --------------------------------------------------------------------------- */ BE32 NlAttrGetBe32(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, BE32); } /* * --------------------------------------------------------------------------- * Returns the 16-bit network byte order value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 2 bytes long. * --------------------------------------------------------------------------- */ BE16 NlAttrGetBe16(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, BE16); } /* * --------------------------------------------------------------------------- * Returns the 8-bit network byte order value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 1 byte long. * --------------------------------------------------------------------------- */ BE8 NlAttrGetBe8(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, BE8); } /* * --------------------------------------------------------------------------- * Returns the 8-bit value in 'nla''s payload. * --------------------------------------------------------------------------- */ UINT8 NlAttrGetU8(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, UINT8); } /* * --------------------------------------------------------------------------- * Returns the 16-bit host byte order value in 'nla''s payload. * Asserts that 'nla''s payload is at least 2 bytes long. * --------------------------------------------------------------------------- */ UINT16 NlAttrGetU16(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, UINT16); } /* * --------------------------------------------------------------------------- * Returns the 32-bit host byte order value in 'nla''s payload. * Asserts that 'nla''s payload is at least 4 bytes long. * --------------------------------------------------------------------------- */ UINT32 NlAttrGetU32(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, UINT32); } /* * --------------------------------------------------------------------------- * Returns the 64-bit host byte order value in 'nla''s payload. * Asserts that 'nla''s payload is at least 8 bytes long. * --------------------------------------------------------------------------- */ UINT64 NlAttrGetU64(const PNL_ATTR nla) { return NL_ATTR_GET_AS(nla, UINT64); } /* * --------------------------------------------------------------------------- * Validate the netlink attribute against the policy * --------------------------------------------------------------------------- */ BOOLEAN NlAttrValidate(const PNL_ATTR nla, const PNL_POLICY policy) { UINT32 minLen; UINT32 maxLen; UINT32 len; BOOLEAN ret = FALSE; if ((policy->type == NL_A_NO_ATTR) || (policy->type == NL_A_VAR_LEN) || (policy->type == NL_A_NESTED)) { /* Do not validate anything for attributes of type var length */ ret = TRUE; goto done; } /* Figure out min and max length. */ minLen = policy->minLen; if (!minLen) { minLen = NlAttrMinLen(policy->type); } maxLen = policy->maxLen; if (!maxLen) { maxLen = NlAttrMaxLen(policy->type); } /* Verify length. */ len = NlAttrGetSize(nla); if (len < minLen || len > maxLen) { OVS_LOG_WARN("Attribute: %p, len: %d, not in valid range, " "min: %d, max: %d", nla, len, minLen, maxLen); goto done; } /* Strings must be null terminated and must not have embedded nulls. */ if (policy->type == NL_A_STRING) { if (((PCHAR) nla)[nla->nlaLen - 1]) { OVS_LOG_WARN("Attributes %p lacks null at the end", nla); goto done; } if (memchr(nla + 1, '\0', len - 1) != NULL) { OVS_LOG_WARN("Attributes %p has bad length", nla); goto done; } } ret = TRUE; done: return ret; } /* * --------------------------------------------------------------------------- * Returns an attribute of type 'type' from a series of * attributes. * --------------------------------------------------------------------------- */ const PNL_ATTR NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type) { PNL_ATTR iter = NULL; PNL_ATTR ret = NULL; UINT32 left; NL_ATTR_FOR_EACH (iter, left, attrs, size) { if (NlAttrType(iter) == type) { ret = iter; goto done; } } done: return ret; } /* * --------------------------------------------------------------------------- * Returns the first Netlink attribute within 'nla' with the specified * 'type'. * * This function does not validate the attribute's length. * --------------------------------------------------------------------------- */ const PNL_ATTR NlAttrFindNested(const PNL_ATTR nla, UINT16 type) { return NlAttrFind__((const PNL_ATTR)(NlAttrGet(nla)), NlAttrGetSize(nla), type); } /* *---------------------------------------------------------------------------- * Parses the netlink message at a given offset (attrOffset) * as a series of attributes. A pointer to the attribute with type * 'type' is stored in attrs at index 'type'. policy is used to define the * attribute type validation parameters. * 'nla_offset' should be NLMSG_HDRLEN + GENL_HDRLEN + OVS_HEADER * * Returns BOOLEAN to indicate success/failure. *---------------------------------------------------------------------------- */ BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy, PNL_ATTR attrs[], UINT32 numAttrs) { PNL_ATTR nla; UINT32 left; UINT32 iter; BOOLEAN ret = FALSE; UINT32 numPolicyAttr = MIN(numPolicy, numAttrs); RtlZeroMemory(attrs, numAttrs * sizeof *attrs); /* There is nothing to parse */ if (!(NlMsgAttrsLen(nlMsg))) { ret = TRUE; goto done; } if ((NlMsgSize(nlMsg) < attrOffset)) { OVS_LOG_WARN("No attributes in nlMsg: %p at offset: %d", nlMsg, attrOffset); goto done; } NL_ATTR_FOR_EACH (nla, left, NlMsgAt(nlMsg, attrOffset), totalAttrLen) { UINT16 type = NlAttrType(nla); if (type < numPolicyAttr && policy[type].type != NL_A_NO_ATTR) { /* Typecasting to keep the compiler happy */ const PNL_POLICY e = (const PNL_POLICY)(&policy[type]); if (!NlAttrValidate(nla, e)) { goto done; } if (attrs[type]) { OVS_LOG_WARN("Duplicate attribute in nlMsg: %p, " "type: %u", nlMsg, type); } attrs[type] = nla; } } if (left) { OVS_LOG_ERROR("Attributes followed by garbage"); goto done; } for (iter = 0; iter < numPolicyAttr; iter++) { const PNL_POLICY e = (const PNL_POLICY)(&policy[iter]); if (!e->optional && e->type != NL_A_NO_ATTR && !attrs[iter]) { OVS_LOG_ERROR("Required attr:%d missing", iter); goto done; } } ret = TRUE; done: return ret; } /* *---------------------------------------------------------------------------- * Parses the netlink message for nested attributes. attrOffset must be the * offset of nla which is the header of the nested attribute series. * Refer nl_parse_nested for more details. * * Returns BOOLEAN to indicate success/failure. *---------------------------------------------------------------------------- */ BOOLEAN NlAttrParseNested(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy, PNL_ATTR attrs[], UINT32 numAttrs) { return NlAttrParse(nlMsg, attrOffset + NLA_HDRLEN, totalAttrLen - NLA_HDRLEN, policy, numPolicy, attrs, numAttrs); } openvswitch-2.5.0/datapath-windows/ovsext/Netlink/PaxHeaders.69223/NetlinkError.h0000644000000000000000000000013212664352753024647 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.201289156 openvswitch-2.5.0/datapath-windows/ovsext/Netlink/NetlinkError.h0000664000175000017500000001757412664352753026355 0ustar00jpettitjpettit00000000000000/* * Copyright 2014 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include "precomp.h" /* * These are error codes to be used by netlink transactional operations. * The error code is assigned to the "error" field (INT) of the NL_MSG_ERR * struct. */ typedef enum _NL_ERROR_ { NL_ERROR_SUCCESS = 0, /* The operation is not permitted */ NL_ERROR_PERM = ((ULONG)-1), /* There is no such file or directory */ NL_ERROR_NOENT = ((ULONG)-2), /* There is no such process */ NL_ERROR_SRCH = ((ULONG)-3), /* An interrupted system call / interrupted function */ NL_ERROR_INTR = ((ULONG)-4), /* An I/O error */ NL_ERROR_IO = ((ULONG)-5), /* There is no such device or address */ NL_ERROR_NXIO = ((ULONG)-6), /* The argument list is too long */ NL_ERROR_2BIG = ((ULONG)-7), /* Executable file format error */ NL_ERROR_NOEXEC = ((ULONG)-8), /* A bad file descriptor / number */ NL_ERROR_BADF = ((ULONG)-9), /* Have no child processes */ NL_ERROR_CHILD = ((ULONG)-10), /* resource unavailable => try again later */ NL_ERROR_AGAIN = ((ULONG)-11), /* We're out of memory */ NL_ERROR_NOMEM = ((ULONG)-12), /* Permission is denied */ NL_ERROR_ACCES = ((ULONG)-13), /* A bad address */ NL_ERROR_FAULT = ((ULONG)-14), /* The device or the resource is busy */ NL_ERROR_BUSY = ((ULONG)-16), /* The file exists */ NL_ERROR_EXIST = ((ULONG)-17), /* A cross-device link */ NL_ERROR_XDEV = ((ULONG)-18), /* There is no such device */ NL_ERROR_NODEV = ((ULONG)-19), /* It is not a directory, nor a symbolic link to a directory. */ NL_ERROR_NOTDIR = ((ULONG)-20), /* This is a directory */ NL_ERROR_ISDIR = ((ULONG)-21), /* An invalid argument */ NL_ERROR_INVAL = ((ULONG)-22), /* * There are too many files open in system (i.e. no room for another file * descriptor) */ NL_ERROR_NFILE = ((ULONG)-23), /* The file descriptor value is too large. */ NL_ERROR_MFILE = ((ULONG)-24), /* And Inappropriate I/O control operation. Or, this is not a typewriter */ NL_ERROR_NOTTY = ((ULONG)-25), /* The file is too large */ NL_ERROR_FBIG = ((ULONG)-27), /* There is no space left on the device */ NL_ERROR_NOSPC = ((ULONG)-28), /* This is an invalid seek */ NL_ERROR_SPIPE = ((ULONG)-29), /* A read-only file system */ NL_ERROR_ROFS = ((ULONG)-30), /* There are too many links */ NL_ERROR_MLINK = ((ULONG)-31), /* A broken pipe */ NL_ERROR_PIPE = ((ULONG)-32), /* The mathematics argument is out of the domain of the function. */ NL_ERROR_DOM = ((ULONG)-33), /* The result is too large / cannot be represented */ NL_ERROR_RANGE = ((ULONG)-34), /* A resource deadlock would occur */ NL_ERROR_DEADLK = ((ULONG)-36), /* The file name is too long */ NL_ERROR_NAMETOOLONG = ((ULONG)-38), /* There are no locks available */ NL_ERROR_NOLCK = ((ULONG)-39), /* The function is not implemented / not supported */ NL_ERROR_NOSYS = ((ULONG)-40), /* The directory is not empty */ NL_ERROR_NOTEMPTY = ((ULONG)-41), /* The byte sequence is illegal */ NL_ERROR_ILSEQ = ((ULONG)-42), NL_ERROR_STRUNCATE = ((ULONG)-80), /* The address is already in use */ NL_ERROR_ADDRINUSE = ((ULONG)-100), /* The requested address cannot be assigned: is is not available */ NL_ERROR_ADDRNOTAVAIL = ((ULONG)-101), /* the address family is not supported by the protocol */ NL_ERROR_AFNOSUPPORT = ((ULONG)-102), /* The operation / connection is already in progress */ NL_ERROR_ALREADY = ((ULONG)-103), /* The message is bad */ NL_ERROR_BADMSG = ((ULONG)-104), /* The operation was canceled */ NL_ERROR_CANCELED = ((ULONG)-105), /* The software has caused a connection abort */ NL_ERROR_CONNABORTED = ((ULONG)-106), /*The connection was refused */ NL_ERROR_CONNREFUSED = ((ULONG)-107), /* The connection was reset by the peer */ NL_ERROR_CONNRESET = ((ULONG)-108), /* The destination address is required */ NL_ERROR_DESTADDRREQ = ((ULONG)-109), /*The host is unreachable */ NL_ERROR_HOSTUNREACH = ((ULONG)-110), /* The identifier was removed */ NL_ERROR_IDRM = ((ULONG)-111), /* The operations is in progress */ NL_ERROR_INPROGRESS = ((ULONG)-112), /* The socket is already connected */ NL_ERROR_ISCONN = ((ULONG)-113), /* There are too many levels of symbolic links. */ NL_ERROR_LOOP = ((ULONG)-114), /*The message is too large */ NL_ERROR_MSGSIZE = ((ULONG)-115), /* The network is down */ NL_ERROR_NETDOWN = ((ULONG)-116), /* The network has dropped connection because of a reset (i.e. the * connection was aborted by the network) */ NL_ERROR_NETRESET = ((ULONG)-117), /* The network is unreachable */ NL_ERROR_NETUNREACH = ((ULONG)-118), /* There is no buffer space available */ NL_ERROR_NOBUFS = ((ULONG)-119), /* There is no data available (on the stream head read queue) */ NL_ERROR_NODATA = ((ULONG)-120), /* The link has been severed (it's reserved in posix) */ NL_ERROR_NOLINK = ((ULONG)-121), /* There is no message of the desired type */ NL_ERROR_NOMSG = ((ULONG)-122), /* The protocol is not available */ NL_ERROR_NOPROTOOPT = ((ULONG)-123), /* We're out of streams resources */ NL_ERROR_NOSR = ((ULONG)-124), /* This is not a stream */ NL_ERROR_NOSTR = ((ULONG)-125), /* The socket is not connected */ NL_ERROR_NOTCONN = ((ULONG)-126), /* The state is not recoverable */ NL_ERROR_NOTRECOVERABLE = ((ULONG)-127), /* This is not a socket */ NL_ERROR_NOTSOCK = ((ULONG)-128), /* The operation is not supported */ NL_ERROR_NOTSUPP = ((ULONG)-129), /* The operation is not supported on socket */ NL_ERROR_OPNOTSUPP = ((ULONG)-130), NL_ERROR_OTHER = ((ULONG)-131), /* The value is too large for the data type */ NL_ERROR_OVERFLOW = ((ULONG)-132), /* The previous owner died */ NL_ERROR_OWNERDEAD = ((ULONG)-133), /* A protocol error */ NL_ERROR_PROTO = ((ULONG)-134), /* The protocol is not supported */ NL_ERROR_PROTONOSUPPORT = ((ULONG)-135), /* This is a wrong protocol type for the socket */ NL_ERROR_PROTOTYPE = ((ULONG)-136), /* The timer has expired (or, the stream ioctl has timed out) */ NL_ERROR_TIME = ((ULONG)-137), /* The connection has timed out */ NL_ERROR_TIMEDOUT = ((ULONG)-138), /* The given text file is busy */ NL_ERROR_TXTBSY = ((ULONG)-139), /* The operation would block */ NL_ERROR_WOULDBLOCK = ((ULONG)-140), /* The operation is not finished */ NL_ERROR_PENDING = ((ULONG)-141), } NL_ERROR; static __inline NlMapStatusToNlErr(NTSTATUS status) { NL_ERROR ret; switch (status) { case STATUS_NOT_SUPPORTED: ret = NL_ERROR_NOTSUPP; break; case STATUS_INSUFFICIENT_RESOURCES: ret = NL_ERROR_NOMEM; break; case STATUS_SUCCESS: ret = NL_ERROR_SUCCESS; break; case STATUS_PENDING: ret = NL_ERROR_PENDING; break; case STATUS_CANCELLED: ret = NL_ERROR_CANCELED; break; case STATUS_INVALID_PARAMETER: ret = NL_ERROR_INVAL; break; case STATUS_OBJECT_NAME_EXISTS: ret = NL_ERROR_EXIST; break; default: ret = NL_ERROR_OTHER; break; } return ret; } openvswitch-2.5.0/datapath-windows/ovsext/Netlink/PaxHeaders.69223/Netlink.h0000644000000000000000000000013212664352753023635 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.201289156 openvswitch-2.5.0/datapath-windows/ovsext/Netlink/Netlink.h0000664000175000017500000002011712664352753025326 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NETLINK_H_ #define __NETLINK_H_ 1 #include "Types.h" #include "NetlinkProto.h" #include "NetlinkBuf.h" #include "..\..\include\OvsDpInterface.h" /* * Structure of any message passed between userspace and kernel. */ typedef struct _OVS_MESSAGE { NL_MSG_HDR nlMsg; GENL_MSG_HDR genlMsg; OVS_HDR ovsHdr; /* Variable length nl_attrs follow. */ } OVS_MESSAGE, *POVS_MESSAGE; /* * Structure of an error message sent as a reply from kernel. */ typedef struct _OVS_MESSAGE_ERROR { NL_MSG_HDR nlMsg; NL_MSG_ERR errorMsg; } OVS_MESSAGE_ERROR, *POVS_MESSAGE_ERROR; /* Netlink attribute types. */ typedef enum { NL_A_NO_ATTR = 0, NL_A_VAR_LEN, NL_A_UNSPEC, NL_A_U8, NL_A_U16, NL_A_BE16 = NL_A_U16, NL_A_U32, NL_A_BE32 = NL_A_U32, NL_A_U64, NL_A_BE64 = NL_A_U64, NL_A_STRING, NL_A_FLAG, NL_A_NESTED, N_NL_ATTR_TYPES } NL_ATTR_TYPE; /* Netlink attribute policy. * Specifies the policy for parsing for netlink attribute. */ typedef struct _NL_POLICY { NL_ATTR_TYPE type; UINT32 minLen; UINT32 maxLen; BOOLEAN optional; } NL_POLICY, *PNL_POLICY; /* This macro is careful to check for attributes with bad lengths. */ #define NL_ATTR_FOR_EACH(ITER, LEFT, ATTRS, ATTRS_LEN) \ for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ NlAttrIsValid(ITER, LEFT); \ (LEFT) -= NlAttrLenPad(ITER, LEFT), (ITER) = NlAttrNext(ITER)) /* This macro does not check for attributes with bad lengths. It should only * be used with messages from trusted sources or with messages that have * already been validated (e.g. with NL_ATTR_FOR_EACH). */ #define NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, ATTRS, ATTRS_LEN) \ for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ (LEFT) > 0; \ (LEFT) -= NLA_ALIGN((ITER)->nlaLen), (ITER) = NlAttrNext(ITER)) #define NL_ATTR_GET_AS(NLA, TYPE) \ (*(TYPE*) NlAttrGetUnspec(nla, sizeof(TYPE))) BOOLEAN NlFillOvsMsg(PNL_BUFFER nlBuf, UINT16 nlmsgType, UINT16 nlmsgFlags, UINT32 nlmsgSeq, UINT32 nlmsgPid, UINT8 genlCmd, UINT8 genlVer, UINT32 dpNo); BOOLEAN NlFillNlHdr(PNL_BUFFER nlBuf, UINT16 nlmsgType, UINT16 nlmsgFlags, UINT32 nlmsgSeq, UINT32 nlmsgPid); VOID NlBuildErrorMsg(POVS_MESSAGE msgIn, POVS_MESSAGE_ERROR msgOut, UINT errorCode); /* Netlink message accessing the payload */ PVOID NlMsgAt(const PNL_MSG_HDR nlh, UINT32 offset); UINT32 NlMsgSize(const PNL_MSG_HDR nlh); VOID NlMsgAlignSize(const PNL_MSG_HDR nlh); VOID NlMsgSetSize(const PNL_MSG_HDR nlh, UINT32 msgLen); PCHAR NlHdrPayload(const PNL_MSG_HDR nlh); UINT32 NlHdrPayloadLen(const PNL_MSG_HDR nlh); PNL_ATTR NlMsgAttrs(const PNL_MSG_HDR nlh); UINT32 NlMsgAttrsLen(const PNL_MSG_HDR nlh); /* Netlink message parse */ PNL_MSG_HDR NlMsgNext(const PNL_MSG_HDR nlh); INT NlAttrIsValid(const PNL_ATTR nla, UINT32 maxlen); UINT32 NlAttrLenPad(const PNL_ATTR nla, UINT32 maxlen); /* Netlink attribute parsing. */ UINT32 NlAttrMinLen(NL_ATTR_TYPE type); UINT32 NlAttrMinLen(NL_ATTR_TYPE type); PNL_ATTR NlAttrNext(const PNL_ATTR nla); UINT16 NlAttrType(const PNL_ATTR nla); PVOID NlAttrData(const PNL_ATTR nla); UINT32 NlAttrGetSize(const PNL_ATTR nla); const PVOID NlAttrGet(const PNL_ATTR nla); const PVOID NlAttrGetUnspec(const PNL_ATTR nla, UINT32 size); BE64 NlAttrGetBe64(const PNL_ATTR nla); BE32 NlAttrGetBe32(const PNL_ATTR nla); UINT8 NlAttrGetU8(const PNL_ATTR nla); UINT16 NlAttrGetU16(const PNL_ATTR nla); UINT32 NlAttrGetU32(const PNL_ATTR nla); UINT64 NlAttrGetU64(const PNL_ATTR nla); const PNL_ATTR NlAttrFind__(const PNL_ATTR attrs, UINT32 size, UINT16 type); const PNL_ATTR NlAttrFindNested(const PNL_ATTR nla, UINT16 type); BOOLEAN NlAttrParse(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy, PNL_ATTR attrs[], UINT32 numAttrs); BOOLEAN NlAttrParseNested(const PNL_MSG_HDR nlMsg, UINT32 attrOffset, UINT32 totalAttrLen, const NL_POLICY policy[], const UINT32 numPolicy, PNL_ATTR attrs[], UINT32 numAttrs); /* * -------------------------------------------------------------------------- * Returns the length of attribute. * -------------------------------------------------------------------------- */ static __inline UINT16 NlAttrLen(const PNL_ATTR nla) { return nla->nlaLen; } /* * --------------------------------------------------------------------------- * Default maximum payload size for each type of attribute. * --------------------------------------------------------------------------- */ UINT32 static __inline NlAttrSize(UINT32 payloadSize) { return NLA_HDRLEN + payloadSize; } /* * --------------------------------------------------------------------------- * Total length including padding. * --------------------------------------------------------------------------- */ UINT32 static __inline NlAttrTotalSize(UINT32 payloadSize) { return NLA_ALIGN(NlAttrSize(payloadSize)); } /* Netlink attribute validation */ BOOLEAN NlAttrValidate(const PNL_ATTR, const PNL_POLICY); /* Put APis */ BOOLEAN NlMsgPutNlHdr(PNL_BUFFER buf, PNL_MSG_HDR nlMsg); BOOLEAN NlMsgPutGenlHdr(PNL_BUFFER buf, PGENL_MSG_HDR genlMsg); BOOLEAN NlMsgPutOvsHdr(PNL_BUFFER buf, POVS_HDR ovsHdr); BOOLEAN NlMsgPutTail(PNL_BUFFER buf, const PCHAR data, UINT32 len); PCHAR NlMsgPutTailUninit(PNL_BUFFER buf, UINT32 len); PCHAR NlMsgPutTailUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len); BOOLEAN NlMsgPutTailUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len); BOOLEAN NlMsgPutTailFlag(PNL_BUFFER buf, UINT16 type); BOOLEAN NlMsgPutTailU8(PNL_BUFFER buf, UINT16 type, UINT8 value); BOOLEAN NlMsgPutTailU16(PNL_BUFFER buf, UINT16 type, UINT16 value); BOOLEAN NlMsgPutTailU32(PNL_BUFFER buf, UINT16 type, UINT32 value); BOOLEAN NlMsgPutTailU64(PNL_BUFFER buf, UINT16 type, UINT64 value); BOOLEAN NlMsgPutTailString(PNL_BUFFER buf, UINT16 type, PCHAR value); BOOLEAN NlMsgPutHead(PNL_BUFFER buf, const PCHAR data, UINT32 len); PCHAR NlMsgPutHeadUninit(PNL_BUFFER buf, UINT32 len); PCHAR NlMsgPutHeadUnspecUninit(PNL_BUFFER buf, UINT16 type, UINT16 len); BOOLEAN NlMsgPutHeadUnspec(PNL_BUFFER buf, UINT16 type, PCHAR data, UINT16 len); BOOLEAN NlMsgPutHeadFlag(PNL_BUFFER buf, UINT16 type); BOOLEAN NlMsgPutHeadU8(PNL_BUFFER buf, UINT16 type, UINT8 value); BOOLEAN NlMsgPutHeadU16(PNL_BUFFER buf, UINT16 type, UINT16 value); BOOLEAN NlMsgPutHeadU32(PNL_BUFFER buf, UINT16 type, UINT32 value); BOOLEAN NlMsgPutHeadU64(PNL_BUFFER buf, UINT16 type, UINT64 value); BOOLEAN NlMsgPutHeadString(PNL_BUFFER buf, UINT16 type, PCHAR value); UINT32 NlMsgStartNested(PNL_BUFFER buf, UINT16 type); VOID NlMsgEndNested(PNL_BUFFER buf, UINT32 offset); BOOLEAN NlMsgPutNested(PNL_BUFFER buf, UINT16 type, const PVOID data, UINT32 size); /* These variants are convenient for iterating nested attributes. */ #define NL_NESTED_FOR_EACH(ITER, LEFT, A) \ NL_ATTR_FOR_EACH(ITER, LEFT, NlAttrGet(A), NlAttrGetSize(A)) #define NL_NESTED_FOR_EACH_UNSAFE(ITER, LEFT, A) \ NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, NlAttrGet(A), NlAttrGetSize(A)) #endif /* __NETLINK_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/PacketIO.c0000644000000000000000000000013212631676262022255 xustar0030 mtime=1449622706.966439188 30 atime=1456592667.311090405 30 ctime=1456594660.209289493 openvswitch-2.5.0/datapath-windows/ovsext/PacketIO.c0000664000175000017500000004636512631676262023763 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * This file contains the implementation of the datapath/forwarding * functionality of the OVS. */ #include "precomp.h" #include "Switch.h" #include "Vport.h" #include "NetProto.h" #include "User.h" #include "PacketIO.h" #include "Flow.h" #include "Event.h" #include "User.h" /* Due to an imported header file */ #pragma warning( disable:4505 ) #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_DISPATCH #include "Debug.h" extern NDIS_STRING ovsExtGuidUC; extern NDIS_STRING ovsExtFriendlyNameUC; static VOID OvsFinalizeCompletionList(OvsCompletionList *completionList); static VOID OvsCompleteNBLIngress(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST netBufferLists, ULONG sendCompleteFlags); static NTSTATUS OvsCreateNewNBLsFromMultipleNBs( POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST *curNbl, PNET_BUFFER_LIST *nextNbl); __inline VOID OvsInitCompletionList(OvsCompletionList *completionList, POVS_SWITCH_CONTEXT switchContext, ULONG sendCompleteFlags) { ASSERT(completionList); completionList->dropNbl = NULL; completionList->dropNblNext = &completionList->dropNbl; completionList->switchContext = switchContext; completionList->sendCompleteFlags = sendCompleteFlags; } /* Utility function used to complete an NBL. */ __inline VOID OvsAddPktCompletionList(OvsCompletionList *completionList, BOOLEAN incoming, NDIS_SWITCH_PORT_ID sourcePort, PNET_BUFFER_LIST netBufferList, UINT32 netBufferListCount, PNDIS_STRING filterReason) { POVS_BUFFER_CONTEXT ctx; /* XXX: We handle one NBL at a time. */ ASSERT(netBufferList->Next == NULL); /* Make sure it has a context. */ ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(netBufferList); ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC); completionList->switchContext->NdisSwitchHandlers.ReportFilteredNetBufferLists( completionList->switchContext->NdisSwitchContext, &ovsExtGuidUC, &ovsExtFriendlyNameUC, sourcePort, incoming ? NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING : 0, netBufferListCount, netBufferList, filterReason); *completionList->dropNblNext = netBufferList; completionList->dropNblNext = &netBufferList->Next; ASSERT(completionList->dropNbl); } static __inline VOID OvsReportNBLIngressError(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST nblList, PNDIS_STRING filterReason, NDIS_STATUS error) { PNET_BUFFER_LIST nbl = nblList; while (nbl) { PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl); nbl->Status = error; /* This can be optimized by batching NBL's from the same * SourcePortId. */ switchContext->NdisSwitchHandlers.ReportFilteredNetBufferLists( switchContext->NdisSwitchContext, &ovsExtGuidUC, &ovsExtFriendlyNameUC, fwdDetail->SourcePortId, NDIS_SWITCH_REPORT_FILTERED_NBL_FLAGS_IS_INCOMING, 1 /*Nbl count.*/, nbl, filterReason); nbl = NET_BUFFER_LIST_NEXT_NBL(nbl); } } static __inline ULONG OvsGetSendCompleteFlags(ULONG sendFlags) { BOOLEAN dispatch, sameSource; ULONG sendCompleteFlags; dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(sendFlags); sendCompleteFlags = (dispatch ? NDIS_SEND_COMPLETE_FLAGS_DISPATCH_LEVEL : 0); sameSource = NDIS_TEST_SEND_FLAG(sendFlags, NDIS_SEND_FLAGS_SWITCH_SINGLE_SOURCE); sendCompleteFlags |= (sameSource ? NDIS_SEND_COMPLETE_FLAGS_SWITCH_SINGLE_SOURCE : 0); return sendCompleteFlags; } VOID OvsSendNBLIngress(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST netBufferLists, ULONG sendFlags) { if (switchContext->dataFlowState == OvsSwitchPaused) { /* If a filter module is in the Paused state, the filter driver must not * originate any send requests for that filter module. If NDIS calls * FilterSendNetBufferLists, the driver must not call * NdisFSendNetBufferLists to pass on the data until the driver is * restarted. The driver should call NdisFSendNetBufferListsComplete * immediately to complete the send operation. It should set the * complete status in each NET_BUFFER_LIST structure to * NDIS_STATUS_PAUSED. * * http://msdn.microsoft.com/en-us/library/windows/hardware/ * ff549966(v=vs.85).aspx */ NDIS_STRING filterReason; ULONG sendCompleteFlags = OvsGetSendCompleteFlags(sendFlags); RtlInitUnicodeString(&filterReason, L"Switch state PAUSED, drop before FSendNBL."); OvsReportNBLIngressError(switchContext, netBufferLists, &filterReason, NDIS_STATUS_PAUSED); OvsCompleteNBLIngress(switchContext, netBufferLists, sendCompleteFlags); return; } ASSERT(switchContext->dataFlowState == OvsSwitchRunning); NdisFSendNetBufferLists(switchContext->NdisFilterHandle, netBufferLists, NDIS_DEFAULT_PORT_NUMBER, sendFlags); } static __inline VOID OvsStartNBLIngressError(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST nblList, ULONG sendCompleteFlags, PNDIS_STRING filterReason, NDIS_STATUS error) { ASSERT(error); OvsReportNBLIngressError(switchContext, nblList, filterReason, error); NdisFSendNetBufferListsComplete(switchContext->NdisFilterHandle, nblList, sendCompleteFlags); } static VOID OvsAppendNativeForwardedPacket(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, PNET_BUFFER_LIST *nativeNbls, ULONG flags, BOOLEAN isRecv) { POVS_BUFFER_CONTEXT ctx = { 0 }; NDIS_STRING filterReason; *nativeNbls = curNbl; nativeNbls = &(curNbl->Next); ctx = OvsInitExternalNBLContext(switchContext, curNbl, isRecv); if (ctx == NULL) { RtlInitUnicodeString(&filterReason, L"Cannot allocate native NBL context."); OvsStartNBLIngressError(switchContext, curNbl, flags, &filterReason, NDIS_STATUS_RESOURCES); } } static VOID OvsStartNBLIngress(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST netBufferLists, ULONG SendFlags) { NDIS_SWITCH_PORT_ID sourcePort = 0; NDIS_SWITCH_NIC_INDEX sourceIndex = 0; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO fwdDetail; PNET_BUFFER_LIST curNbl = NULL, nextNbl = NULL; ULONG sendCompleteFlags; UCHAR dispatch; LOCK_STATE_EX lockState, dpLockState; NDIS_STATUS status; NDIS_STRING filterReason; LIST_ENTRY missedPackets; UINT32 num = 0; OvsCompletionList completionList; #if (NDIS_SUPPORT_NDIS640) PNET_BUFFER_LIST nativeForwardedNbls = NULL; PNET_BUFFER_LIST *nextNativeForwardedNbl = &nativeForwardedNbls; #endif dispatch = NDIS_TEST_SEND_AT_DISPATCH_LEVEL(SendFlags)? NDIS_RWL_AT_DISPATCH_LEVEL : 0; sendCompleteFlags = OvsGetSendCompleteFlags(SendFlags); SendFlags |= NDIS_SEND_FLAGS_SWITCH_DESTINATION_GROUP; InitializeListHead(&missedPackets); OvsInitCompletionList(&completionList, switchContext, sendCompleteFlags); for (curNbl = netBufferLists; curNbl != NULL; curNbl = nextNbl) { POVS_VPORT_ENTRY vport; UINT32 portNo; OVS_DATAPATH *datapath = &switchContext->datapath; OVS_PACKET_HDR_INFO layers; OvsFlowKey key; UINT64 hash; PNET_BUFFER curNb; POVS_BUFFER_CONTEXT ctx; nextNbl = curNbl->Next; curNbl->Next = NULL; fwdDetail = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(curNbl); sourcePort = fwdDetail->SourcePortId; sourceIndex = (NDIS_SWITCH_NIC_INDEX)fwdDetail->SourceNicIndex; #if (NDIS_SUPPORT_NDIS640) if (fwdDetail->NativeForwardingRequired) { /* Add current NBL to those that require native forwarding. */ OvsAppendNativeForwardedPacket( switchContext, curNbl, nextNativeForwardedNbl, sendCompleteFlags, sourcePort == switchContext->virtualExternalPortId); continue; } #endif /* NDIS_SUPPORT_NDIS640 */ ctx = OvsInitExternalNBLContext(switchContext, curNbl, sourcePort == switchContext->virtualExternalPortId); if (ctx == NULL) { RtlInitUnicodeString(&filterReason, L"Cannot allocate external NBL context."); OvsStartNBLIngressError(switchContext, curNbl, sendCompleteFlags, &filterReason, NDIS_STATUS_RESOURCES); continue; } /* Ethernet Header is a guaranteed safe access. */ curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); if (curNb->Next != NULL) { /* Create a NET_BUFFER_LIST for each NET_BUFFER. */ status = OvsCreateNewNBLsFromMultipleNBs(switchContext, &curNbl, &nextNbl); if (!NT_SUCCESS(status)) { RtlInitUnicodeString(&filterReason, L"Cannot allocate NBLs with single NB."); OvsStartNBLIngressError(switchContext, curNbl, sendCompleteFlags, &filterReason, NDIS_STATUS_RESOURCES); continue; } } { OvsFlow *flow; /* Take the DispatchLock so none of the VPORTs disconnect while * we are setting destination ports. * * XXX: acquire/release the dispatch lock for a "batch" of packets * rather than for each packet. */ NdisAcquireRWLockRead(switchContext->dispatchLock, &lockState, dispatch); vport = OvsFindVportByPortIdAndNicIndex(switchContext, sourcePort, sourceIndex); if (vport == NULL || vport->ovsState != OVS_STATE_CONNECTED) { RtlInitUnicodeString(&filterReason, L"OVS-Cannot forward packet from unknown source port"); goto dropit; } else { portNo = vport->portNo; } vport->stats.rxPackets++; vport->stats.rxBytes += NET_BUFFER_DATA_LENGTH(curNb); status = OvsExtractFlow(curNbl, vport->portNo, &key, &layers, NULL); if (status != NDIS_STATUS_SUCCESS) { RtlInitUnicodeString(&filterReason, L"OVS-Flow extract failed"); goto dropit; } ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL); OvsAcquireDatapathRead(datapath, &dpLockState, TRUE); flow = OvsLookupFlow(datapath, &key, &hash, FALSE); if (flow) { OvsFlowUsed(flow, curNbl, &layers); datapath->hits++; /* If successful, OvsActionsExecute() consumes the NBL. * Otherwise, it adds it to the completionList. No need to * check the return value. */ OvsActionsExecute(switchContext, &completionList, curNbl, portNo, SendFlags, &key, &hash, &layers, flow->actions, flow->actionsLen); OvsReleaseDatapath(datapath, &dpLockState); NdisReleaseRWLock(switchContext->dispatchLock, &lockState); continue; } else { OvsReleaseDatapath(datapath, &dpLockState); datapath->misses++; status = OvsCreateAndAddPackets(NULL, 0, OVS_PACKET_CMD_MISS, vport, &key, curNbl, sourcePort == switchContext->virtualExternalPortId, &layers, switchContext, &missedPackets, &num); if (status == NDIS_STATUS_SUCCESS) { /* Complete the packet since it was copied to user * buffer. */ RtlInitUnicodeString(&filterReason, L"OVS-Dropped since packet was copied to userspace"); } else { RtlInitUnicodeString(&filterReason, L"OVS-Dropped due to failure to queue to userspace"); } goto dropit; } dropit: OvsAddPktCompletionList(&completionList, TRUE, sourcePort, curNbl, 0, &filterReason); NdisReleaseRWLock(switchContext->dispatchLock, &lockState); } } #if (NDIS_SUPPORT_NDIS640) if (nativeForwardedNbls) { /* This is NVGRE encapsulated traffic and is forwarded to NDIS * in order to be handled by the HNV module. */ OvsSendNBLIngress(switchContext, nativeForwardedNbls, SendFlags); } #endif /* NDIS_SUPPORT_NDIS640 */ /* Queue the missed packets. */ OvsQueuePackets(&missedPackets, num); OvsFinalizeCompletionList(&completionList); } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterSendNetBufferLists Function. * -------------------------------------------------------------------------- */ VOID OvsExtSendNBL(NDIS_HANDLE filterModuleContext, PNET_BUFFER_LIST netBufferLists, NDIS_PORT_NUMBER portNumber, ULONG sendFlags) { UNREFERENCED_PARAMETER(portNumber); /* 'filterModuleContext' is the switch context that gets created in the * AttachHandler. */ POVS_SWITCH_CONTEXT switchContext; switchContext = (POVS_SWITCH_CONTEXT) filterModuleContext; if (switchContext->dataFlowState == OvsSwitchPaused) { NDIS_STRING filterReason; ULONG sendCompleteFlags = OvsGetSendCompleteFlags(sendFlags); RtlInitUnicodeString(&filterReason, L"Switch state PAUSED, drop on ingress."); OvsStartNBLIngressError(switchContext, netBufferLists, sendCompleteFlags, &filterReason, NDIS_STATUS_PAUSED); return; } ASSERT(switchContext->dataFlowState == OvsSwitchRunning); OvsStartNBLIngress(switchContext, netBufferLists, sendFlags); } static VOID OvsCompleteNBLIngress(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST netBufferLists, ULONG sendCompleteFlags) { PNET_BUFFER_LIST curNbl = NULL, nextNbl = NULL; OvsCompletionList newList; newList.dropNbl = NULL; newList.dropNblNext = &newList.dropNbl; for (curNbl = netBufferLists; curNbl != NULL; curNbl = nextNbl) { nextNbl = curNbl->Next; curNbl->Next = NULL; curNbl = OvsCompleteNBL(switchContext, curNbl, TRUE); if (curNbl != NULL) { /* NBL originated from the upper layer. */ *newList.dropNblNext = curNbl; newList.dropNblNext = &curNbl->Next; } } /* Complete the NBL's that were sent by the upper layer. */ if (newList.dropNbl != NULL) { NdisFSendNetBufferListsComplete(switchContext->NdisFilterHandle, newList.dropNbl, sendCompleteFlags); } } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterSendNetBufferListsComplete function. * -------------------------------------------------------------------------- */ VOID OvsExtSendNBLComplete(NDIS_HANDLE filterModuleContext, PNET_BUFFER_LIST netBufferLists, ULONG sendCompleteFlags) { OvsCompleteNBLIngress((POVS_SWITCH_CONTEXT)filterModuleContext, netBufferLists, sendCompleteFlags); } VOID OvsFinalizeCompletionList(OvsCompletionList *completionList) { if (completionList->dropNbl != NULL) { OvsCompleteNBLIngress(completionList->switchContext, completionList->dropNbl, completionList->sendCompleteFlags); completionList->dropNbl = NULL; completionList->dropNblNext = &completionList->dropNbl; } } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterCancelSendNetBufferLists function. * * "If a filter driver specifies a FilterSendNetBufferLists function and it * queues send requests, it must also specify a * FilterCancelSendNetBufferLists function." * * http://msdn.microsoft.com/en-us/library/windows/hardware/ * ff549966(v=vs.85).aspx * -------------------------------------------------------------------------- */ VOID OvsExtCancelSendNBL(NDIS_HANDLE filterModuleContext, PVOID CancelId) { UNREFERENCED_PARAMETER(filterModuleContext); UNREFERENCED_PARAMETER(CancelId); /* All send requests get completed synchronously, so there is no need to * implement this callback. */ } static NTSTATUS OvsCreateNewNBLsFromMultipleNBs(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST *curNbl, PNET_BUFFER_LIST *nextNbl) { NTSTATUS status = STATUS_SUCCESS; PNET_BUFFER_LIST newNbls = NULL; PNET_BUFFER_LIST lastNbl = NULL; PNET_BUFFER_LIST nbl = NULL; BOOLEAN error = TRUE; do { /* Create new NBLs from curNbl with multiple net buffers. */ newNbls = OvsPartialCopyToMultipleNBLs(switchContext, *curNbl, 0, 0, TRUE); if (NULL == newNbls) { OVS_LOG_ERROR("Failed to allocate NBLs with single NB."); status = NDIS_STATUS_RESOURCES; break; } nbl = newNbls; while (nbl) { lastNbl = nbl; nbl = NET_BUFFER_LIST_NEXT_NBL(nbl); } lastNbl->Next = *nextNbl; *nextNbl = newNbls->Next; OvsCompleteNBL(switchContext, *curNbl, TRUE); *curNbl = newNbls; (*curNbl)->Next = NULL; error = FALSE; } while (error); return status; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Gre.c0000644000000000000000000000013112664352753021334 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 29 ctime=1456594660.19328882 openvswitch-2.5.0/datapath-windows/ovsext/Gre.c0000664000175000017500000003624112664352753023033 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2015 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Atomic.h" #include "Checksum.h" #include "Flow.h" #include "Gre.h" #include "IpHelper.h" #include "NetProto.h" #include "PacketIO.h" #include "PacketParser.h" #include "Switch.h" #include "User.h" #include "Util.h" #include "Vport.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_GRE #include "Debug.h" static NDIS_STATUS OvsDoEncapGre(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, const OvsIPv4TunnelKey *tunKey, const POVS_FWD_INFO fwdInfo, POVS_PACKET_HDR_INFO layers, POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST *newNbl); /* * -------------------------------------------------------------------------- * OvsInitGreTunnel -- * Initialize GRE tunnel module. * -------------------------------------------------------------------------- */ NTSTATUS OvsInitGreTunnel(POVS_VPORT_ENTRY vport) { POVS_GRE_VPORT grePort; grePort = (POVS_GRE_VPORT)OvsAllocateMemoryWithTag(sizeof(*grePort), OVS_GRE_POOL_TAG); if (!grePort) { OVS_LOG_ERROR("Insufficient memory, can't allocate OVS_GRE_VPORT"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(grePort, sizeof(*grePort)); vport->priv = (PVOID)grePort; return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsCleanupGreTunnel -- * Cleanup GRE Tunnel module. * -------------------------------------------------------------------------- */ void OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport) { if (vport->ovsType != OVS_VPORT_TYPE_GRE || vport->priv == NULL) { return; } OvsFreeMemoryWithTag(vport->priv, OVS_GRE_POOL_TAG); vport->priv = NULL; } /* * -------------------------------------------------------------------------- * OvsEncapGre -- * Encapsulates a packet with an GRE header. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, PNET_BUFFER_LIST *newNbl) { OVS_FWD_INFO fwdInfo; NDIS_STATUS status; status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); if (status != STATUS_SUCCESS) { OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); return NDIS_STATUS_FAILURE; } status = OvsDoEncapGre(vport, curNbl, tunKey, &fwdInfo, layers, switchContext, newNbl); return status; } /* * -------------------------------------------------------------------------- * OvsDoEncapGre -- * Internal utility function which actually does the GRE encap. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsDoEncapGre(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, const OvsIPv4TunnelKey *tunKey, const POVS_FWD_INFO fwdInfo, POVS_PACKET_HDR_INFO layers, POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST *newNbl) { NDIS_STATUS status; PNET_BUFFER curNb; PMDL curMdl; PUINT8 bufferStart; EthHdr *ethHdr; IPHdr *ipHdr; PGREHdr greHdr; POVS_GRE_VPORT vportGre; UINT32 headRoom = GreTunHdrSize(tunKey->flags); #if DBG UINT32 counterHeadRoom; #endif UINT32 packetLength; ULONG mss = 0; ASSERT(*newNbl == NULL); curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); packetLength = NET_BUFFER_DATA_LENGTH(curNb); if (layers->isTcp) { NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO tsoInfo; tsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpLargeSendNetBufferListInfo); switch (tsoInfo.Transmit.Type) { case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: mss = tsoInfo.LsoV1Transmit.MSS; break; case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: mss = tsoInfo.LsoV2Transmit.MSS; break; default: OVS_LOG_ERROR("Unknown LSO transmit type:%d", tsoInfo.Transmit.Type); } OVS_LOG_TRACE("MSS %u packet len %u", mss, packetLength); if (mss) { OVS_LOG_TRACE("l4Offset %d", layers->l4Offset); *newNbl = OvsTcpSegmentNBL(switchContext, curNbl, layers, mss, headRoom); if (*newNbl == NULL) { OVS_LOG_ERROR("Unable to segment NBL"); return NDIS_STATUS_FAILURE; } /* Clear out LSO flags after this point */ NET_BUFFER_LIST_INFO(*newNbl, TcpLargeSendNetBufferListInfo) = 0; } } vportGre = (POVS_GRE_VPORT)GetOvsVportPriv(vport); ASSERT(vportGre); /* If we didn't split the packet above, make a copy now */ if (*newNbl == NULL) { *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom, FALSE /*NBL info*/); if (*newNbl == NULL) { OVS_LOG_ERROR("Unable to copy NBL"); return NDIS_STATUS_FAILURE; } /* * To this point we do not have GRE hardware offloading. * Apply defined checksums */ curNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); curMdl = NET_BUFFER_CURRENT_MDL(curNb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); if (!bufferStart) { status = NDIS_STATUS_RESOURCES; goto ret_error; } NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); if (layers->isIPv4) { IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); if (csumInfo.Transmit.IpHeaderChecksum) { ip->check = 0; ip->check = IPChecksum((UINT8 *)ip, 4 * ip->ihl, 0); } if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, IPPROTO_TCP, csumLength); tcp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); udp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, IPPROTO_UDP, csumLength); udp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } } else if (layers->isIPv6) { IPv6Hdr *ip = (IPv6Hdr *)(bufferStart + layers->l3Offset); if (layers->isTcp && csumInfo.Transmit.TcpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); TCPHdr *tcp = (TCPHdr *)(bufferStart + layers->l4Offset); tcp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, (UINT32 *) &ip->daddr, IPPROTO_TCP, csumLength); tcp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } else if (layers->isUdp && csumInfo.Transmit.UdpChecksum) { UINT16 csumLength = (UINT16)(packetLength - layers->l4Offset); UDPHdr *udp = (UDPHdr *)((PCHAR)ip + sizeof *ip); udp->check = IPv6PseudoChecksum((UINT32 *) &ip->saddr, (UINT32 *) &ip->daddr, IPPROTO_UDP, csumLength); udp->check = CalculateChecksumNB(curNb, csumLength, (UINT32)(layers->l4Offset)); } } /* Clear out TcpIpChecksumNetBufferListInfo flag */ NET_BUFFER_LIST_INFO(*newNbl, TcpIpChecksumNetBufferListInfo) = 0; } curNbl = *newNbl; for (curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curNb != NULL; curNb = curNb->Next) { #if DBG counterHeadRoom = headRoom; #endif status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL); if (status != NDIS_STATUS_SUCCESS) { goto ret_error; } curMdl = NET_BUFFER_CURRENT_MDL(curNb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); if (!bufferStart) { status = NDIS_STATUS_RESOURCES; goto ret_error; } bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); if (NET_BUFFER_NEXT_NB(curNb)) { OVS_LOG_TRACE("nb length %u next %u", NET_BUFFER_DATA_LENGTH(curNb), NET_BUFFER_DATA_LENGTH(curNb->Next)); } /* L2 header */ ethHdr = (EthHdr *)bufferStart; ASSERT(((PCHAR)&fwdInfo->dstMacAddr + sizeof fwdInfo->dstMacAddr) == (PCHAR)&fwdInfo->srcMacAddr); NdisMoveMemory(ethHdr->Destination, fwdInfo->dstMacAddr, sizeof ethHdr->Destination + sizeof ethHdr->Source); ethHdr->Type = htons(ETH_TYPE_IPV4); #if DBG counterHeadRoom -= sizeof *ethHdr; #endif /* IP header */ ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); ipHdr->ihl = sizeof *ipHdr / 4; ipHdr->version = IPPROTO_IPV4; ipHdr->tos = tunKey->tos; ipHdr->tot_len = htons(NET_BUFFER_DATA_LENGTH(curNb) - sizeof *ethHdr); ipHdr->id = (uint16)atomic_add64(&vportGre->ipId, NET_BUFFER_DATA_LENGTH(curNb)); ipHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ? IP_DF_NBO : 0; ipHdr->ttl = tunKey->ttl ? tunKey->ttl : 64; ipHdr->protocol = IPPROTO_GRE; ASSERT(tunKey->dst == fwdInfo->dstIpAddr); ASSERT(tunKey->src == fwdInfo->srcIpAddr || tunKey->src == 0); ipHdr->saddr = fwdInfo->srcIpAddr; ipHdr->daddr = fwdInfo->dstIpAddr; ipHdr->check = 0; ipHdr->check = IPChecksum((UINT8 *)ipHdr, sizeof *ipHdr, 0); #if DBG counterHeadRoom -= sizeof *ipHdr; #endif /* GRE header */ greHdr = (GREHdr *)((PCHAR)ipHdr + sizeof *ipHdr); greHdr->flags = OvsTunnelFlagsToGreFlags(tunKey->flags); greHdr->protocolType = GRE_NET_TEB; #if DBG counterHeadRoom -= sizeof *greHdr; #endif PCHAR currentOffset = (PCHAR)greHdr + sizeof *greHdr; if (tunKey->flags & OVS_TNL_F_CSUM) { RtlZeroMemory(currentOffset, 4); currentOffset += 4; #if DBG counterHeadRoom -= 4; #endif } if (tunKey->flags & OVS_TNL_F_KEY) { RtlZeroMemory(currentOffset, 4); UINT32 key = (tunKey->tunnelId >> 32); RtlCopyMemory(currentOffset, &key, sizeof key); currentOffset += 4; #if DBG counterHeadRoom -= 4; #endif } #if DBG ASSERT(counterHeadRoom == 0); #endif } return STATUS_SUCCESS; ret_error: OvsCompleteNBL(switchContext, *newNbl, TRUE); *newNbl = NULL; return status; } NDIS_STATUS OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, PNET_BUFFER_LIST *newNbl) { PNET_BUFFER curNb; PMDL curMdl; EthHdr *ethHdr; IPHdr *ipHdr; GREHdr *greHdr; UINT32 tunnelSize = 0, packetLength = 0; UINT32 headRoom = 0; PUINT8 bufferStart; NDIS_STATUS status; curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); packetLength = NET_BUFFER_DATA_LENGTH(curNb); tunnelSize = GreTunHdrSize(tunKey->flags); if (packetLength <= tunnelSize) { return NDIS_STATUS_INVALID_LENGTH; } /* * Create a copy of the NBL so that we have all the headers in one MDL. */ *newNbl = OvsPartialCopyNBL(switchContext, curNbl, tunnelSize + OVS_DEFAULT_COPY_SIZE, 0, TRUE /*copy NBL info */); if (*newNbl == NULL) { return NDIS_STATUS_RESOURCES; } curNbl = *newNbl; curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curMdl = NET_BUFFER_CURRENT_MDL(curNb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority) + NET_BUFFER_CURRENT_MDL_OFFSET(curNb); if (!bufferStart) { status = NDIS_STATUS_RESOURCES; goto dropNbl; } ethHdr = (EthHdr *)bufferStart; headRoom += sizeof *ethHdr; ipHdr = (IPHdr *)((PCHAR)ethHdr + sizeof *ethHdr); tunKey->src = ipHdr->saddr; tunKey->dst = ipHdr->daddr; tunKey->tos = ipHdr->tos; tunKey->ttl = ipHdr->ttl; tunKey->pad = 0; headRoom += sizeof *ipHdr; greHdr = (GREHdr *)((PCHAR)ipHdr + sizeof *ipHdr); headRoom += sizeof *greHdr; /* Validate if GRE header protocol type. */ if (greHdr->protocolType != GRE_NET_TEB) { status = STATUS_NDIS_INVALID_PACKET; goto dropNbl; } PCHAR currentOffset = (PCHAR)greHdr + sizeof *greHdr; if (greHdr->flags & GRE_CSUM) { tunKey->flags |= OVS_TNL_F_CSUM; currentOffset += 4; headRoom += 4; } if (greHdr->flags & GRE_KEY) { tunKey->flags |= OVS_TNL_F_KEY; UINT32 key = 0; RtlCopyMemory(&key, currentOffset, 4); tunKey->tunnelId = (UINT64)key << 32; currentOffset += 4; headRoom += 4; } /* Clear out the receive flag for the inner packet. */ NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = 0; NdisAdvanceNetBufferDataStart(curNb, GreTunHdrSize(tunKey->flags), FALSE, NULL); ASSERT(headRoom == GreTunHdrSize(tunKey->flags)); return NDIS_STATUS_SUCCESS; dropNbl: OvsCompleteNBL(switchContext, *newNbl, TRUE); *newNbl = NULL; return status; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Debug.c0000644000000000000000000000013112631676262021643 xustar0030 mtime=1449622706.938438204 29 atime=1456592667.30709024 30 ctime=1456594660.177288147 openvswitch-2.5.0/datapath-windows/ovsext/Debug.c0000664000175000017500000000301712631676262023335 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Debug.h" #ifdef DBG #define OVS_DBG_DEFAULT OVS_DBG_INFO #else #define OVS_DBG_DEFAULT OVS_DBG_ERROR #endif UINT32 ovsLogFlags = 0xffffffff; UINT32 ovsLogLevel = OVS_DBG_DEFAULT; #define OVS_LOG_BUFFER_SIZE 384 /* * -------------------------------------------------------------------------- * OvsLog -- * Utility function to log to the Windows debug console. * -------------------------------------------------------------------------- */ VOID OvsLog(UINT32 level, UINT32 flag, CHAR *funcName, UINT32 line, CHAR *format, ...) { va_list args; CHAR buf[OVS_LOG_BUFFER_SIZE]; if (level > ovsLogLevel || (ovsLogFlags & flag) == 0) { return; } buf[0] = 0; va_start(args, format); RtlStringCbVPrintfA(buf, sizeof (buf), format, args); va_end(args); DbgPrintEx(DPFLTR_IHVNETWORK_ID, level, "%s:%lu %s\n", funcName, line, buf); } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Gre.h0000644000000000000000000000013212652645507021341 xustar0030 mtime=1454066503.406754588 30 atime=1456592356.374330686 30 ctime=1456594660.189288653 openvswitch-2.5.0/datapath-windows/ovsext/Gre.h0000664000175000017500000000565312652645507023042 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2015 Cloudbase Solutions Srl * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __GRE_H_ #define __GRE_H_ 1 #include "NetProto.h" #include "Flow.h" typedef struct _OVS_GRE_VPORT { UINT64 ipId; /* * To be filled */ } OVS_GRE_VPORT, *POVS_GRE_VPORT; /* GRE RFC 2890 header based on http://tools.ietf.org/html/rfc2890 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |C| |K|S| Reserved0 | Ver | Protocol Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Checksum (optional) | Reserved1 (Optional) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Key (optional) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Sequence Number (Optional) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ typedef struct GREHdr { UINT16 flags; UINT16 protocolType; } GREHdr, *PGREHdr; /* Transparent Ethernet Bridging */ #define GRE_NET_TEB 0x5865 /* GRE Flags*/ #define GRE_CSUM 0x0080 #define GRE_KEY 0x0020 NTSTATUS OvsInitGreTunnel(POVS_VPORT_ENTRY vport); VOID OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport); void OvsCleanupGreTunnel(POVS_VPORT_ENTRY vport); NDIS_STATUS OvsEncapGre(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, PNET_BUFFER_LIST *newNbl); NDIS_STATUS OvsDecapGre(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, PNET_BUFFER_LIST *newNbl); static __inline UINT16 OvsTunnelFlagsToGreFlags(UINT16 tunnelflags) { UINT16 flags = 0; if (tunnelflags & OVS_TNL_F_CSUM) flags |= GRE_CSUM; if (tunnelflags & OVS_TNL_F_KEY) flags |= GRE_KEY; return flags; } static __inline UINT32 GreTunHdrSize(UINT16 flags) { UINT32 sum = sizeof(EthHdr) + sizeof(IPHdr) + sizeof(GREHdr); sum += (flags & OVS_TNL_F_CSUM) ? 4 : 0; sum += (flags & OVS_TNL_F_KEY) ? 4 : 0; return sum; } #endif /*__GRE_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/IpHelper.c0000644000000000000000000000013112652645507022326 xustar0030 mtime=1454066503.406754588 30 atime=1456592667.311090405 29 ctime=1456594660.19328882 openvswitch-2.5.0/datapath-windows/ovsext/IpHelper.c0000664000175000017500000014432712652645507024032 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "IpHelper.h" #include "Switch.h" #include "Jhash.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_IPHELPER #include "Debug.h" /* * Fow now, we assume only one internal adapter */ KSTART_ROUTINE OvsStartIpHelper; /* * Only when the internal IP is configured and virtual * internal port is connected, the IP helper request can be * queued. */ static BOOLEAN ovsInternalIPConfigured; static BOOLEAN ovsInternalAdapterUp; static GUID ovsInternalNetCfgId; static MIB_IF_ROW2 ovsInternalRow; static MIB_IPINTERFACE_ROW ovsInternalIPRow; /* we only keep one internal IP for reference, it will not be used for * determining SRC IP of Tunnel */ static UINT32 ovsInternalIP; /* * FWD_ENTRY --------> IPFORWARD_ENTRY * | * |--------------------------------------> IPENIGH_ENTRY * * IPFORWARD_ENTRY ------> FWD_ENTRY LIST with same IPFORWARD * * IPNEIGH_ENTRY ------> FWD_ENTRY LIST with same IPNEIGH * */ static PLIST_ENTRY ovsFwdHashTable; // based on DST IP static PLIST_ENTRY ovsRouteHashTable; // based on DST PREFIX static PLIST_ENTRY ovsNeighHashTable; // based on DST IP static LIST_ENTRY ovsSortedIPNeighList; static UINT32 ovsNumFwdEntries; static PNDIS_RW_LOCK_EX ovsTableLock; static NDIS_SPIN_LOCK ovsIpHelperLock; static LIST_ENTRY ovsIpHelperRequestList; static UINT32 ovsNumIpHelperRequests; static HANDLE ipInterfaceNotificationHandle; static HANDLE ipRouteNotificationHandle; static HANDLE unicastIPNotificationHandle; static OVS_IP_HELPER_THREAD_CONTEXT ovsIpHelperThreadContext; static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix); static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf); static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr); static VOID OvsCleanupIpHelperRequestList(VOID); static VOID OvsCleanupFwdTable(VOID); static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn); static VOID OvsDumpIfRow(PMIB_IF_ROW2 ifRow) { OVS_LOG_INFO("InterfaceLuid: NetLuidIndex: %d, type: %d", ifRow->InterfaceLuid.Info.NetLuidIndex, ifRow->InterfaceLuid.Info.IfType); OVS_LOG_INFO("InterfaceIndex: %d", ifRow->InterfaceIndex); OVS_LOG_INFO("Interface GUID: %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", ifRow->InterfaceGuid.Data1, ifRow->InterfaceGuid.Data2, ifRow->InterfaceGuid.Data3, *(UINT16 *)ifRow->InterfaceGuid.Data4, ifRow->InterfaceGuid.Data4[2], ifRow->InterfaceGuid.Data4[3], ifRow->InterfaceGuid.Data4[4], ifRow->InterfaceGuid.Data4[5], ifRow->InterfaceGuid.Data4[6], ifRow->InterfaceGuid.Data4[7]); OVS_LOG_INFO("Perm MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", ifRow->PermanentPhysicalAddress[0], ifRow->PermanentPhysicalAddress[1], ifRow->PermanentPhysicalAddress[2], ifRow->PermanentPhysicalAddress[3], ifRow->PermanentPhysicalAddress[4], ifRow->PermanentPhysicalAddress[5]); } static VOID OvsDumpIfTable(PMIB_IF_TABLE2 ifTable) { PMIB_IF_ROW2 ifRow; UINT32 i; OVS_LOG_INFO("======Number of entries: %d========", ifTable->NumEntries); for (i = 0; i < ifTable->NumEntries; i++) { ifRow = &ifTable->Table[i]; OvsDumpIfRow(ifRow); } } NTSTATUS OvsGetIfEntry(GUID *interfaceGuid, PMIB_IF_ROW2 ifEntry) { NTSTATUS status; PMIB_IF_TABLE2 ifTable; UINT32 i; if (interfaceGuid == NULL || ifEntry == NULL) { return STATUS_INVALID_PARAMETER; } status = GetIfTable2Ex(MibIfTableNormal, &ifTable); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fail to get if table, status: %x", status); return status; } status = STATUS_NOT_FOUND; for (i = 0; i < ifTable->NumEntries; i++) { PMIB_IF_ROW2 ifRow; ifRow = &ifTable->Table[i]; if (!memcmp(interfaceGuid, &ifRow->InterfaceGuid, sizeof (GUID))) { RtlCopyMemory(ifEntry, ifRow, sizeof (MIB_IF_ROW2)); status = STATUS_SUCCESS; OvsDumpIfRow(ifEntry); break; } } FreeMibTable(ifTable); return status; } static VOID OvsDumpIPInterfaceEntry(PMIB_IPINTERFACE_ROW ipRow) { OVS_LOG_INFO("InterfaceLuid: NetLuidIndex: %d, type: %d", ipRow->InterfaceLuid.Info.NetLuidIndex, ipRow->InterfaceLuid.Info.IfType); OVS_LOG_INFO("InterfaceIndex: %d", ipRow->InterfaceIndex); OVS_LOG_INFO("MaxReassembleSize: %u", ipRow->MaxReassemblySize); } NTSTATUS OvsGetIPInterfaceEntry(NET_LUID luid, PMIB_IPINTERFACE_ROW ipRow) { NTSTATUS status; if (ipRow == NULL) { return STATUS_INVALID_PARAMETER; } ipRow->Family = AF_INET; ipRow->InterfaceLuid.Value = luid.Value; status = GetIpInterfaceEntry(ipRow); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fail to get internal IP Interface mib row, status: %x", status); return status; } OvsDumpIPInterfaceEntry(ipRow); return status; } static VOID OvsDumpIPEntry(PMIB_UNICASTIPADDRESS_ROW ipRow) { UINT32 ipAddr; OVS_LOG_INFO("InterfaceLuid: NetLuidIndex: %d, type: %d", ipRow->InterfaceLuid.Info.NetLuidIndex, ipRow->InterfaceLuid.Info.IfType); OVS_LOG_INFO("InterfaceIndex: %d", ipRow->InterfaceIndex); ASSERT(ipRow->Address.si_family == AF_INET); ipAddr = ipRow->Address.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Unicast Address: %d.%d.%d.%d\n", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, ipAddr >> 24); } NTSTATUS OvsGetIPEntry(NET_LUID interfaceLuid, PMIB_UNICASTIPADDRESS_ROW ipEntry) { PMIB_UNICASTIPADDRESS_TABLE ipTable; NTSTATUS status; UINT32 i; if (ipEntry == NULL || ipEntry == NULL) { return STATUS_INVALID_PARAMETER; } status = GetUnicastIpAddressTable(AF_INET, &ipTable); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fail to get unicast address table, status: %x", status); return status; } status = STATUS_NOT_FOUND; for (i = 0; i < ipTable->NumEntries; i++) { PMIB_UNICASTIPADDRESS_ROW ipRow; ipRow = &ipTable->Table[i]; if (ipRow->InterfaceLuid.Value == interfaceLuid.Value) { RtlCopyMemory(ipEntry, ipRow, sizeof (*ipRow)); OvsDumpIPEntry(ipEntry); status = STATUS_SUCCESS; break; } } FreeMibTable(ipTable); return status; } #ifdef OVS_ENABLE_IPPATH static VOID OvsDumpIPPath(PMIB_IPPATH_ROW ipPath) { UINT32 ipAddr = ipPath->Source.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Source: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Destination: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); ipAddr = ipPath->CurrentNextHop.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("NextHop: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); } NTSTATUS OvsGetIPPathEntry(PMIB_IPPATH_ROW ipPath) { NTSTATUS status; UINT32 ipAddr = ipPath->Destination.Ipv4.sin_addr.s_addr; status = GetIpPathEntry(ipPath); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fail to get IP path to %d.%d.%d.%d, status:%x", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status); return status; } OvsDumpIPPath(ipPath); return status; } #endif static VOID OvsDumpRoute(const SOCKADDR_INET *sourceAddress, const SOCKADDR_INET *destinationAddress, PMIB_IPFORWARD_ROW2 route) { UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Destination: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); ipAddr = sourceAddress->Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Source: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); ipAddr = route->NextHop.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("NextHop: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); } NTSTATUS OvsGetRoute(NET_LUID interfaceLuid, const SOCKADDR_INET *destinationAddress, PMIB_IPFORWARD_ROW2 route, SOCKADDR_INET *sourceAddress) { NTSTATUS status; if (destinationAddress == NULL || route == NULL) { return STATUS_INVALID_PARAMETER; } status = GetBestRoute2(&interfaceLuid, 0, NULL, destinationAddress, 0, route, sourceAddress); if (status != STATUS_SUCCESS) { UINT32 ipAddr = destinationAddress->Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Fail to get route to %d.%d.%d.%d, status: %x", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status); return status; } OvsDumpRoute(sourceAddress, destinationAddress, route); return status; } static VOID OvsDumpIPNeigh(PMIB_IPNET_ROW2 ipNeigh) { UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Neigh: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); OVS_LOG_INFO("MAC Address: %02x:%02x:%02x:%02x:%02x:%02x", ipNeigh->PhysicalAddress[0], ipNeigh->PhysicalAddress[1], ipNeigh->PhysicalAddress[2], ipNeigh->PhysicalAddress[3], ipNeigh->PhysicalAddress[4], ipNeigh->PhysicalAddress[5]); } NTSTATUS OvsGetIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) { NTSTATUS status; ASSERT(ipNeigh); status = GetIpNetEntry2(ipNeigh); if (status != STATUS_SUCCESS) { UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Fail to get ARP entry: %d.%d.%d.%d, status: %x", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status); return status; } if (ipNeigh->State == NlnsReachable || ipNeigh->State == NlnsPermanent) { OvsDumpIPNeigh(ipNeigh); return STATUS_SUCCESS; } return STATUS_FWP_TCPIP_NOT_READY; } NTSTATUS OvsResolveIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) { NTSTATUS status; ASSERT(ipNeigh); status = ResolveIpNetEntry2(ipNeigh, NULL); if (status != STATUS_SUCCESS) { UINT32 ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("Fail to resolve ARP entry: %d.%d.%d.%d, status: %x", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, status); return status; } if (ipNeigh->State == NlnsReachable || ipNeigh->State == NlnsPermanent) { OvsDumpIPNeigh(ipNeigh); return STATUS_SUCCESS; } return STATUS_FWP_TCPIP_NOT_READY; } NTSTATUS OvsGetOrResolveIPNeigh(UINT32 ipAddr, PMIB_IPNET_ROW2 ipNeigh) { NTSTATUS status; ASSERT(ipNeigh); RtlZeroMemory(ipNeigh, sizeof (*ipNeigh)); ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value; ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex; ipNeigh->Address.si_family = AF_INET; ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr; status = OvsGetIPNeighEntry(ipNeigh); if (status != STATUS_SUCCESS) { RtlZeroMemory(ipNeigh, sizeof (*ipNeigh)); ipNeigh->InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value; ipNeigh->InterfaceIndex = ovsInternalRow.InterfaceIndex; ipNeigh->Address.si_family = AF_INET; ipNeigh->Address.Ipv4.sin_addr.s_addr = ipAddr; status = OvsResolveIPNeighEntry(ipNeigh); } return status; } static VOID OvsChangeCallbackIpInterface(PVOID context, PMIB_IPINTERFACE_ROW ipRow, MIB_NOTIFICATION_TYPE notificationType) { UNREFERENCED_PARAMETER(context); switch (notificationType) { case MibParameterNotification: case MibAddInstance: if (ipRow->InterfaceLuid.Info.NetLuidIndex == ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && ipRow->InterfaceLuid.Info.IfType == ovsInternalRow.InterfaceLuid.Info.IfType && ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { /* * Update the IP Interface Row */ NdisAcquireSpinLock(&ovsIpHelperLock); RtlCopyMemory(&ovsInternalIPRow, ipRow, sizeof (PMIB_IPINTERFACE_ROW)); ovsInternalIPConfigured = TRUE; NdisReleaseSpinLock(&ovsIpHelperLock); } OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d is %s", ipRow->InterfaceLuid.Info.NetLuidIndex, ipRow->InterfaceLuid.Info.IfType, notificationType == MibAddInstance ? "added" : "modified"); break; case MibDeleteInstance: OVS_LOG_INFO("IP Interface with NetLuidIndex: %d, type: %d, deleted", ipRow->InterfaceLuid.Info.NetLuidIndex, ipRow->InterfaceLuid.Info.IfType); if (ipRow->InterfaceLuid.Info.NetLuidIndex == ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && ipRow->InterfaceLuid.Info.IfType == ovsInternalRow.InterfaceLuid.Info.IfType && ipRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { NdisAcquireSpinLock(&ovsIpHelperLock); ovsInternalIPConfigured = FALSE; NdisReleaseSpinLock(&ovsIpHelperLock); OvsCleanupIpHelperRequestList(); OvsCleanupFwdTable(); } break; case MibInitialNotification: OVS_LOG_INFO("Get Initial notification for IP Interface change."); default: return; } } static VOID OvsChangeCallbackIpRoute(PVOID context, PMIB_IPFORWARD_ROW2 ipRoute, MIB_NOTIFICATION_TYPE notificationType) { UINT32 ipAddr, nextHop; UNREFERENCED_PARAMETER(context); switch (notificationType) { case MibAddInstance: ASSERT(ipRoute); ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr; nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d added", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, ipRoute->DestinationPrefix.PrefixLength, nextHop & 0xff, (nextHop >> 8) & 0xff, (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff); break; case MibParameterNotification: case MibDeleteInstance: ASSERT(ipRoute); ipAddr = ipRoute->DestinationPrefix.Prefix.Ipv4.sin_addr.s_addr; nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("IPRoute: To %d.%d.%d.%d/%d through %d.%d.%d.%d %s.", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, ipRoute->DestinationPrefix.PrefixLength, nextHop & 0xff, (nextHop >> 8) & 0xff, (nextHop >> 16) & 0xff, (nextHop >> 24) & 0xff, notificationType == MibDeleteInstance ? "deleted" : "modified"); if (ipRoute->InterfaceLuid.Info.NetLuidIndex == ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && ipRoute->InterfaceLuid.Info.IfType == ovsInternalRow.InterfaceLuid.Info.IfType && ipRoute->InterfaceIndex == ovsInternalRow.InterfaceIndex) { POVS_IPFORWARD_ENTRY ipf; LOCK_STATE_EX lockState; NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); ipf = OvsLookupIPForwardEntry(&ipRoute->DestinationPrefix); if (ipf != NULL) { OvsRemoveIPForwardEntry(ipf); } NdisReleaseRWLock(ovsTableLock, &lockState); } break; case MibInitialNotification: OVS_LOG_INFO("Get Initial notification for IP Route change."); default: return; } } static VOID OvsChangeCallbackUnicastIpAddress(PVOID context, PMIB_UNICASTIPADDRESS_ROW unicastRow, MIB_NOTIFICATION_TYPE notificationType) { UINT32 ipAddr; UNREFERENCED_PARAMETER(context); switch (notificationType) { case MibParameterNotification: case MibAddInstance: ASSERT(unicastRow); ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr; if (unicastRow->InterfaceLuid.Info.NetLuidIndex == ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && unicastRow->InterfaceLuid.Info.IfType == ovsInternalRow.InterfaceLuid.Info.IfType && unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { ovsInternalIP = ipAddr; } OVS_LOG_INFO("IP Address: %d.%d.%d.%d is %s", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff, notificationType == MibAddInstance ? "added": "modified"); break; case MibDeleteInstance: ASSERT(unicastRow); ipAddr = unicastRow->Address.Ipv4.sin_addr.s_addr; OVS_LOG_INFO("IP Address removed: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); if (unicastRow->InterfaceLuid.Info.NetLuidIndex == ovsInternalRow.InterfaceLuid.Info.NetLuidIndex && unicastRow->InterfaceLuid.Info.IfType == ovsInternalRow.InterfaceLuid.Info.IfType && unicastRow->InterfaceIndex == ovsInternalRow.InterfaceIndex) { LOCK_STATE_EX lockState; NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); OvsRemoveAllFwdEntriesWithSrc(ipAddr); NdisReleaseRWLock(ovsTableLock, &lockState); } break; case MibInitialNotification: OVS_LOG_INFO("Get Initial notification for Unicast IP Address change."); default: return; } } static VOID OvsCancelChangeNotification() { if (ipInterfaceNotificationHandle != NULL) { CancelMibChangeNotify2(ipInterfaceNotificationHandle); ipInterfaceNotificationHandle = NULL; } if (ipRouteNotificationHandle != NULL) { CancelMibChangeNotify2(ipRouteNotificationHandle); ipRouteNotificationHandle = NULL; } if (unicastIPNotificationHandle != NULL) { CancelMibChangeNotify2(unicastIPNotificationHandle); unicastIPNotificationHandle = NULL; } } static NTSTATUS OvsRegisterChangeNotification() { NTSTATUS status; status = NotifyIpInterfaceChange(AF_INET, OvsChangeCallbackIpInterface, NULL, TRUE, &ipInterfaceNotificationHandle); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Fail to register Notify IP interface change, status:%x.", status); return status; } status = NotifyRouteChange2(AF_INET, OvsChangeCallbackIpRoute, NULL, TRUE, &ipRouteNotificationHandle); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Fail to regiter ip route change, status: %x.", status); goto register_cleanup; } status = NotifyUnicastIpAddressChange(AF_INET, OvsChangeCallbackUnicastIpAddress, NULL, TRUE, &unicastIPNotificationHandle); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Fail to regiter unicast ip change, status: %x.", status); } register_cleanup: if (status != STATUS_SUCCESS) { OvsCancelChangeNotification(); } return status; } static POVS_IPNEIGH_ENTRY OvsLookupIPNeighEntry(UINT32 ipAddr) { PLIST_ENTRY link; POVS_IPNEIGH_ENTRY entry; UINT32 hash = OvsJhashWords(&ipAddr, 1, OVS_HASH_BASIS); LIST_FORALL(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], link) { entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, link); if (entry->ipAddr == ipAddr) { return entry; } } return NULL; } static UINT32 OvsHashIPPrefix(PIP_ADDRESS_PREFIX prefix) { UINT64 words = (UINT64)prefix->Prefix.Ipv4.sin_addr.s_addr << 32 | (UINT32)prefix->PrefixLength; return OvsJhashWords((UINT32 *)&words, 2, OVS_HASH_BASIS); } static POVS_IPFORWARD_ENTRY OvsLookupIPForwardEntry(PIP_ADDRESS_PREFIX prefix) { PLIST_ENTRY link; POVS_IPFORWARD_ENTRY ipfEntry; UINT32 hash; ASSERT(prefix->Prefix.si_family == AF_INET); hash = RtlUlongByteSwap(prefix->Prefix.Ipv4.sin_addr.s_addr); ASSERT(prefix->PrefixLength >= 32 || (hash & (((UINT32)1 << (32 - prefix->PrefixLength)) - 1)) == 0); hash = OvsHashIPPrefix(prefix); LIST_FORALL(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], link) { ipfEntry = CONTAINING_RECORD(link, OVS_IPFORWARD_ENTRY, link); if (ipfEntry->prefix.PrefixLength == prefix->PrefixLength && ipfEntry->prefix.Prefix.Ipv4.sin_addr.s_addr == prefix->Prefix.Ipv4.sin_addr.s_addr) { return ipfEntry; } } return NULL; } static POVS_FWD_ENTRY OvsLookupIPFwdEntry(UINT32 dstIp) { PLIST_ENTRY link; POVS_FWD_ENTRY entry; UINT32 hash = OvsJhashWords(&dstIp, 1, OVS_HASH_BASIS); LIST_FORALL(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], link) { entry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link); if (entry->info.dstIpAddr == dstIp) { return entry; } } return NULL; } NTSTATUS OvsLookupIPFwdInfo(UINT32 dstIp, POVS_FWD_INFO info) { POVS_FWD_ENTRY entry; LOCK_STATE_EX lockState; NTSTATUS status = STATUS_NOT_FOUND; NdisAcquireRWLockRead(ovsTableLock, &lockState, 0); entry = OvsLookupIPFwdEntry(dstIp); if (entry) { info->value[0] = entry->info.value[0]; info->value[1] = entry->info.value[1]; info->value[2] = entry->info.value[2]; status = STATUS_SUCCESS; } NdisReleaseRWLock(ovsTableLock, &lockState); return status; } static POVS_IPNEIGH_ENTRY OvsCreateIPNeighEntry(PMIB_IPNET_ROW2 ipNeigh) { POVS_IPNEIGH_ENTRY entry; UINT64 timeVal; ASSERT(ipNeigh != NULL); entry = (POVS_IPNEIGH_ENTRY)OvsAllocateMemoryWithTag( sizeof(OVS_IPNEIGH_ENTRY), OVS_IPHELPER_POOL_TAG); if (entry == NULL) { return NULL; } RtlZeroMemory(entry, sizeof (OVS_IPNEIGH_ENTRY)); entry->ipAddr = ipNeigh->Address.Ipv4.sin_addr.s_addr; KeQuerySystemTime((LARGE_INTEGER *)&timeVal); entry->timeout = timeVal + OVS_IPNEIGH_TIMEOUT; RtlCopyMemory(entry->macAddr, ipNeigh->PhysicalAddress, ETH_ADDR_LEN); InitializeListHead(&entry->fwdList); return entry; } static POVS_IPFORWARD_ENTRY OvsCreateIPForwardEntry(PMIB_IPFORWARD_ROW2 ipRoute) { POVS_IPFORWARD_ENTRY entry; ASSERT(ipRoute); entry = (POVS_IPFORWARD_ENTRY)OvsAllocateMemoryWithTag( sizeof(OVS_IPFORWARD_ENTRY), OVS_IPHELPER_POOL_TAG); if (entry == NULL) { return NULL; } RtlZeroMemory(entry, sizeof (OVS_IPFORWARD_ENTRY)); RtlCopyMemory(&entry->prefix, &ipRoute->DestinationPrefix, sizeof (IP_ADDRESS_PREFIX)); entry->nextHop = ipRoute->NextHop.Ipv4.sin_addr.s_addr; InitializeListHead(&entry->fwdList); return entry; } static POVS_FWD_ENTRY OvsCreateFwdEntry(POVS_FWD_INFO fwdInfo) { POVS_FWD_ENTRY entry; entry = (POVS_FWD_ENTRY)OvsAllocateMemoryWithTag( sizeof(OVS_FWD_ENTRY), OVS_IPHELPER_POOL_TAG); if (entry == NULL) { return NULL; } RtlZeroMemory(entry, sizeof (OVS_FWD_ENTRY)); RtlCopyMemory(&entry->info, fwdInfo, sizeof (OVS_FWD_INFO)); return entry; } static VOID OvsRemoveFwdEntry(POVS_FWD_ENTRY fwdEntry) { POVS_IPFORWARD_ENTRY ipf; POVS_IPNEIGH_ENTRY ipn; ipf = fwdEntry->ipf; ipn = fwdEntry->ipn; RemoveEntryList(&fwdEntry->link); ovsNumFwdEntries--; RemoveEntryList(&fwdEntry->ipfLink); ipf->refCount--; RemoveEntryList(&fwdEntry->ipnLink); ipn->refCount--; if (ipf->refCount == 0) { ASSERT(IsListEmpty(&ipf->fwdList)); RemoveEntryList(&ipf->link); OvsFreeMemoryWithTag(ipf, OVS_IPHELPER_POOL_TAG); } if (ipn->refCount == 0) { ASSERT(IsListEmpty(&ipn->fwdList)); RemoveEntryList(&ipn->link); NdisAcquireSpinLock(&ovsIpHelperLock); RemoveEntryList(&ipn->slink); NdisReleaseSpinLock(&ovsIpHelperLock); OvsFreeMemoryWithTag(ipn, OVS_IPHELPER_POOL_TAG); } OvsFreeMemoryWithTag(fwdEntry, OVS_IPHELPER_POOL_TAG); } static VOID OvsRemoveIPForwardEntry(POVS_IPFORWARD_ENTRY ipf) { POVS_FWD_ENTRY fwdEntry; PLIST_ENTRY link, next; ipf->refCount++; LIST_FORALL_SAFE(&ipf->fwdList, link, next) { fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink); OvsRemoveFwdEntry(fwdEntry); } ASSERT(ipf->refCount == 1); RemoveEntryList(&ipf->link); OvsFreeMemoryWithTag(ipf, OVS_IPHELPER_POOL_TAG); } static VOID OvsRemoveIPNeighEntry(POVS_IPNEIGH_ENTRY ipn) { PLIST_ENTRY link, next; POVS_FWD_ENTRY fwdEntry; ipn->refCount++; LIST_FORALL_SAFE(&ipn->fwdList, link, next) { fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink); OvsRemoveFwdEntry(fwdEntry); } if (ipn->refCount == 1) { RemoveEntryList(&ipn->link); NdisAcquireSpinLock(&ovsIpHelperLock); RemoveEntryList(&ipn->slink); NdisReleaseSpinLock(&ovsIpHelperLock); OvsFreeMemoryWithTag(ipn, OVS_IPHELPER_POOL_TAG); } } static VOID OvsAddToSortedNeighList(POVS_IPNEIGH_ENTRY ipn) { PLIST_ENTRY link; POVS_IPNEIGH_ENTRY entry; if (!IsListEmpty(&ovsSortedIPNeighList)) { link = ovsSortedIPNeighList.Blink; entry = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink); if (entry->timeout > ipn->timeout) { ipn->timeout++; } } InsertTailList(&ovsSortedIPNeighList, &ipn->slink); } static VOID OvsAddIPFwdCache(POVS_FWD_ENTRY fwdEntry, POVS_IPFORWARD_ENTRY ipf, POVS_IPNEIGH_ENTRY ipn) { UINT32 hash; if (ipn->refCount == 0) { NdisAcquireSpinLock(&ovsIpHelperLock); OvsAddToSortedNeighList(ipn); NdisReleaseSpinLock(&ovsIpHelperLock); hash = OvsJhashWords(&ipn->ipAddr, 1, OVS_HASH_BASIS); InsertHeadList(&ovsNeighHashTable[hash & OVS_NEIGH_HASH_TABLE_MASK], &ipn->link); } if (ipf->refCount == 0) { hash = OvsHashIPPrefix(&ipf->prefix); InsertHeadList(&ovsRouteHashTable[hash & OVS_ROUTE_HASH_TABLE_MASK], &ipf->link); } InsertHeadList(&ipf->fwdList, &fwdEntry->ipfLink); ipf->refCount++; fwdEntry->ipf = ipf; InsertHeadList(&ipn->fwdList, &fwdEntry->ipnLink); ipn->refCount++; fwdEntry->ipn = ipn; hash = OvsJhashWords(&fwdEntry->info.dstIpAddr, 1, OVS_HASH_BASIS); InsertHeadList(&ovsFwdHashTable[hash & OVS_FWD_HASH_TABLE_MASK], &fwdEntry->link); ovsNumFwdEntries++; } static VOID OvsRemoveAllFwdEntriesWithSrc(UINT32 ipAddr) { UINT32 i; POVS_FWD_ENTRY fwdEntry; PLIST_ENTRY link, next; for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) { LIST_FORALL_SAFE(&ovsFwdHashTable[i], link, next) { fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, link); if (fwdEntry->info.srcIpAddr == ipAddr) { OvsRemoveFwdEntry(fwdEntry); } } } } static VOID OvsCleanupFwdTable(VOID) { PLIST_ENTRY link, next; POVS_IPNEIGH_ENTRY ipn; UINT32 i; LOCK_STATE_EX lockState; NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); if (ovsNumFwdEntries) { LIST_FORALL_SAFE(&ovsSortedIPNeighList, link, next) { ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink); OvsRemoveIPNeighEntry(ipn); } } for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) { ASSERT(IsListEmpty(&ovsFwdHashTable[i])); } for (i = 0; i < OVS_ROUTE_HASH_TABLE_SIZE; i++) { ASSERT(IsListEmpty(&ovsRouteHashTable[i])); } NdisReleaseRWLock(ovsTableLock, &lockState); } static VOID OvsCleanupIpHelperRequestList(VOID) { LIST_ENTRY list; PLIST_ENTRY next, link; POVS_IP_HELPER_REQUEST request; NdisAcquireSpinLock(&ovsIpHelperLock); if (ovsNumIpHelperRequests == 0) { NdisReleaseSpinLock(&ovsIpHelperLock); return; } InitializeListHead(&list); OvsAppendList(&list, &ovsIpHelperRequestList); ovsNumIpHelperRequests = 0; NdisReleaseSpinLock(&ovsIpHelperLock); LIST_FORALL_SAFE(&list, link, next) { request = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link); if (request->command == OVS_IP_HELPER_FWD_REQUEST && request->fwdReq.cb) { request->fwdReq.cb(request->fwdReq.nbl, request->fwdReq.inPort, &request->fwdReq.tunnelKey, request->fwdReq.cbData1, request->fwdReq.cbData2, STATUS_DEVICE_NOT_READY, NULL); } OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); } } static VOID OvsWakeupIPHelper(VOID) { KeSetEvent(&ovsIpHelperThreadContext.event, 0, FALSE); } VOID OvsInternalAdapterDown(VOID) { NdisAcquireSpinLock(&ovsIpHelperLock); ovsInternalAdapterUp = FALSE; ovsInternalIPConfigured = FALSE; NdisReleaseSpinLock(&ovsIpHelperLock); OvsCleanupIpHelperRequestList(); OvsCleanupFwdTable(); } VOID OvsInternalAdapterUp(GUID *netCfgInstanceId) { POVS_IP_HELPER_REQUEST request; RtlCopyMemory(&ovsInternalNetCfgId, netCfgInstanceId, sizeof (GUID)); RtlZeroMemory(&ovsInternalRow, sizeof (MIB_IF_ROW2)); request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag( sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG); if (request == NULL) { OVS_LOG_ERROR("Fail to initialize Internal Adapter"); return; } RtlZeroMemory(request, sizeof (OVS_IP_HELPER_REQUEST)); request->command = OVS_IP_HELPER_INTERNAL_ADAPTER_UP; NdisAcquireSpinLock(&ovsIpHelperLock); ovsInternalAdapterUp = TRUE; InsertHeadList(&ovsIpHelperRequestList, &request->link); ovsNumIpHelperRequests++; if (ovsNumIpHelperRequests == 1) { OvsWakeupIPHelper(); } NdisReleaseSpinLock(&ovsIpHelperLock); } static VOID OvsHandleInternalAdapterUp(POVS_IP_HELPER_REQUEST request) { NTSTATUS status; MIB_UNICASTIPADDRESS_ROW ipEntry; GUID *netCfgInstanceId = &ovsInternalNetCfgId; OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); status = OvsGetIfEntry(&ovsInternalNetCfgId, &ovsInternalRow); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Fali to get IF entry for internal port with GUID" " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", netCfgInstanceId->Data1, netCfgInstanceId->Data2, netCfgInstanceId->Data3, *(UINT16 *)netCfgInstanceId->Data4, netCfgInstanceId->Data4[2], netCfgInstanceId->Data4[3], netCfgInstanceId->Data4[4], netCfgInstanceId->Data4[5], netCfgInstanceId->Data4[6], netCfgInstanceId->Data4[7]); return; } status = OvsGetIPInterfaceEntry(ovsInternalRow.InterfaceLuid, &ovsInternalIPRow); if (status == STATUS_SUCCESS) { NdisAcquireSpinLock(&ovsIpHelperLock); ovsInternalIPConfigured = TRUE; NdisReleaseSpinLock(&ovsIpHelperLock); } else { return; } status = OvsGetIPEntry(ovsInternalRow.InterfaceLuid, &ipEntry); if (status != STATUS_SUCCESS) { OVS_LOG_INFO("Fali to get IP entry for internal port with GUID" " %08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", netCfgInstanceId->Data1, netCfgInstanceId->Data2, netCfgInstanceId->Data3, *(UINT16 *)netCfgInstanceId->Data4, netCfgInstanceId->Data4[2], netCfgInstanceId->Data4[3], netCfgInstanceId->Data4[4], netCfgInstanceId->Data4[5], netCfgInstanceId->Data4[6], netCfgInstanceId->Data4[7]); } } static NTSTATUS OvsEnqueueIpHelperRequest(POVS_IP_HELPER_REQUEST request) { NdisAcquireSpinLock(&ovsIpHelperLock); if (ovsInternalAdapterUp == FALSE || ovsInternalIPConfigured == FALSE) { NdisReleaseSpinLock(&ovsIpHelperLock); OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); return STATUS_NDIS_ADAPTER_NOT_READY; } else { InsertHeadList(&ovsIpHelperRequestList, &request->link); ovsNumIpHelperRequests++; if (ovsNumIpHelperRequests == 1) { OvsWakeupIPHelper(); } NdisReleaseSpinLock(&ovsIpHelperLock); return STATUS_SUCCESS; } } NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort, const OvsIPv4TunnelKey *tunnelKey, OvsIPHelperCallback cb, PVOID cbData1, PVOID cbData2) { POVS_IP_HELPER_REQUEST request; request = (POVS_IP_HELPER_REQUEST)OvsAllocateMemoryWithTag( sizeof(OVS_IP_HELPER_REQUEST), OVS_IPHELPER_POOL_TAG); if (request == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } request->command = OVS_IP_HELPER_FWD_REQUEST; request->fwdReq.nbl = nbl; request->fwdReq.inPort = inPort; RtlCopyMemory(&request->fwdReq.tunnelKey, tunnelKey, sizeof (*tunnelKey)); request->fwdReq.cb = cb; request->fwdReq.cbData1 = cbData1; request->fwdReq.cbData2 = cbData2; return OvsEnqueueIpHelperRequest(request); } static VOID OvsHandleFwdRequest(POVS_IP_HELPER_REQUEST request) { SOCKADDR_INET dst, src; NTSTATUS status = STATUS_SUCCESS; MIB_IPFORWARD_ROW2 ipRoute; MIB_IPNET_ROW2 ipNeigh; OVS_FWD_INFO fwdInfo; UINT32 ipAddr; UINT32 srcAddr; POVS_FWD_ENTRY fwdEntry = NULL; POVS_IPFORWARD_ENTRY ipf = NULL; POVS_IPNEIGH_ENTRY ipn = NULL; LOCK_STATE_EX lockState; BOOLEAN newIPF = FALSE; BOOLEAN newIPN = FALSE; BOOLEAN newFWD = FALSE; status = OvsLookupIPFwdInfo(request->fwdReq.tunnelKey.dst, &fwdInfo); if (status == STATUS_SUCCESS) { goto fwd_handle_nbl; } /* find IPRoute */ RtlZeroMemory(&dst, sizeof(dst)); RtlZeroMemory(&src, sizeof(src)); RtlZeroMemory(&ipRoute, sizeof (MIB_IPFORWARD_ROW2)); dst.si_family = AF_INET; dst.Ipv4.sin_addr.s_addr = request->fwdReq.tunnelKey.dst; status = OvsGetRoute(ovsInternalRow.InterfaceLuid, &dst, &ipRoute, &src); if (status != STATUS_SUCCESS) { goto fwd_handle_nbl; } srcAddr = src.Ipv4.sin_addr.s_addr; /* find IPNeigh */ ipAddr = ipRoute.NextHop.Ipv4.sin_addr.s_addr; if (ipAddr != 0) { NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); ipn = OvsLookupIPNeighEntry(ipAddr); if (ipn) { goto fwd_request_done; } NdisReleaseRWLock(ovsTableLock, &lockState); } RtlZeroMemory(&ipNeigh, sizeof (ipNeigh)); ipNeigh.InterfaceLuid.Value = ovsInternalRow.InterfaceLuid.Value; if (ipAddr == 0) { ipAddr = request->fwdReq.tunnelKey.dst; } status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh); if (status != STATUS_SUCCESS) { goto fwd_handle_nbl; } NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); fwd_request_done: /* * Initialize ipf */ ipf = OvsLookupIPForwardEntry(&ipRoute.DestinationPrefix); if (ipf == NULL) { ipf = OvsCreateIPForwardEntry(&ipRoute); if (ipf == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); status = STATUS_INSUFFICIENT_RESOURCES; goto fwd_handle_nbl; } newIPF = TRUE; } else { PLIST_ENTRY link; link = ipf->fwdList.Flink; fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipfLink); srcAddr = fwdEntry->info.srcIpAddr; } /* * initialize ipn */ if (ipn == NULL) { ipn = OvsLookupIPNeighEntry(ipAddr); if (ipn == NULL) { ipn = OvsCreateIPNeighEntry(&ipNeigh); if (ipn == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); status = STATUS_INSUFFICIENT_RESOURCES; goto fwd_handle_nbl; } newIPN = TRUE; } } /* * initialize fwdEntry */ fwdInfo.dstIpAddr = request->fwdReq.tunnelKey.dst; fwdInfo.srcIpAddr = srcAddr; RtlCopyMemory(fwdInfo.dstMacAddr, ipn->macAddr, ETH_ADDR_LEN); RtlCopyMemory(fwdInfo.srcMacAddr, ovsInternalRow.PhysicalAddress, ETH_ADDR_LEN); fwdInfo.srcPortNo = request->fwdReq.inPort; fwdEntry = OvsCreateFwdEntry(&fwdInfo); if (fwdEntry == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); status = STATUS_INSUFFICIENT_RESOURCES; goto fwd_handle_nbl; } newFWD = TRUE; /* * Cache the result */ OvsAddIPFwdCache(fwdEntry, ipf, ipn); NdisReleaseRWLock(ovsTableLock, &lockState); fwd_handle_nbl: if (status != STATUS_SUCCESS) { if (newFWD) { ASSERT(fwdEntry != NULL); OvsFreeMemoryWithTag(fwdEntry, OVS_IPHELPER_POOL_TAG); } if (newIPF) { ASSERT(ipf && ipf->refCount == 0); OvsFreeMemoryWithTag(ipf, OVS_IPHELPER_POOL_TAG); } if (newIPN) { ASSERT(ipn && ipn->refCount == 0); OvsFreeMemoryWithTag(ipn, OVS_IPHELPER_POOL_TAG); } ipAddr = request->fwdReq.tunnelKey.dst; OVS_LOG_INFO("Fail to handle IP helper request for dst: %d.%d.%d.%d", ipAddr & 0xff, (ipAddr >> 8) & 0xff, (ipAddr >> 16) & 0xff, (ipAddr >> 24) & 0xff); } if (request->fwdReq.cb) { request->fwdReq.cb(request->fwdReq.nbl, request->fwdReq.inPort, &request->fwdReq.tunnelKey, request->fwdReq.cbData1, request->fwdReq.cbData2, status, status == STATUS_SUCCESS ? &fwdInfo : NULL); } OvsFreeMemoryWithTag(request, OVS_IPHELPER_POOL_TAG); } static VOID OvsUpdateIPNeighEntry(UINT32 ipAddr, PMIB_IPNET_ROW2 ipNeigh, NTSTATUS status) { UINT64 timeVal; POVS_IPNEIGH_ENTRY ipn; LOCK_STATE_EX lockState; KeQuerySystemTime((LARGE_INTEGER *)&timeVal); /* * if mac changed, update all relevant fwdEntry */ if (status != STATUS_SUCCESS) { NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); } else { NdisAcquireRWLockRead(ovsTableLock, &lockState, 0); } ipn = OvsLookupIPNeighEntry(ipAddr); if (ipn == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); return; } if (status != STATUS_SUCCESS) { OvsRemoveIPNeighEntry(ipn); NdisReleaseRWLock(ovsTableLock, &lockState); return; } if (memcmp((const PVOID)ipn->macAddr, (const PVOID)ipNeigh->PhysicalAddress, (size_t)ETH_ADDR_LEN)) { PLIST_ENTRY link; POVS_FWD_ENTRY fwdEntry; NdisReleaseRWLock(ovsTableLock, &lockState); /* * need update, release and acquire write lock * This is not the common case. */ NdisAcquireRWLockWrite(ovsTableLock, &lockState, 0); ipn = OvsLookupIPNeighEntry(ipAddr); if (ipn == NULL) { NdisReleaseRWLock(ovsTableLock, &lockState); return; } LIST_FORALL(&ipn->fwdList, link) { fwdEntry = CONTAINING_RECORD(link, OVS_FWD_ENTRY, ipnLink); RtlCopyMemory(fwdEntry->info.dstMacAddr, ipNeigh->PhysicalAddress, ETH_ADDR_LEN); } } /* * update timeout and move to the end of * the sorted list */ NdisAcquireSpinLock(&ovsIpHelperLock); RemoveEntryList(&ipn->slink); ipn->timeout = timeVal + OVS_IPNEIGH_TIMEOUT; OvsAddToSortedNeighList(ipn); NdisReleaseSpinLock(&ovsIpHelperLock); NdisReleaseRWLock(ovsTableLock, &lockState); } static VOID OvsHandleIPNeighTimeout(UINT32 ipAddr) { MIB_IPNET_ROW2 ipNeigh; NTSTATUS status; status = OvsGetOrResolveIPNeigh(ipAddr, &ipNeigh); OvsUpdateIPNeighEntry(ipAddr, &ipNeigh, status); } /* *---------------------------------------------------------------------------- * IP Helper system threash handle following request * 1. Intialize Internal port row when internal port is connected * 2. Handle FWD request * 3. Handle IP Neigh timeout * * IP Interface, unicast address, and IP route change will be handled * by the revelant callback. *---------------------------------------------------------------------------- */ VOID OvsStartIpHelper(PVOID data) { POVS_IP_HELPER_THREAD_CONTEXT context = (POVS_IP_HELPER_THREAD_CONTEXT)data; POVS_IP_HELPER_REQUEST req; POVS_IPNEIGH_ENTRY ipn; PLIST_ENTRY link; UINT64 timeVal, timeout; OVS_LOG_INFO("Start the IP Helper Thread, context: %p", context); NdisAcquireSpinLock(&ovsIpHelperLock); while (!context->exit) { timeout = 0; while (!IsListEmpty(&ovsIpHelperRequestList)) { if (context->exit) { goto ip_helper_wait; } link = ovsIpHelperRequestList.Flink; RemoveEntryList(link); NdisReleaseSpinLock(&ovsIpHelperLock); req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link); switch (req->command) { case OVS_IP_HELPER_INTERNAL_ADAPTER_UP: OvsHandleInternalAdapterUp(req); break; case OVS_IP_HELPER_FWD_REQUEST: OvsHandleFwdRequest(req); break; default: OvsFreeMemoryWithTag(req, OVS_IPHELPER_POOL_TAG); } NdisAcquireSpinLock(&ovsIpHelperLock); } /* for now, let us hold the lock here, if this cause any issue * we will change to use IpHelper lock only to protect * IPN */ while (!IsListEmpty(&ovsSortedIPNeighList)) { UINT32 ipAddr; if (context->exit) { goto ip_helper_wait; } link = ovsSortedIPNeighList.Flink; ipn = CONTAINING_RECORD(link, OVS_IPNEIGH_ENTRY, slink); KeQuerySystemTime((LARGE_INTEGER *)&timeVal); if (ipn->timeout > timeVal) { timeout = ipn->timeout; break; } ipAddr = ipn->ipAddr; NdisReleaseSpinLock(&ovsIpHelperLock); OvsHandleIPNeighTimeout(ipAddr); NdisAcquireSpinLock(&ovsIpHelperLock); } if (!IsListEmpty(&ovsIpHelperRequestList)) { continue; } ip_helper_wait: if (context->exit) { break; } KeClearEvent(&context->event); NdisReleaseSpinLock(&ovsIpHelperLock); KeWaitForSingleObject(&context->event, Executive, KernelMode, FALSE, (LARGE_INTEGER *)&timeout); NdisAcquireSpinLock(&ovsIpHelperLock); } NdisReleaseSpinLock(&ovsIpHelperLock); OvsCleanupFwdTable(); OvsCleanupIpHelperRequestList(); OVS_LOG_INFO("Terminating the OVS IP Helper system thread"); PsTerminateSystemThread(STATUS_SUCCESS); } NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle) { NTSTATUS status; HANDLE threadHandle; UINT32 i; ovsFwdHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_FWD_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG); ovsRouteHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_ROUTE_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG); ovsNeighHashTable = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_NEIGH_HASH_TABLE_SIZE, OVS_IPHELPER_POOL_TAG); RtlZeroMemory(&ovsInternalRow, sizeof(MIB_IF_ROW2)); RtlZeroMemory(&ovsInternalIPRow, sizeof (MIB_IPINTERFACE_ROW)); ovsInternalIP = 0; ovsInternalAdapterUp = FALSE; InitializeListHead(&ovsSortedIPNeighList); ovsTableLock = NdisAllocateRWLock(ndisFilterHandle); NdisAllocateSpinLock(&ovsIpHelperLock); InitializeListHead(&ovsIpHelperRequestList); ovsNumIpHelperRequests = 0; ipInterfaceNotificationHandle = NULL; ipRouteNotificationHandle = NULL; unicastIPNotificationHandle = NULL; if (ovsFwdHashTable == NULL || ovsRouteHashTable == NULL || ovsNeighHashTable == NULL || ovsTableLock == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto init_cleanup; } for (i = 0; i < OVS_FWD_HASH_TABLE_SIZE; i++) { InitializeListHead(&ovsFwdHashTable[i]); } for (i = 0; i < OVS_ROUTE_HASH_TABLE_SIZE; i++) { InitializeListHead(&ovsRouteHashTable[i]); } for (i = 0; i < OVS_NEIGH_HASH_TABLE_SIZE; i++) { InitializeListHead(&ovsNeighHashTable[i]); } KeInitializeEvent(&ovsIpHelperThreadContext.event, NotificationEvent, FALSE); status = OvsRegisterChangeNotification(); ovsIpHelperThreadContext.exit = 0; if (status == STATUS_SUCCESS) { status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL, NULL, OvsStartIpHelper, &ovsIpHelperThreadContext); if (status != STATUS_SUCCESS) { goto init_cleanup; } ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, KernelMode, &ovsIpHelperThreadContext.threadObject, NULL); ZwClose(threadHandle); } init_cleanup: if (status != STATUS_SUCCESS) { OvsCancelChangeNotification(); if (ovsFwdHashTable) { OvsFreeMemoryWithTag(ovsFwdHashTable, OVS_IPHELPER_POOL_TAG); ovsFwdHashTable = NULL; } if (ovsRouteHashTable) { OvsFreeMemoryWithTag(ovsRouteHashTable, OVS_IPHELPER_POOL_TAG); ovsRouteHashTable = NULL; } if (ovsNeighHashTable) { OvsFreeMemoryWithTag(ovsNeighHashTable, OVS_IPHELPER_POOL_TAG); ovsNeighHashTable = NULL; } if (ovsTableLock) { NdisFreeRWLock(ovsTableLock); ovsTableLock = NULL; } NdisFreeSpinLock(&ovsIpHelperLock); } return STATUS_SUCCESS; } VOID OvsCleanupIpHelper(VOID) { OvsCancelChangeNotification(); NdisAcquireSpinLock(&ovsIpHelperLock); ovsIpHelperThreadContext.exit = 1; OvsWakeupIPHelper(); NdisReleaseSpinLock(&ovsIpHelperLock); KeWaitForSingleObject(ovsIpHelperThreadContext.threadObject, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(ovsIpHelperThreadContext.threadObject); OvsFreeMemoryWithTag(ovsFwdHashTable, OVS_IPHELPER_POOL_TAG); OvsFreeMemoryWithTag(ovsRouteHashTable, OVS_IPHELPER_POOL_TAG); OvsFreeMemoryWithTag(ovsNeighHashTable, OVS_IPHELPER_POOL_TAG); NdisFreeRWLock(ovsTableLock); NdisFreeSpinLock(&ovsIpHelperLock); } VOID OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl) { PLIST_ENTRY link, next; POVS_IP_HELPER_REQUEST req; LIST_ENTRY list; InitializeListHead(&list); NdisAcquireSpinLock(&ovsIpHelperLock); LIST_FORALL_SAFE(&ovsIpHelperRequestList, link, next) { req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link); if (req->command == OVS_IP_HELPER_FWD_REQUEST && (nbl == NULL || req->fwdReq.nbl == nbl)) { RemoveEntryList(link); InsertHeadList(&list, link); if (nbl != NULL) { break; } } } NdisReleaseSpinLock(&ovsIpHelperLock); LIST_FORALL_SAFE(&list, link, next) { req = CONTAINING_RECORD(link, OVS_IP_HELPER_REQUEST, link); if (req->fwdReq.cb) { req->fwdReq.cb(req->fwdReq.nbl, req->fwdReq.inPort, &req->fwdReq.tunnelKey, req->fwdReq.cbData1, req->fwdReq.cbData2, STATUS_DEVICE_NOT_READY, NULL); } OvsFreeMemoryWithTag(req, OVS_IPHELPER_POOL_TAG); } } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Datapath.h0000644000000000000000000000013112631676262022350 xustar0030 mtime=1449622706.938438204 29 atime=1456592667.30709024 30 ctime=1456594660.173287978 openvswitch-2.5.0/datapath-windows/ovsext/Datapath.h0000664000175000017500000001066012631676262024044 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * XXX: OVS_USE_NL_INTERFACE is being used to keep the legacy DPIF interface * alive while we transition over to the netlink based interface. * OVS_USE_NL_INTERFACE = 0 => legacy inteface to use with dpif-windows.c * OVS_USE_NL_INTERFACE = 1 => netlink inteface to use with ported dpif-linux.c */ #ifndef __DATAPATH_H_ #define __DATAPATH_H_ 1 /* * Device operations to tag netlink commands with. This is a bitmask since it * is possible that a particular command can be invoked via different device * operations. */ #define OVS_READ_DEV_OP (1 << 0) #define OVS_WRITE_DEV_OP (1 << 1) #define OVS_TRANSACTION_DEV_OP (1 << 2) typedef struct _OVS_DEVICE_EXTENSION { INT numberOpenInstance; INT pidCount; } OVS_DEVICE_EXTENSION, *POVS_DEVICE_EXTENSION; // forward declaration typedef struct _OVS_USER_PACKET_QUEUE OVS_USER_PACKET_QUEUE, *POVS_USER_PACKET_QUEUE; /* * Private context for each handle on the device. */ typedef struct _OVS_OPEN_INSTANCE { UINT32 cookie; PFILE_OBJECT fileObject; PVOID eventQueue; POVS_USER_PACKET_QUEUE packetQueue; UINT32 pid; struct { POVS_MESSAGE ovsMsg; /* OVS message passed during dump start. */ UINT32 index[2]; /* markers to continue dump from. One or more * of them may be used. Eg. in flow dump, the * markers can store the row and the column * indices. */ } dumpState; /* data to support dump commands. */ LIST_ENTRY pidLink; /* Links the instance to * pidHashArray */ } OVS_OPEN_INSTANCE, *POVS_OPEN_INSTANCE; NDIS_STATUS OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle); VOID OvsDeleteDeviceObject(); VOID OvsInit(); VOID OvsCleanup(); POVS_OPEN_INSTANCE OvsGetOpenInstance(PFILE_OBJECT fileObject, UINT32 dpNo); NTSTATUS OvsCompleteIrpRequest(PIRP irp, ULONG_PTR infoPtr, NTSTATUS status); VOID OvsAcquireCtrlLock(); VOID OvsReleaseCtrlLock(); /* * Utility structure and functions to collect in one place all the parameters * passed during a call from userspace. */ typedef struct _OVS_USER_PARAMS_CONTEXT { PIRP irp; /* The IRP used for the userspace call. */ POVS_OPEN_INSTANCE ovsInstance; /* Private data of the device handle. */ UINT32 devOp; /* Device operation of the userspace call. */ POVS_MESSAGE ovsMsg; /* OVS message that userspace passed down. */ PVOID inputBuffer; /* Input data specified by userspace. Maybe NULL. */ UINT32 inputLength; /* Length of input buffer. */ PVOID outputBuffer; /* Output buffer specified by userspace for reading * data. Maybe NULL. */ UINT32 outputLength; /* Length of output buffer. */ } OVS_USER_PARAMS_CONTEXT, *POVS_USER_PARAMS_CONTEXT; static __inline VOID InitUserParamsCtx(PIRP irp, POVS_OPEN_INSTANCE ovsInstance, UINT32 devOp, POVS_MESSAGE ovsMsg, PVOID inputBuffer, UINT32 inputLength, PVOID outputBuffer, UINT32 outputLength, POVS_USER_PARAMS_CONTEXT usrParamsCtx) { usrParamsCtx->irp = irp; usrParamsCtx->ovsInstance = ovsInstance; usrParamsCtx->devOp = devOp; usrParamsCtx->ovsMsg = ovsMsg; usrParamsCtx->inputBuffer = inputBuffer; usrParamsCtx->inputLength = inputLength; usrParamsCtx->outputBuffer = outputBuffer; usrParamsCtx->outputLength = outputLength; } NTSTATUS InitUserDumpState(POVS_OPEN_INSTANCE instance, POVS_MESSAGE ovsMsg); VOID FreeUserDumpState(POVS_OPEN_INSTANCE instance); NTSTATUS OvsSetupDumpStart(POVS_USER_PARAMS_CONTEXT usrParamsCtx); #endif /* __DATAPATH_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Tunnel.h0000644000000000000000000000013112631676262022067 xustar0029 mtime=1449622706.97843961 30 atime=1456592667.315090569 30 ctime=1456594660.217289829 openvswitch-2.5.0/datapath-windows/ovsext/Tunnel.h0000664000175000017500000000330012631676262023554 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __TUNNEL_H_ #define __TUNNEL_H_ 1 // // OVS_TUNNEL_PENDED_PACKET is the object type we used to store all information // needed for out-of-band packet modification and re-injection. This type // also points back to the flow context the packet belongs to. typedef struct OVS_TUNNEL_PENDED_PACKET_ { /* Common fields for inbound and outbound traffic */ NET_BUFFER_LIST *netBufferList; UINT32 ipHeaderSize; UINT32 transportHeaderSize; FWPS_CLASSIFY_OUT *classifyOut; } OVS_TUNNEL_PENDED_PACKET; // // Shared function prototypes // VOID OvsTunnelClassify(const FWPS_INCOMING_VALUES *inFixedValues, const FWPS_INCOMING_METADATA_VALUES *inMetaValues, VOID *layerData, const VOID *classifyContext, const FWPS_FILTER *filter, UINT64 flowContext, FWPS_CLASSIFY_OUT *classifyOut); NTSTATUS OvsTunnelNotify(FWPS_CALLOUT_NOTIFY_TYPE notifyType, const GUID *filterKey, const FWPS_FILTER *filter); #endif /* __TUNNEL_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Oid.c0000644000000000000000000000013212652645507021332 xustar0030 mtime=1454066503.406754588 30 atime=1456592667.311090405 30 ctime=1456594660.205289325 openvswitch-2.5.0/datapath-windows/ovsext/Oid.c0000664000175000017500000007142012652645507023026 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Switch.h" #include "Vport.h" #include "NetProto.h" #include "User.h" #include "Flow.h" #include "Event.h" #include "User.h" #include "Oid.h" /* Due to an imported header file */ #pragma warning( disable:4505 ) #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_DISPATCH #include "Debug.h" typedef struct _OVS_OID_CONTEXT { NDIS_EVENT oidComplete; NDIS_STATUS status; } OVS_OID_CONTEXT, *POVS_OID_CONTEXT; VOID OvsExtOidRequestComplete(NDIS_HANDLE filterModuleContext, PNDIS_OID_REQUEST oidRequest, NDIS_STATUS status); static VOID OvsOidRequestCompleteMethod(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PNDIS_OID_REQUEST origOidRequest, NDIS_STATUS status); static VOID OvsOidRequestCompleteSetInfo(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PNDIS_OID_REQUEST origOidRequest, NDIS_STATUS status); static VOID OvsOidRequestCompleteQuery(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PNDIS_OID_REQUEST origOidRequest, NDIS_STATUS status); static NDIS_STATUS OvsProcessSetOidPortProp(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest); static NDIS_STATUS OvsProcessSetOidPort(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest); static NDIS_STATUS OvsProcessSetOidNic(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest); __inline BOOLEAN OvsCheckOidHeaderFunc(PNDIS_OBJECT_HEADER header, LONG propRev, LONG propSize) { return header->Type != NDIS_OBJECT_TYPE_DEFAULT || header->Revision < propRev || header->Size < propSize; } #define OvsCheckOidHeader(_hdr, _rev) \ OvsCheckOidHeaderFunc(_hdr, _rev, ##NDIS_SIZEOF_##_rev) static __inline VOID OvsOidSetOrigRequest(PNDIS_OID_REQUEST clonedRequest, PNDIS_OID_REQUEST origRequest) { *(PVOID*)(&clonedRequest->SourceReserved[0]) = origRequest; } static __inline PNDIS_OID_REQUEST OvsOidGetOrigRequest(PNDIS_OID_REQUEST clonedRequest) { return *((PVOID*)(&clonedRequest->SourceReserved[0])); } static __inline VOID OvsOidSetContext(PNDIS_OID_REQUEST clonedRequest, POVS_OID_CONTEXT origRequest) { *(PVOID*)(&clonedRequest->SourceReserved[8]) = origRequest; } static __inline POVS_OID_CONTEXT OvsOidGetContext(PNDIS_OID_REQUEST clonedRequest) { return *((PVOID*)(&clonedRequest->SourceReserved[8])); } static NDIS_STATUS OvsProcessSetOidPortProp(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION); PNDIS_SWITCH_PORT_PROPERTY_PARAMETERS portPropParam = setInfo->InformationBuffer; BOOLEAN checkFailed = TRUE; UNREFERENCED_PARAMETER(switchObject); if (setInfo->Oid == OID_SWITCH_PORT_PROPERTY_DELETE) { checkFailed = OvsCheckOidHeader( (PNDIS_OBJECT_HEADER)portPropParam, NDIS_SWITCH_PORT_PROPERTY_DELETE_PARAMETERS_REVISION_1); } else { /* it must be a add or update request */ checkFailed = OvsCheckOidHeader( (PNDIS_OBJECT_HEADER)portPropParam, NDIS_SWITCH_PORT_PROPERTY_PARAMETERS_REVISION_1); } if (checkFailed) { status = NDIS_STATUS_INVALID_PARAMETER; goto done; } if (portPropParam->PropertyType == NdisSwitchPortPropertyTypeVlan) { status = NDIS_STATUS_NOT_SUPPORTED; goto done; } done: return status; } static NDIS_STATUS OvsProcessSetOidPort(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION); PNDIS_SWITCH_PORT_PARAMETERS portParam = setInfo->InformationBuffer; if (OvsCheckOidHeader((PNDIS_OBJECT_HEADER)portParam, NDIS_SWITCH_PORT_PARAMETERS_REVISION_1)) { status = NDIS_STATUS_NOT_SUPPORTED; goto done; } if (portParam->IsValidationPort) { /* Validation ports are used internally by the Hyper-V switch * to validate and verify settings. We must skip handling them, * and return STATUS_SUCCESS as the OID result */ return NDIS_STATUS_SUCCESS; } switch(setInfo->Oid) { case OID_SWITCH_PORT_CREATE: status = HvCreatePort(switchObject, portParam, 0); break; case OID_SWITCH_PORT_UPDATED: status = HvUpdatePort(switchObject, portParam); break; case OID_SWITCH_PORT_TEARDOWN: HvTeardownPort(switchObject, portParam); break; case OID_SWITCH_PORT_DELETE: HvDeletePort(switchObject, portParam); break; default: break; } done: return status; } static NDIS_STATUS OvsProcessSetOidNic(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION); PNDIS_SWITCH_NIC_PARAMETERS nicParam = setInfo->InformationBuffer; if (OvsCheckOidHeader((PNDIS_OBJECT_HEADER)nicParam, NDIS_SWITCH_NIC_PARAMETERS_REVISION_1)) { status = NDIS_STATUS_NOT_SUPPORTED; goto done; } switch(setInfo->Oid) { case OID_SWITCH_NIC_CREATE: status = HvCreateNic(switchObject, nicParam); break; case OID_SWITCH_NIC_CONNECT: HvConnectNic(switchObject, nicParam); break; case OID_SWITCH_NIC_UPDATED: HvUpdateNic(switchObject, nicParam); break; case OID_SWITCH_NIC_DISCONNECT: HvDisconnectNic(switchObject, nicParam); break; case OID_SWITCH_NIC_DELETE: HvDeleteNic(switchObject, nicParam); break; default: break; } done: return status; } static NDIS_STATUS OvsProcessSetOid(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PBOOLEAN complete) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION); *complete = FALSE; OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu", oidRequest, setInfo->Oid); /* Verify the basic Oid paramters first */ if (setInfo->InformationBufferLength && (setInfo->InformationBufferLength < sizeof(NDIS_OBJECT_HEADER))) { status = NDIS_STATUS_INVALID_OID; OVS_LOG_INFO("Invalid input %d", setInfo->InformationBufferLength); goto error; } /* Documentation does not specify what should be done * if informationBuffer is not present. Although it mentions the * structure type informationBUffer points to for each oid request, * but it does not explicitly mention that it is a MUST. * hence we are following this scenario same way as what sample code * mentions. */ if (!(setInfo->InformationBufferLength)) { /* We cannot do anything about this oid request, * lets just pass it down. */ OVS_LOG_INFO("Buffer Length Zero"); goto done; } switch(setInfo->Oid) { case OID_SWITCH_PORT_PROPERTY_ADD: case OID_SWITCH_PORT_PROPERTY_UPDATE: case OID_SWITCH_PORT_PROPERTY_DELETE: status = OvsProcessSetOidPortProp(switchObject, oidRequest); break; case OID_SWITCH_PORT_CREATE: case OID_SWITCH_PORT_UPDATED: case OID_SWITCH_PORT_TEARDOWN: case OID_SWITCH_PORT_DELETE: status = OvsProcessSetOidPort(switchObject, oidRequest); break; case OID_SWITCH_NIC_CREATE: case OID_SWITCH_NIC_CONNECT: case OID_SWITCH_NIC_UPDATED: case OID_SWITCH_NIC_DISCONNECT: case OID_SWITCH_NIC_DELETE: status = OvsProcessSetOidNic(switchObject, oidRequest); break; default: /* Non handled OID request */ break; } if (status != NDIS_STATUS_SUCCESS) { goto error; } goto done; error: *complete = TRUE; done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; } static NDIS_STATUS OvsProcessMethodOid(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PBOOLEAN complete, PULONG bytesNeededParam) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION); struct _SET *nicReqSetInfo = NULL; PNDIS_OBJECT_HEADER header = NULL; PNDIS_OID_REQUEST nicOidRequest = NULL; UNREFERENCED_PARAMETER(switchObject); OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu", oidRequest, methodInfo->Oid); *complete = FALSE; *bytesNeededParam = 0; header = methodInfo->InformationBuffer; switch(methodInfo->Oid) { /* We deal with only OID_SWITCH_NIC_REQUEST as of now */ case OID_SWITCH_NIC_REQUEST: if (OvsCheckOidHeader(header, NDIS_SWITCH_NIC_OID_REQUEST_REVISION_1)) { OVS_LOG_INFO("Check Header failed"); status = NDIS_STATUS_NOT_SUPPORTED; *complete = TRUE; goto done; } nicOidRequest = (((PNDIS_SWITCH_NIC_OID_REQUEST)header)->OidRequest); nicReqSetInfo = &(nicOidRequest->DATA.SET_INFORMATION); /* Fail the SR-IOV VF case */ if ((nicOidRequest->RequestType == NdisRequestSetInformation) && (nicReqSetInfo->Oid == OID_NIC_SWITCH_ALLOCATE_VF)) { OVS_LOG_INFO("We do not support Oid: " "OID_NIC_SWITCH_ALLOCATE_VF"); status = NDIS_STATUS_FAILURE; *complete = TRUE; } break; default: /* No op */ break; } done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterOidRequest function. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsExtOidRequest(NDIS_HANDLE filterModuleContext, PNDIS_OID_REQUEST oidRequest) { POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext; NDIS_STATUS status = NDIS_STATUS_SUCCESS; PNDIS_OID_REQUEST clonedOidRequest = NULL; struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION); BOOLEAN completeOid = FALSE; ULONG bytesNeeded = 0; OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d", oidRequest, oidRequest->RequestType); status = NdisAllocateCloneOidRequest(switchObject->NdisFilterHandle, oidRequest, OVS_MEMORY_TAG, &clonedOidRequest); if (status != NDIS_STATUS_SUCCESS) { goto done; } NdisInterlockedIncrement(&(switchObject->pendingOidCount)); /* set the original oid request in cloned one. */ OvsOidSetOrigRequest(clonedOidRequest, oidRequest); OvsOidSetContext(clonedOidRequest, NULL); switch(clonedOidRequest->RequestType) { case NdisRequestSetInformation: status = OvsProcessSetOid(switchObject, clonedOidRequest, &completeOid); break; case NdisRequestMethod: status = OvsProcessMethodOid(switchObject, clonedOidRequest, &completeOid, &bytesNeeded); break; default: /* We do not handle other request types as of now. * We are just a passthrough for those. */ break; } if (completeOid == TRUE) { /* dont leave any reference back to original request, * even if we are freeing it up. */ OVS_LOG_INFO("Complete True oidRequest %p.", oidRequest); OvsOidSetOrigRequest(clonedOidRequest, NULL); NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, clonedOidRequest); methodInfo->BytesNeeded = bytesNeeded; NdisInterlockedDecrement(&switchObject->pendingOidCount); goto done; } /* pass the request down */ status = NdisFOidRequest(switchObject->NdisFilterHandle, clonedOidRequest); if (status != NDIS_STATUS_PENDING) { OvsExtOidRequestComplete(switchObject, clonedOidRequest, status); /* sample code says so */ status = NDIS_STATUS_PENDING; } done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterOidRequestComplete function. * -------------------------------------------------------------------------- */ VOID OvsExtOidRequestComplete(NDIS_HANDLE filterModuleContext, PNDIS_OID_REQUEST oidRequest, NDIS_STATUS status) { POVS_SWITCH_CONTEXT switchObject = (POVS_SWITCH_CONTEXT)filterModuleContext; PNDIS_OID_REQUEST origReq = OvsOidGetOrigRequest(oidRequest); POVS_OID_CONTEXT oidContext = OvsOidGetContext(oidRequest); /* Only one of the two should be set */ ASSERT(origReq != NULL || oidContext != NULL); ASSERT(oidContext != NULL || origReq != NULL); OVS_LOG_TRACE("Enter: oidRequest %p, reqType: %d", oidRequest, oidRequest->RequestType); if (origReq == NULL) { NdisInterlockedDecrement(&(switchObject->pendingOidCount)); oidContext->status = status; NdisSetEvent(&oidContext->oidComplete); OVS_LOG_INFO("Internally generated request"); goto done; } switch(oidRequest->RequestType) { case NdisRequestMethod: OvsOidRequestCompleteMethod(switchObject, oidRequest, origReq, status); break; case NdisRequestSetInformation: OvsOidRequestCompleteSetInfo(switchObject, oidRequest, origReq, status); break; case NdisRequestQueryInformation: case NdisRequestQueryStatistics: default: OvsOidRequestCompleteQuery(switchObject, oidRequest, origReq, status); break; } OvsOidSetOrigRequest(oidRequest, NULL); NdisFreeCloneOidRequest(switchObject->NdisFilterHandle, oidRequest); NdisFOidRequestComplete(switchObject->NdisFilterHandle, origReq, status); NdisInterlockedDecrement(&(switchObject->pendingOidCount)); done: OVS_LOG_TRACE("Exit"); } static VOID OvsOidRequestCompleteMethod(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PNDIS_OID_REQUEST origOidRequest, NDIS_STATUS status) { UNREFERENCED_PARAMETER(status); UNREFERENCED_PARAMETER(switchObject); struct _METHOD *methodInfo = &(oidRequest->DATA.METHOD_INFORMATION); struct _METHOD *origMethodInfo = &(origOidRequest->DATA. METHOD_INFORMATION); OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu", oidRequest, methodInfo->Oid); origMethodInfo->OutputBufferLength = methodInfo->OutputBufferLength; origMethodInfo->BytesRead = methodInfo->BytesRead; origMethodInfo->BytesNeeded = methodInfo->BytesNeeded; origMethodInfo->BytesWritten = methodInfo->BytesWritten; OVS_LOG_TRACE("Exit"); } static VOID OvsOidRequestCompleteSetInfo(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PNDIS_OID_REQUEST origOidRequest, NDIS_STATUS status) { struct _SET *setInfo = &(oidRequest->DATA.SET_INFORMATION); struct _SET *origSetInfo = &(origOidRequest->DATA.SET_INFORMATION); PNDIS_OBJECT_HEADER origHeader = origSetInfo->InformationBuffer; OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu", oidRequest, setInfo->Oid); origSetInfo->BytesRead = setInfo->BytesRead; origSetInfo->BytesNeeded = setInfo->BytesNeeded; if (status != NDIS_STATUS_SUCCESS) { switch(setInfo->Oid) { case OID_SWITCH_PORT_CREATE: HvDeletePort(switchObject, (PNDIS_SWITCH_PORT_PARAMETERS)origHeader); break; case OID_SWITCH_NIC_CREATE: HvDeleteNic(switchObject, (PNDIS_SWITCH_NIC_PARAMETERS)origHeader); break; default: break; } } OVS_LOG_TRACE("Exit"); } static VOID OvsOidRequestCompleteQuery(POVS_SWITCH_CONTEXT switchObject, PNDIS_OID_REQUEST oidRequest, PNDIS_OID_REQUEST origOidRequest, NDIS_STATUS status) { UNREFERENCED_PARAMETER(switchObject); UNREFERENCED_PARAMETER(status); struct _QUERY *queryInfo = &((oidRequest->DATA).QUERY_INFORMATION); struct _QUERY *origQueryInfo = &((origOidRequest->DATA).QUERY_INFORMATION); OVS_LOG_TRACE("Enter: oidRequest %p, Oid: %lu", oidRequest, queryInfo->Oid); origQueryInfo->BytesWritten = queryInfo->BytesWritten; origQueryInfo->BytesNeeded = queryInfo->BytesNeeded; OVS_LOG_TRACE("Exit"); } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterCancelOidRequest function. * -------------------------------------------------------------------------- */ VOID OvsExtCancelOidRequest(NDIS_HANDLE filterModuleContext, PVOID requestId) { OVS_LOG_TRACE("Enter: requestId: %p", requestId); UNREFERENCED_PARAMETER(filterModuleContext); UNREFERENCED_PARAMETER(requestId); } /* * -------------------------------------------------------------------------- * Utility function to issue the specified OID to the NDIS stack. The OID is * directed towards the miniport edge of the extensible switch. * An OID that gets issued may not complete immediately, and in such cases, the * function waits for the OID to complete. Thus, this function must not be * called at the PASSIVE_LEVEL. * -------------------------------------------------------------------------- */ static NDIS_STATUS OvsIssueOidRequest(POVS_SWITCH_CONTEXT switchContext, NDIS_REQUEST_TYPE oidType, UINT32 oidRequestEnum, PVOID oidInputBuffer, UINT32 inputSize, PVOID oidOutputBuffer, UINT32 outputSize, UINT32 *outputSizeNeeded) { NDIS_STATUS status; PNDIS_OID_REQUEST oidRequest; POVS_OID_CONTEXT oidContext; ULONG OvsExtOidRequestId = 'ISVO'; DBG_UNREFERENCED_PARAMETER(inputSize); DBG_UNREFERENCED_PARAMETER(oidInputBuffer); OVS_LOG_TRACE("Enter: switchContext: %p, oidType: %d", switchContext, oidType); ASSERT(oidInputBuffer == NULL || inputSize != 0); ASSERT(oidOutputBuffer == NULL || outputSize != 0); ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); oidRequest = OvsAllocateMemoryWithTag(sizeof *oidRequest, OVS_OID_POOL_TAG); if (!oidRequest) { status = NDIS_STATUS_RESOURCES; goto done; } oidContext = OvsAllocateMemoryWithTag(sizeof *oidContext, OVS_OID_POOL_TAG); if (!oidContext) { OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); status = NDIS_STATUS_RESOURCES; goto done; } RtlZeroMemory(oidRequest, sizeof *oidRequest); RtlZeroMemory(oidContext, sizeof *oidContext); oidRequest->Header.Type = NDIS_OBJECT_TYPE_OID_REQUEST; oidRequest->Header.Revision = NDIS_OID_REQUEST_REVISION_1; oidRequest->Header.Size = NDIS_SIZEOF_OID_REQUEST_REVISION_1; oidRequest->RequestType = oidType; oidRequest->PortNumber = 0; oidRequest->Timeout = 0; oidRequest->RequestId = (PVOID)OvsExtOidRequestId; switch(oidType) { case NdisRequestQueryInformation: oidRequest->DATA.QUERY_INFORMATION.Oid = oidRequestEnum; oidRequest->DATA.QUERY_INFORMATION.InformationBuffer = oidOutputBuffer; oidRequest->DATA.QUERY_INFORMATION.InformationBufferLength = outputSize; break; default: ASSERT(FALSE); status = NDIS_STATUS_INVALID_PARAMETER; break; } /* * We make use of the SourceReserved field in the OID request to store * pointers to the original OID (if any), and also context for completion * (if any). */ oidContext->status = NDIS_STATUS_SUCCESS; NdisInitializeEvent(&oidContext->oidComplete); OvsOidSetOrigRequest(oidRequest, NULL); OvsOidSetContext(oidRequest, oidContext); NdisInterlockedIncrement(&(switchContext->pendingOidCount)); status = NdisFOidRequest(switchContext->NdisFilterHandle, oidRequest); if (status == NDIS_STATUS_PENDING) { NdisWaitEvent(&oidContext->oidComplete, 0); } else { NdisInterlockedDecrement(&(switchContext->pendingOidCount)); } if (status == NDIS_STATUS_INVALID_LENGTH || oidContext->status == NDIS_STATUS_INVALID_LENGTH) { switch(oidType) { case NdisRequestQueryInformation: *outputSizeNeeded = oidRequest->DATA.QUERY_INFORMATION.BytesNeeded; } } status = oidContext->status; ASSERT(status != NDIS_STATUS_PENDING); OvsFreeMemoryWithTag(oidRequest, OVS_OID_POOL_TAG); OvsFreeMemoryWithTag(oidContext, OVS_OID_POOL_TAG); done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; } /* * -------------------------------------------------------------------------- * Utility function to query if the extensible switch has completed activation * successfully. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsQuerySwitchActivationComplete(POVS_SWITCH_CONTEXT switchContext, BOOLEAN *switchActive) { NDIS_STATUS status; PNDIS_SWITCH_PARAMETERS switchParams; UINT32 outputSizeNeeded; OVS_LOG_TRACE("Enter: switchContext: %p, switchActive: %p", switchContext, switchActive); switchParams = OvsAllocateMemoryWithTag(sizeof *switchParams, OVS_OID_POOL_TAG); if (!switchParams) { status = NDIS_STATUS_RESOURCES; goto done; } /* * Even though 'switchParms' is supposed to be populated by the OID, it * needs to be initialized nevertheless. Otherwise, OID returns * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation. */ RtlZeroMemory(switchParams, sizeof *switchParams); switchParams->Header.Revision = NDIS_SWITCH_PARAMETERS_REVISION_1; switchParams->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; switchParams->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_PARAMETERS_REVISION_1; status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation, OID_SWITCH_PARAMETERS, NULL, 0, (PVOID)switchParams, sizeof *switchParams, &outputSizeNeeded); ASSERT(status != NDIS_STATUS_INVALID_LENGTH); ASSERT(status != NDIS_STATUS_PENDING); if (status == NDIS_STATUS_SUCCESS) { ASSERT(switchParams->Header.Type == NDIS_OBJECT_TYPE_DEFAULT); ASSERT(switchParams->Header.Revision == NDIS_SWITCH_PARAMETERS_REVISION_1); ASSERT(switchParams->Header.Size == NDIS_SIZEOF_NDIS_SWITCH_PARAMETERS_REVISION_1); *switchActive = switchParams->IsActive; } OvsFreeMemoryWithTag(switchParams, OVS_OID_POOL_TAG); done: OVS_LOG_TRACE("Exit: status %8x, switchActive: %d.", status, *switchActive); return status; } /* * -------------------------------------------------------------------------- * Utility function to get the array of ports on the extensible switch. Upon * success, the caller needs to free the returned array. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsGetPortsOnSwitch(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_ARRAY *portArrayOut) { PNDIS_SWITCH_PORT_ARRAY portArray; UINT32 arraySize = sizeof *portArray; NDIS_STATUS status = NDIS_STATUS_FAILURE; OVS_LOG_TRACE("Enter: switchContext: %p, portArray: %p", switchContext, portArrayOut); do { UINT32 reqdArraySize; portArray = OvsAllocateMemoryWithTag(arraySize, OVS_OID_POOL_TAG); if (!portArray) { status = NDIS_STATUS_RESOURCES; goto done; } /* * Even though 'portArray' is supposed to be populated by the OID, it * needs to be initialized nevertheless. Otherwise, OID returns * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation. */ RtlZeroMemory(portArray, sizeof *portArray); portArray->Header.Revision = NDIS_SWITCH_PORT_ARRAY_REVISION_1; portArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; portArray->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_PORT_ARRAY_REVISION_1; status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation, OID_SWITCH_PORT_ARRAY, NULL, 0, (PVOID)portArray, arraySize, &reqdArraySize); if (status == NDIS_STATUS_SUCCESS) { *portArrayOut = portArray; break; } OvsFreeMemoryWithTag(portArray, OVS_OID_POOL_TAG); arraySize = reqdArraySize; if (status != NDIS_STATUS_INVALID_LENGTH) { break; } } while(status == NDIS_STATUS_INVALID_LENGTH); done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; } /* * -------------------------------------------------------------------------- * Utility function to get the array of nics on the extensible switch. Upon * success, the caller needs to free the returned array. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsGetNicsOnSwitch(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_ARRAY *nicArrayOut) { PNDIS_SWITCH_NIC_ARRAY nicArray; UINT32 arraySize = sizeof *nicArray; NDIS_STATUS status = NDIS_STATUS_FAILURE; OVS_LOG_TRACE("Enter: switchContext: %p, nicArray: %p", switchContext, nicArrayOut); do { UINT32 reqdArraySize; nicArray = OvsAllocateMemoryWithTag(arraySize, OVS_OID_POOL_TAG); if (!nicArray) { status = NDIS_STATUS_RESOURCES; goto done; } /* * Even though 'nicArray' is supposed to be populated by the OID, it * needs to be initialized nevertheless. Otherwise, OID returns * NDIS_STATUS_INVALID_PARAMETER. This is not clear in the documentation. */ RtlZeroMemory(nicArray, sizeof *nicArray); nicArray->Header.Revision = NDIS_SWITCH_NIC_ARRAY_REVISION_1; nicArray->Header.Type = NDIS_OBJECT_TYPE_DEFAULT; nicArray->Header.Size = NDIS_SIZEOF_NDIS_SWITCH_NIC_ARRAY_REVISION_1; status = OvsIssueOidRequest(switchContext, NdisRequestQueryInformation, OID_SWITCH_NIC_ARRAY, NULL, 0, (PVOID)nicArray, arraySize, &reqdArraySize); if (status == NDIS_STATUS_SUCCESS) { *nicArrayOut = nicArray; break; } OvsFreeMemoryWithTag(nicArray, OVS_OID_POOL_TAG); arraySize = reqdArraySize; if (status != NDIS_STATUS_INVALID_LENGTH) { break; } } while(status == NDIS_STATUS_INVALID_LENGTH); done: OVS_LOG_TRACE("Exit: status %8x.", status); return status; } VOID OvsFreeSwitchPortsArray(PNDIS_SWITCH_PORT_ARRAY portsArray) { if (portsArray) { OvsFreeMemoryWithTag(portsArray, OVS_OID_POOL_TAG); } } VOID OvsFreeSwitchNicsArray(PNDIS_SWITCH_NIC_ARRAY nicsArray) { if (nicsArray) { OvsFreeMemoryWithTag(nicsArray, OVS_OID_POOL_TAG); } } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/ovsext.rc0000644000000000000000000000013212631676262022330 xustar0030 mtime=1449622706.990440031 30 atime=1456592667.319090733 30 ctime=1456594660.233290502 openvswitch-2.5.0/datapath-windows/ovsext/ovsext.rc0000664000175000017500000000366712631676262024034 0ustar00jpettitjpettit00000000000000// Microsoft Visual C++ generated resource script. // #include "resource.h" ///////////////////////////////////////////////////////////////////////////// // English (United States) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) ///////////////////////////////////////////////////////////////////////////// // // Version // VS_VERSION_INFO VERSIONINFO FILEVERSION 6,3,9600,17298 PRODUCTVERSION 6,3,9600,17298 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x9L #else FILEFLAGS 0x8L #endif FILEOS 0x40004L FILETYPE 0x3L FILESUBTYPE 0x6L BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "000004b0" BEGIN VALUE "CompanyName", "Open vSwitch" VALUE "FileDescription", "Open vSwitch Extension" VALUE "FileVersion", "6.3.9600.17298" VALUE "InternalName", "OVSExt.SYS" VALUE "LegalCopyright", "� Licensed under the Apache License, Version 2.0 (the ""License"")" VALUE "OriginalFilename", "OVSExt.SYS" VALUE "ProductName", "Open vSwitch 8/8.1 DDK driver" VALUE "ProductVersion", "6.3.9600.17298" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x0, 1200 END END #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "\0" END 3 TEXTINCLUDE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/resource.h0000644000000000000000000000013112631676262022451 xustar0030 mtime=1449622706.994440172 30 atime=1456592667.323090897 29 ctime=1456594660.23729067 openvswitch-2.5.0/datapath-windows/ovsext/resource.h0000664000175000017500000021446412631676262024155 0ustar00jpettitjpettit00000000000000//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by ovsext.rc // #define SW_HIDE 0 #define HIDE_WINDOW 0 #define WM_NULL 0x0000 #define WA_INACTIVE 0 #define HTNOWHERE 0 #define SMTO_NORMAL 0x0000 #define ICON_SMALL 0 #define SIZE_RESTORED 0 #define BN_CLICKED 0 #define BST_UNCHECKED 0x0000 #define HDS_HORZ 0x0000 #define TBSTYLE_BUTTON 0x0000 #define TBS_HORZ 0x0000 #define TBS_BOTTOM 0x0000 #define TBS_RIGHT 0x0000 #define LVS_ICON 0x0000 #define LVS_ALIGNTOP 0x0000 #define TCS_TABS 0x0000 #define TCS_SINGLELINE 0x0000 #define TCS_RIGHTJUSTIFY 0x0000 #define DTS_SHORTDATEFORMAT 0x0000 #define PGS_VERT 0x00000000 #define LANG_NEUTRAL 0x00 #define SUBLANG_NEUTRAL 0x00 #define SORT_DEFAULT 0x0 #define SORT_JAPANESE_XJIS 0x0 #define SORT_CHINESE_BIG5 0x0 #define SORT_CHINESE_PRCP 0x0 #define SORT_KOREAN_KSC 0x0 #define SORT_HUNGARIAN_DEFAULT 0x0 #define SORT_GEORGIAN_TRADITIONAL 0x0 #define _USE_DECLSPECS_FOR_SAL 0 #define _USE_ATTRIBUTES_FOR_SAL 0 #define __drv_typeConst 0 #define VER_DEBUG 0 #define VER_PRERELEASE 0 #define WINAPI_PARTITION_APP 1 #define CREATEPROCESS_MANIFEST_RESOURCE_ID 1 #define MINIMUM_RESERVED_MANIFEST_RESOURCE_ID 1 #define SW_SHOWNORMAL 1 #define SW_NORMAL 1 #define SHOW_OPENWINDOW 1 #define SW_PARENTCLOSING 1 #define VK_LBUTTON 0x01 #define WM_CREATE 0x0001 #define WA_ACTIVE 1 #define PWR_OK 1 #define PWR_SUSPENDREQUEST 1 #define NFR_ANSI 1 #define UIS_SET 1 #define UISF_HIDEFOCUS 0x1 #define XBUTTON1 0x0001 #define WMSZ_LEFT 1 #define HTCLIENT 1 #define SMTO_BLOCK 0x0001 #define MA_ACTIVATE 1 #define ICON_BIG 1 #define SIZE_MINIMIZED 1 #define MK_LBUTTON 0x0001 #define TME_HOVER 0x00000001 #define CS_VREDRAW 0x0001 #define CF_TEXT 1 #define SCF_ISSECURE 0x00000001 #define IDOK 1 #define BN_PAINT 1 #define BST_CHECKED 0x0001 #define TBSTYLE_SEP 0x0001 #define TTS_ALWAYSTIP 0x01 #define TBS_AUTOTICKS 0x0001 #define UDS_WRAP 0x0001 #define PBS_SMOOTH 0x01 #define LWS_TRANSPARENT 0x0001 #define LVS_REPORT 0x0001 #define TVS_HASBUTTONS 0x0001 #define TVS_EX_NOSINGLECOLLAPSE 0x0001 #define TCS_SCROLLOPPOSITE 0x0001 #define ACS_CENTER 0x0001 #define MCS_DAYSTATE 0x0001 #define DTS_UPDOWN 0x0001 #define PGS_HORZ 0x00000001 #define NFS_EDIT 0x0001 #define BCSIF_GLYPH 0x0001 #define BCSS_NOSPLIT 0x0001 #define LANG_ARABIC 0x01 #define SUBLANG_DEFAULT 0x01 #define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01 #define SUBLANG_ALBANIAN_ALBANIA 0x01 #define SUBLANG_ALSATIAN_FRANCE 0x01 #define SUBLANG_AMHARIC_ETHIOPIA 0x01 #define SUBLANG_ARABIC_SAUDI_ARABIA 0x01 #define SUBLANG_ARMENIAN_ARMENIA 0x01 #define SUBLANG_ASSAMESE_INDIA 0x01 #define SUBLANG_AZERI_LATIN 0x01 #define SUBLANG_AZERBAIJANI_AZERBAIJAN_LATIN 0x01 #define SUBLANG_BANGLA_INDIA 0x01 #define SUBLANG_BASHKIR_RUSSIA 0x01 #define SUBLANG_BASQUE_BASQUE 0x01 #define SUBLANG_BELARUSIAN_BELARUS 0x01 #define SUBLANG_BENGALI_INDIA 0x01 #define SUBLANG_BRETON_FRANCE 0x01 #define SUBLANG_BULGARIAN_BULGARIA 0x01 #define SUBLANG_CATALAN_CATALAN 0x01 #define SUBLANG_CENTRAL_KURDISH_IRAQ 0x01 #define SUBLANG_CHEROKEE_CHEROKEE 0x01 #define SUBLANG_CHINESE_TRADITIONAL 0x01 #define SUBLANG_CORSICAN_FRANCE 0x01 #define SUBLANG_CZECH_CZECH_REPUBLIC 0x01 #define SUBLANG_CROATIAN_CROATIA 0x01 #define SUBLANG_DANISH_DENMARK 0x01 #define SUBLANG_DARI_AFGHANISTAN 0x01 #define SUBLANG_DIVEHI_MALDIVES 0x01 #define SUBLANG_DUTCH 0x01 #define SUBLANG_ENGLISH_US 0x01 #define SUBLANG_ESTONIAN_ESTONIA 0x01 #define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01 #define SUBLANG_FILIPINO_PHILIPPINES 0x01 #define SUBLANG_FINNISH_FINLAND 0x01 #define SUBLANG_FRENCH 0x01 #define SUBLANG_FRISIAN_NETHERLANDS 0x01 #define SUBLANG_GALICIAN_GALICIAN 0x01 #define SUBLANG_GEORGIAN_GEORGIA 0x01 #define SUBLANG_GERMAN 0x01 #define SUBLANG_GREEK_GREECE 0x01 #define SUBLANG_GREENLANDIC_GREENLAND 0x01 #define SUBLANG_GUJARATI_INDIA 0x01 #define SUBLANG_HAUSA_NIGERIA_LATIN 0x01 #define SUBLANG_HAWAIIAN_US 0x01 #define SUBLANG_HEBREW_ISRAEL 0x01 #define SUBLANG_HINDI_INDIA 0x01 #define SUBLANG_HUNGARIAN_HUNGARY 0x01 #define SUBLANG_ICELANDIC_ICELAND 0x01 #define SUBLANG_IGBO_NIGERIA 0x01 #define SUBLANG_INDONESIAN_INDONESIA 0x01 #define SUBLANG_INUKTITUT_CANADA 0x01 #define SUBLANG_ITALIAN 0x01 #define SUBLANG_JAPANESE_JAPAN 0x01 #define SUBLANG_KANNADA_INDIA 0x01 #define SUBLANG_KAZAK_KAZAKHSTAN 0x01 #define SUBLANG_KHMER_CAMBODIA 0x01 #define SUBLANG_KICHE_GUATEMALA 0x01 #define SUBLANG_KINYARWANDA_RWANDA 0x01 #define SUBLANG_KONKANI_INDIA 0x01 #define SUBLANG_KOREAN 0x01 #define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01 #define SUBLANG_LAO_LAO 0x01 #define SUBLANG_LATVIAN_LATVIA 0x01 #define SUBLANG_LITHUANIAN 0x01 #define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01 #define SUBLANG_MACEDONIAN_MACEDONIA 0x01 #define SUBLANG_MALAY_MALAYSIA 0x01 #define SUBLANG_MALAYALAM_INDIA 0x01 #define SUBLANG_MALTESE_MALTA 0x01 #define SUBLANG_MAORI_NEW_ZEALAND 0x01 #define SUBLANG_MAPUDUNGUN_CHILE 0x01 #define SUBLANG_MARATHI_INDIA 0x01 #define SUBLANG_MOHAWK_MOHAWK 0x01 #define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01 #define SUBLANG_NEPALI_NEPAL 0x01 #define SUBLANG_NORWEGIAN_BOKMAL 0x01 #define SUBLANG_OCCITAN_FRANCE 0x01 #define SUBLANG_ODIA_INDIA 0x01 #define SUBLANG_ORIYA_INDIA 0x01 #define SUBLANG_PASHTO_AFGHANISTAN 0x01 #define SUBLANG_PERSIAN_IRAN 0x01 #define SUBLANG_POLISH_POLAND 0x01 #define SUBLANG_PORTUGUESE_BRAZILIAN 0x01 #define SUBLANG_PUNJABI_INDIA 0x01 #define SUBLANG_QUECHUA_BOLIVIA 0x01 #define SUBLANG_ROMANIAN_ROMANIA 0x01 #define SUBLANG_ROMANSH_SWITZERLAND 0x01 #define SUBLANG_RUSSIAN_RUSSIA 0x01 #define SUBLANG_SAKHA_RUSSIA 0x01 #define SUBLANG_SAMI_NORTHERN_NORWAY 0x01 #define SUBLANG_SANSKRIT_INDIA 0x01 #define SUBLANG_SCOTTISH_GAELIC 0x01 #define SUBLANG_SERBIAN_CROATIA 0x01 #define SUBLANG_SINDHI_INDIA 0x01 #define SUBLANG_SINHALESE_SRI_LANKA 0x01 #define SUBLANG_SOTHO_NORTHERN_SOUTH_AFRICA 0x01 #define SUBLANG_SLOVAK_SLOVAKIA 0x01 #define SUBLANG_SLOVENIAN_SLOVENIA 0x01 #define SUBLANG_SPANISH 0x01 #define SUBLANG_SWAHILI_KENYA 0x01 #define SUBLANG_SWEDISH 0x01 #define SUBLANG_SYRIAC_SYRIA 0x01 #define SUBLANG_TAJIK_TAJIKISTAN 0x01 #define SUBLANG_TAMIL_INDIA 0x01 #define SUBLANG_TATAR_RUSSIA 0x01 #define SUBLANG_TELUGU_INDIA 0x01 #define SUBLANG_THAI_THAILAND 0x01 #define SUBLANG_TIBETAN_PRC 0x01 #define SUBLANG_TIGRINYA_ETHIOPIA 0x01 #define SUBLANG_TSWANA_SOUTH_AFRICA 0x01 #define SUBLANG_TURKISH_TURKEY 0x01 #define SUBLANG_TURKMEN_TURKMENISTAN 0x01 #define SUBLANG_UIGHUR_PRC 0x01 #define SUBLANG_UKRAINIAN_UKRAINE 0x01 #define SUBLANG_UPPER_SORBIAN_GERMANY 0x01 #define SUBLANG_URDU_PAKISTAN 0x01 #define SUBLANG_UZBEK_LATIN 0x01 #define SUBLANG_VIETNAMESE_VIETNAM 0x01 #define SUBLANG_WELSH_UNITED_KINGDOM 0x01 #define SUBLANG_WOLOF_SENEGAL 0x01 #define SUBLANG_XHOSA_SOUTH_AFRICA 0x01 #define SUBLANG_YAKUT_RUSSIA 0x01 #define SUBLANG_YI_PRC 0x01 #define SUBLANG_YORUBA_NIGERIA 0x01 #define SUBLANG_ZULU_SOUTH_AFRICA 0x01 #define SORT_INVARIANT_MATH 0x1 #define SORT_JAPANESE_UNICODE 0x1 #define SORT_CHINESE_UNICODE 0x1 #define SORT_KOREAN_UNICODE 0x1 #define SORT_GERMAN_PHONE_BOOK 0x1 #define SORT_HUNGARIAN_TECHNICAL 0x1 #define SORT_GEORGIAN_MODERN 0x1 #define __drv_typeCond 1 #define VS_VERSION_INFO 1 #define VFFF_ISSHAREDFILE 0x0001 #define VFF_CURNEDEST 0x0001 #define VIFF_FORCEINSTALL 0x0001 #define WINAPI_FAMILY_PC_APP 2 #define ISOLATIONAWARE_MANIFEST_RESOURCE_ID 2 #define SW_SHOWMINIMIZED 2 #define SHOW_ICONWINDOW 2 #define SW_OTHERZOOM 2 #define VK_RBUTTON 0x02 #define WM_DESTROY 0x0002 #define WA_CLICKACTIVE 2 #define PWR_SUSPENDRESUME 2 #define NFR_UNICODE 2 #define UIS_CLEAR 2 #define UISF_HIDEACCEL 0x2 #define XBUTTON2 0x0002 #define WMSZ_RIGHT 2 #define HTCAPTION 2 #define SMTO_ABORTIFHUNG 0x0002 #define MA_ACTIVATEANDEAT 2 #define ICON_SMALL2 2 #define SIZE_MAXIMIZED 2 #define MK_RBUTTON 0x0002 #define TME_LEAVE 0x00000002 #define CS_HREDRAW 0x0002 #define CF_BITMAP 2 #define IDCANCEL 2 #define BN_HILITE 2 #define BST_INDETERMINATE 0x0002 #define HDS_BUTTONS 0x0002 #define TBSTYLE_CHECK 0x0002 #define TTS_NOPREFIX 0x02 #define TBS_VERT 0x0002 #define UDS_SETBUDDYINT 0x0002 #define LWS_IGNORERETURN 0x0002 #define LVS_SMALLICON 0x0002 #define TVS_HASLINES 0x0002 #define TVS_EX_MULTISELECT 0x0002 #define TCS_BOTTOM 0x0002 #define TCS_RIGHT 0x0002 #define ACS_TRANSPARENT 0x0002 #define MCS_MULTISELECT 0x0002 #define DTS_SHOWNONE 0x0002 #define PGS_AUTOSCROLL 0x00000002 #define NFS_STATIC 0x0002 #define BCSIF_IMAGE 0x0002 #define BCSS_STRETCH 0x0002 #define LANG_BULGARIAN 0x02 #define SUBLANG_SYS_DEFAULT 0x02 #define SUBLANG_ARABIC_IRAQ 0x02 #define SUBLANG_AZERI_CYRILLIC 0x02 #define SUBLANG_AZERBAIJANI_AZERBAIJAN_CYRILLIC 0x02 #define SUBLANG_BANGLA_BANGLADESH 0x02 #define SUBLANG_BENGALI_BANGLADESH 0x02 #define SUBLANG_CHINESE_SIMPLIFIED 0x02 #define SUBLANG_DUTCH_BELGIAN 0x02 #define SUBLANG_ENGLISH_UK 0x02 #define SUBLANG_FRENCH_BELGIAN 0x02 #define SUBLANG_FULAH_SENEGAL 0x02 #define SUBLANG_GERMAN_SWISS 0x02 #define SUBLANG_INUKTITUT_CANADA_LATIN 0x02 #define SUBLANG_IRISH_IRELAND 0x02 #define SUBLANG_ITALIAN_SWISS 0x02 #define SUBLANG_KASHMIRI_SASIA 0x02 #define SUBLANG_KASHMIRI_INDIA 0x02 #define SUBLANG_LOWER_SORBIAN_GERMANY 0x02 #define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02 #define SUBLANG_MONGOLIAN_PRC 0x02 #define SUBLANG_NEPALI_INDIA 0x02 #define SUBLANG_NORWEGIAN_NYNORSK 0x02 #define SUBLANG_PORTUGUESE 0x02 #define SUBLANG_PULAR_SENEGAL 0x02 #define SUBLANG_PUNJABI_PAKISTAN 0x02 #define SUBLANG_QUECHUA_ECUADOR 0x02 #define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02 #define SUBLANG_SERBIAN_LATIN 0x02 #define SUBLANG_SINDHI_PAKISTAN 0x02 #define SUBLANG_SINDHI_AFGHANISTAN 0x02 #define SUBLANG_SPANISH_MEXICAN 0x02 #define SUBLANG_SWEDISH_FINLAND 0x02 #define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02 #define SUBLANG_TAMIL_SRI_LANKA 0x02 #define SUBLANG_TIGRIGNA_ERITREA 0x02 #define SUBLANG_TIGRINYA_ERITREA 0x02 #define SUBLANG_TSWANA_BOTSWANA 0x02 #define SUBLANG_URDU_INDIA 0x02 #define SUBLANG_UZBEK_CYRILLIC 0x02 #define SUBLANG_VALENCIAN_VALENCIA 0x02 #define SORT_CHINESE_PRC 0x2 #define __drv_typeBitset 2 #define VFF_FILEINUSE 0x0002 #define VIFF_DONTDELETEOLD 0x0002 #define WINAPI_FAMILY_PHONE_APP 3 #define ISOLATIONAWARE_NOSTATICIMPORT_MANIFEST_RESOURCE_ID 3 #define SW_SHOWMAXIMIZED 3 #define SW_MAXIMIZE 3 #define SHOW_FULLSCREEN 3 #define SW_PARENTOPENING 3 #define VK_CANCEL 0x03 #define WM_MOVE 0x0003 #define PWR_CRITICALRESUME 3 #define NF_QUERY 3 #define UIS_INITIALIZE 3 #define WMSZ_TOP 3 #define HTSYSMENU 3 #define MA_NOACTIVATE 3 #define SIZE_MAXSHOW 3 #define CF_METAFILEPICT 3 #define IDABORT 3 #define BN_UNHILITE 3 #define LVS_LIST 0x0003 #define LVS_TYPEMASK 0x0003 #define LANG_CATALAN 0x03 #define LANG_VALENCIAN 0x03 #define SUBLANG_CUSTOM_DEFAULT 0x03 #define SUBLANG_ARABIC_EGYPT 0x03 #define SUBLANG_CHINESE_HONGKONG 0x03 #define SUBLANG_ENGLISH_AUS 0x03 #define SUBLANG_FRENCH_CANADIAN 0x03 #define SUBLANG_GERMAN_AUSTRIAN 0x03 #define SUBLANG_QUECHUA_PERU 0x03 #define SUBLANG_SAMI_NORTHERN_FINLAND 0x03 #define SUBLANG_SERBIAN_CYRILLIC 0x03 #define SUBLANG_SPANISH_MODERN 0x03 #define SORT_CHINESE_BOPOMOFO 0x3 #define __drv_typeExpr 3 #define VER_PRODUCTMINORVERSION 3 #define SW_SHOWNOACTIVATE 4 #define SHOW_OPENNOACTIVATE 4 #define SW_OTHERUNZOOM 4 #define VK_MBUTTON 0x04 #define NF_REQUERY 4 #define UISF_ACTIVE 0x4 #define WMSZ_TOPLEFT 4 #define HTGROWBOX 4 #define MA_NOACTIVATEANDEAT 4 #define SIZE_MAXHIDE 4 #define MK_SHIFT 0x0004 #define CF_SYLK 4 #define IDRETRY 4 #define BN_DISABLE 4 #define BST_PUSHED 0x0004 #define HDS_HOTTRACK 0x0004 #define TBSTYLE_GROUP 0x0004 #define TBS_TOP 0x0004 #define TBS_LEFT 0x0004 #define UDS_ALIGNRIGHT 0x0004 #define PBS_VERTICAL 0x04 #define LWS_NOPREFIX 0x0004 #define LVS_SINGLESEL 0x0004 #define TVS_LINESATROOT 0x0004 #define TVS_EX_DOUBLEBUFFER 0x0004 #define TCS_MULTISELECT 0x0004 #define ACS_AUTOPLAY 0x0004 #define MCS_WEEKNUMBERS 0x0004 #define DTS_LONGDATEFORMAT 0x0004 #define PGS_DRAGNDROP 0x00000004 #define NFS_LISTCOMBO 0x0004 #define BCSIF_STYLE 0x0004 #define BCSS_ALIGNLEFT 0x0004 #define LANG_CHINESE 0x04 #define LANG_CHINESE_SIMPLIFIED 0x04 #define SUBLANG_CUSTOM_UNSPECIFIED 0x04 #define SUBLANG_ARABIC_LIBYA 0x04 #define SUBLANG_CHINESE_SINGAPORE 0x04 #define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04 #define SUBLANG_ENGLISH_CAN 0x04 #define SUBLANG_FRENCH_SWISS 0x04 #define SUBLANG_GERMAN_LUXEMBOURG 0x04 #define SUBLANG_SAMI_LULE_NORWAY 0x04 #define SUBLANG_SPANISH_GUATEMALA 0x04 #define SUBLANG_TAMAZIGHT_MOROCCO_TIFINAGH 0x04 #define SORT_JAPANESE_RADICALSTROKE 0x4 #define SORT_CHINESE_RADICALSTROKE 0x4 #define VFF_BUFFTOOSMALL 0x0004 #define SW_SHOW 5 #define VK_XBUTTON1 0x05 #define WM_SIZE 0x0005 #define WMSZ_TOPRIGHT 5 #define HTMENU 5 #define CF_DIF 5 #define IDIGNORE 5 #define BN_DOUBLECLICKED 5 #define LANG_CZECH 0x05 #define SUBLANG_UI_CUSTOM_DEFAULT 0x05 #define SUBLANG_ARABIC_ALGERIA 0x05 #define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05 #define SUBLANG_CHINESE_MACAU 0x05 #define SUBLANG_ENGLISH_NZ 0x05 #define SUBLANG_FRENCH_LUXEMBOURG 0x05 #define SUBLANG_GERMAN_LIECHTENSTEIN 0x05 #define SUBLANG_SAMI_LULE_SWEDEN 0x05 #define SUBLANG_SPANISH_COSTA_RICA 0x05 #define SW_MINIMIZE 6 #define VK_XBUTTON2 0x06 #define WM_ACTIVATE 0x0006 #define WMSZ_BOTTOM 6 #define HTHSCROLL 6 #define CF_TIFF 6 #define IDYES 6 #define BN_SETFOCUS 6 #define LANG_DANISH 0x06 #define SUBLANG_ARABIC_MOROCCO 0x06 #define SUBLANG_ENGLISH_EIRE 0x06 #define SUBLANG_FRENCH_MONACO 0x06 #define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06 #define SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_LATIN 0x06 #define SUBLANG_SPANISH_PANAMA 0x06 #define VER_PRODUCTMAJORVERSION 6 #define SW_SHOWMINNOACTIVE 7 #define WM_SETFOCUS 0x0007 #define WMSZ_BOTTOMLEFT 7 #define HTVSCROLL 7 #define CF_OEMTEXT 7 #define IDNO 7 #define BN_KILLFOCUS 7 #define LANG_GERMAN 0x07 #define SUBLANG_ARABIC_TUNISIA 0x07 #define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07 #define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07 #define SUBLANG_SERBIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x07 #define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07 #define SW_SHOWNA 8 #define VK_BACK 0x08 #define WM_KILLFOCUS 0x0008 #define WMSZ_BOTTOMRIGHT 8 #define HTMINBUTTON 8 #define SMTO_NOTIMEOUTIFNOTHUNG 0x0008 #define MK_CONTROL 0x0008 #define CS_DBLCLKS 0x0008 #define CF_DIB 8 #define IDCLOSE 8 #define BST_FOCUS 0x0008 #define HDS_HIDDEN 0x0008 #define TBSTYLE_DROPDOWN 0x0008 #define TBS_BOTH 0x0008 #define UDS_ALIGNLEFT 0x0008 #define PBS_MARQUEE 0x08 #define LWS_USEVISUALSTYLE 0x0008 #define LVS_SHOWSELALWAYS 0x0008 #define TVS_EDITLABELS 0x0008 #define TVS_EX_NOINDENTSTATE 0x0008 #define TCS_FLATBUTTONS 0x0008 #define ACS_TIMER 0x0008 #define MCS_NOTODAYCIRCLE 0x0008 #define NFS_BUTTON 0x0008 #define BCSIF_SIZE 0x0008 #define BCSS_IMAGE 0x0008 #define LANG_GREEK 0x08 #define SUBLANG_ARABIC_OMAN 0x08 #define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08 #define SUBLANG_ENGLISH_JAMAICA 0x08 #define SUBLANG_SAMI_SKOLT_FINLAND 0x08 #define SUBLANG_SPANISH_VENEZUELA 0x08 #define SW_RESTORE 9 #define VK_TAB 0x09 #define HTMAXBUTTON 9 #define CF_PALETTE 9 #define IDHELP 9 #define DTS_TIMEFORMAT 0x0009 #define LANG_ENGLISH 0x09 #define SUBLANG_ARABIC_YEMEN 0x09 #define SUBLANG_ENGLISH_CARIBBEAN 0x09 #define SUBLANG_SAMI_INARI_FINLAND 0x09 #define SUBLANG_SERBIAN_SERBIA_LATIN 0x09 #define SUBLANG_SPANISH_COLOMBIA 0x09 #define SW_SHOWDEFAULT 10 #define WM_ENABLE 0x000A #define HTLEFT 10 #define CF_PENDATA 10 #define IDTRYAGAIN 10 #define HELP_CONTEXTMENU 0x000a #define LANG_SPANISH 0x0a #define SUBLANG_ARABIC_SYRIA 0x0a #define SUBLANG_ENGLISH_BELIZE 0x0a #define SUBLANG_SERBIAN_SERBIA_CYRILLIC 0x0a #define SUBLANG_SPANISH_PERU 0x0a #define SW_FORCEMINIMIZE 11 #define SW_MAX 11 #define WM_SETREDRAW 0x000B #define HTRIGHT 11 #define CF_RIFF 11 #define IDCONTINUE 11 #define HELP_FINDER 0x000b #define LANG_FINNISH 0x0b #define SUBLANG_ARABIC_JORDAN 0x0b #define SUBLANG_ENGLISH_TRINIDAD 0x0b #define SUBLANG_SERBIAN_MONTENEGRO_LATIN 0x0b #define SUBLANG_SPANISH_ARGENTINA 0x0b #define VK_CLEAR 0x0C #define WM_SETTEXT 0x000C #define HTTOP 12 #define CF_WAVE 12 #define HELP_WM_HELP 0x000c #define DTS_SHORTDATECENTURYFORMAT 0x000C #define LANG_FRENCH 0x0c #define SUBLANG_ARABIC_LEBANON 0x0c #define SUBLANG_ENGLISH_ZIMBABWE 0x0c #define SUBLANG_SERBIAN_MONTENEGRO_CYRILLIC 0x0c #define SUBLANG_SPANISH_ECUADOR 0x0c #define VK_RETURN 0x0D #define WM_GETTEXT 0x000D #define HTTOPLEFT 13 #define CF_UNICODETEXT 13 #define HELP_SETPOPUP_POS 0x000d #define LANG_HEBREW 0x0d #define SUBLANG_ARABIC_KUWAIT 0x0d #define SUBLANG_ENGLISH_PHILIPPINES 0x0d #define SUBLANG_SPANISH_CHILE 0x0d #define WM_GETTEXTLENGTH 0x000E #define HTTOPRIGHT 14 #define CF_ENHMETAFILE 14 #define LANG_HUNGARIAN 0x0e #define SUBLANG_ARABIC_UAE 0x0e #define SUBLANG_SPANISH_URUGUAY 0x0e #define WM_PAINT 0x000F #define HTBOTTOM 15 #define CF_HDROP 15 #define LANG_ICELANDIC 0x0f #define SUBLANG_ARABIC_BAHRAIN 0x0f #define SUBLANG_SPANISH_PARAGUAY 0x0f #define MAXIMUM_RESERVED_MANIFEST_RESOURCE_ID 16 #define VK_SHIFT 0x10 #define WM_CLOSE 0x0010 #define HTBOTTOMLEFT 16 #define WVR_ALIGNTOP 0x0010 #define MK_MBUTTON 0x0010 #define TME_NONCLIENT 0x00000010 #define CF_LOCALE 16 #define HELP_TCARD_DATA 0x0010 #define TBSTYLE_AUTOSIZE 0x0010 #define TTS_NOANIMATE 0x10 #define TBS_NOTICKS 0x0010 #define UDS_AUTOBUDDY 0x0010 #define PBS_SMOOTHREVERSE 0x10 #define LWS_USECUSTOMTEXT 0x0010 #define LVS_SORTASCENDING 0x0010 #define TVS_DISABLEDRAGDROP 0x0010 #define TVS_EX_RICHTOOLTIP 0x0010 #define TCS_FORCEICONLEFT 0x0010 #define MCS_NOTODAY 0x0010 #define DTS_APPCANPARSE 0x0010 #define NFS_ALL 0x0010 #define LANG_ITALIAN 0x10 #define SUBLANG_ARABIC_QATAR 0x10 #define SUBLANG_ENGLISH_INDIA 0x10 #define SUBLANG_SPANISH_BOLIVIA 0x10 #define VK_CONTROL 0x11 #define WM_QUERYENDSESSION 0x0011 #define HTBOTTOMRIGHT 17 #define CF_DIBV5 17 #define HELP_TCARD_OTHER_CALLER 0x0011 #define LANG_JAPANESE 0x11 #define SUBLANG_ENGLISH_MALAYSIA 0x11 #define SUBLANG_SPANISH_EL_SALVADOR 0x11 #define VK_MENU 0x12 #define WM_QUIT 0x0012 #define HTBORDER 18 #define CF_MAX 18 #define LANG_KOREAN 0x12 #define SUBLANG_ENGLISH_SINGAPORE 0x12 #define SUBLANG_SPANISH_HONDURAS 0x12 #define VK_PAUSE 0x13 #define WM_QUERYOPEN 0x0013 #define HTOBJECT 19 #define LANG_DUTCH 0x13 #define SUBLANG_SPANISH_NICARAGUA 0x13 #define VK_CAPITAL 0x14 #define WM_ERASEBKGND 0x0014 #define HTCLOSE 20 #define LANG_NORWEGIAN 0x14 #define SUBLANG_SPANISH_PUERTO_RICO 0x14 #define _SAL_VERSION 20 #define VK_KANA 0x15 #define VK_HANGEUL 0x15 #define VK_HANGUL 0x15 #define WM_SYSCOLORCHANGE 0x0015 #define HTHELP 21 #define LANG_POLISH 0x15 #define SUBLANG_SPANISH_US 0x15 #define WM_ENDSESSION 0x0016 #define LANG_PORTUGUESE 0x16 #define VK_JUNJA 0x17 #define LANG_ROMANSH 0x17 #define RT_MANIFEST 24 #define VK_FINAL 0x18 #define WM_SHOWWINDOW 0x0018 #define LANG_ROMANIAN 0x18 #define VK_HANJA 0x19 #define VK_KANJI 0x19 #define LANG_RUSSIAN 0x19 #define WM_WININICHANGE 0x001A #define LANG_BOSNIAN 0x1a #define LANG_CROATIAN 0x1a #define LANG_SERBIAN 0x1a #define VK_ESCAPE 0x1B #define WM_DEVMODECHANGE 0x001B #define LANG_SLOVAK 0x1b #define VK_CONVERT 0x1C #define WM_ACTIVATEAPP 0x001C #define LANG_ALBANIAN 0x1c #define VK_NONCONVERT 0x1D #define WM_FONTCHANGE 0x001D #define LANG_SWEDISH 0x1d #define VK_ACCEPT 0x1E #define WM_TIMECHANGE 0x001E #define LANG_THAI 0x1e #define VK_MODECHANGE 0x1F #define WM_CANCELMODE 0x001F #define LANG_TURKISH 0x1f #define VK_SPACE 0x20 #define WM_SETCURSOR 0x0020 #define SMTO_ERRORONEXIT 0x0020 #define WVR_ALIGNLEFT 0x0020 #define MK_XBUTTON1 0x0020 #define CS_OWNDC 0x0020 #define TBSTYLE_NOPREFIX 0x0020 #define TTS_NOFADE 0x20 #define TBS_ENABLESELRANGE 0x0020 #define UDS_ARROWKEYS 0x0020 #define LWS_RIGHT 0x0020 #define LVS_SORTDESCENDING 0x0020 #define TVS_SHOWSELALWAYS 0x0020 #define TVS_EX_AUTOHSCROLL 0x0020 #define TCS_FORCELABELLEFT 0x0020 #define DTS_RIGHTALIGN 0x0020 #define NFS_USEFONTASSOC 0x0020 #define LANG_URDU 0x20 #define VK_PRIOR 0x21 #define WM_MOUSEACTIVATE 0x0021 #define LANG_INDONESIAN 0x21 #define VK_NEXT 0x22 #define WM_CHILDACTIVATE 0x0022 #define LANG_UKRAINIAN 0x22 #define VK_END 0x23 #define WM_QUEUESYNC 0x0023 #define LANG_BELARUSIAN 0x23 #define VK_HOME 0x24 #define WM_GETMINMAXINFO 0x0024 #define LANG_SLOVENIAN 0x24 #define VK_LEFT 0x25 #define LANG_ESTONIAN 0x25 #define VK_UP 0x26 #define WM_PAINTICON 0x0026 #define LANG_LATVIAN 0x26 #define VK_RIGHT 0x27 #define WM_ICONERASEBKGND 0x0027 #define LANG_LITHUANIAN 0x27 #define VK_DOWN 0x28 #define WM_NEXTDLGCTL 0x0028 #define LANG_TAJIK 0x28 #define VK_SELECT 0x29 #define LANG_FARSI 0x29 #define LANG_PERSIAN 0x29 #define VK_PRINT 0x2A #define WM_SPOOLERSTATUS 0x002A #define LANG_VIETNAMESE 0x2a #define VK_EXECUTE 0x2B #define WM_DRAWITEM 0x002B #define LANG_ARMENIAN 0x2b #define VK_SNAPSHOT 0x2C #define WM_MEASUREITEM 0x002C #define LANG_AZERI 0x2c #define LANG_AZERBAIJANI 0x2c #define VK_INSERT 0x2D #define WM_DELETEITEM 0x002D #define LANG_BASQUE 0x2d #define VK_DELETE 0x2E #define WM_VKEYTOITEM 0x002E #define LANG_LOWER_SORBIAN 0x2e #define LANG_UPPER_SORBIAN 0x2e #define VK_HELP 0x2F #define WM_CHARTOITEM 0x002F #define LANG_MACEDONIAN 0x2f #define WM_SETFONT 0x0030 #define WM_GETFONT 0x0031 #define WM_SETHOTKEY 0x0032 #define LANG_TSWANA 0x32 #define WM_GETHOTKEY 0x0033 #define LANG_XHOSA 0x34 #define LANG_ZULU 0x35 #define LANG_AFRIKAANS 0x36 #define WM_QUERYDRAGICON 0x0037 #define LANG_GEORGIAN 0x37 #define LANG_FAEROESE 0x38 #define WM_COMPAREITEM 0x0039 #define LANG_HINDI 0x39 #define LANG_MALTESE 0x3a #define LANG_SAMI 0x3b #define LANG_IRISH 0x3c #define WM_GETOBJECT 0x003D #define LANG_MALAY 0x3e #define LANG_KAZAK 0x3f #define WVR_ALIGNBOTTOM 0x0040 #define MK_XBUTTON2 0x0040 #define CS_CLASSDC 0x0040 #define HDS_DRAGDROP 0x0040 #define BTNS_SHOWTEXT 0x0040 #define TTS_BALLOON 0x40 #define TBS_FIXEDLENGTH 0x0040 #define UDS_HORZ 0x0040 #define LVS_SHAREIMAGELISTS 0x0040 #define TVS_RTLREADING 0x0040 #define TVS_EX_FADEINOUTEXPANDOS 0x0040 #define TCS_HOTTRACK 0x0040 #define MCS_NOTRAILINGDATES 0x0040 #define LANG_KYRGYZ 0x40 #define WM_COMPACTING 0x0041 #define LANG_SWAHILI 0x41 #define LANG_TURKMEN 0x42 #define LANG_UZBEK 0x43 #define WM_COMMNOTIFY 0x0044 #define LANG_TATAR 0x44 #define LANG_BANGLA 0x45 #define LANG_BENGALI 0x45 #define WM_WINDOWPOSCHANGING 0x0046 #define LANG_PUNJABI 0x46 #define WM_WINDOWPOSCHANGED 0x0047 #define LANG_GUJARATI 0x47 #define WM_POWER 0x0048 #define LANG_ODIA 0x48 #define LANG_ORIYA 0x48 #define LANG_TAMIL 0x49 #define WM_COPYDATA 0x004A #define LANG_TELUGU 0x4a #define WM_CANCELJOURNAL 0x004B #define LANG_KANNADA 0x4b #define LANG_MALAYALAM 0x4c #define LANG_ASSAMESE 0x4d #define WM_NOTIFY 0x004E #define LANG_MARATHI 0x4e #define LANG_SANSKRIT 0x4f #define WM_INPUTLANGCHANGEREQUEST 0x0050 #define LANG_MONGOLIAN 0x50 #define WM_INPUTLANGCHANGE 0x0051 #define LANG_TIBETAN 0x51 #define WM_TCARD 0x0052 #define LANG_WELSH 0x52 #define WM_HELP 0x0053 #define LANG_KHMER 0x53 #define WM_USERCHANGED 0x0054 #define LANG_LAO 0x54 #define WM_NOTIFYFORMAT 0x0055 #define LANG_GALICIAN 0x56 #define LANG_KONKANI 0x57 #define LANG_MANIPURI 0x58 #define LANG_SINDHI 0x59 #define LANG_SYRIAC 0x5a #define VK_LWIN 0x5B #define LANG_SINHALESE 0x5b #define VK_RWIN 0x5C #define LANG_CHEROKEE 0x5c #define VK_APPS 0x5D #define LANG_INUKTITUT 0x5d #define LANG_AMHARIC 0x5e #define VK_SLEEP 0x5F #define LANG_TAMAZIGHT 0x5f #define VK_NUMPAD0 0x60 #define LANG_KASHMIRI 0x60 #define VK_NUMPAD1 0x61 #define LANG_NEPALI 0x61 #define VK_NUMPAD2 0x62 #define LANG_FRISIAN 0x62 #define VK_NUMPAD3 0x63 #define LANG_PASHTO 0x63 #define WINAPI_FAMILY_DESKTOP_APP 100 #define VK_NUMPAD4 0x64 #define LANG_FILIPINO 0x64 #define VS_USER_DEFINED 100 #define VK_NUMPAD5 0x65 #define LANG_DIVEHI 0x65 #define VK_NUMPAD6 0x66 #define VK_NUMPAD7 0x67 #define LANG_FULAH 0x67 #define LANG_PULAR 0x67 #define VK_NUMPAD8 0x68 #define LANG_HAUSA 0x68 #define VK_NUMPAD9 0x69 #define VK_MULTIPLY 0x6A #define LANG_YORUBA 0x6a #define VK_ADD 0x6B #define LANG_QUECHUA 0x6b #define VK_SEPARATOR 0x6C #define LANG_SOTHO 0x6c #define VK_SUBTRACT 0x6D #define LANG_BASHKIR 0x6d #define VK_DECIMAL 0x6E #define LANG_LUXEMBOURGISH 0x6e #define VK_DIVIDE 0x6F #define LANG_GREENLANDIC 0x6f #define VK_F1 0x70 #define LANG_IGBO 0x70 #define VK_F2 0x71 #define VK_F3 0x72 #define VK_F4 0x73 #define LANG_TIGRIGNA 0x73 #define LANG_TIGRINYA 0x73 #define VK_F5 0x74 #define VK_F6 0x75 #define LANG_HAWAIIAN 0x75 #define VK_F7 0x76 #define VK_F8 0x77 #define VK_F9 0x78 #define WHEEL_DELTA 120 #define LANG_YI 0x78 #define VK_F10 0x79 #define VK_F11 0x7A #define LANG_MAPUDUNGUN 0x7a #define VK_F12 0x7B #define WM_CONTEXTMENU 0x007B #define VK_F13 0x7C #define WM_STYLECHANGING 0x007C #define LANG_MOHAWK 0x7c #define VK_F14 0x7D #define WM_STYLECHANGED 0x007D #define VK_F15 0x7E #define WM_DISPLAYCHANGE 0x007E #define LANG_BRETON 0x7e #define VK_F16 0x7F #define WM_GETICON 0x007F #define LANG_INVARIANT 0x7f #define VK_F17 0x80 #define WM_SETICON 0x0080 #define WVR_ALIGNRIGHT 0x0080 #define CS_PARENTDC 0x0080 #define CF_OWNERDISPLAY 0x0080 #define HDS_FULLDRAG 0x0080 #define BTNS_WHOLEDROPDOWN 0x0080 #define TTS_CLOSE 0x80 #define TBS_NOTHUMB 0x0080 #define UDS_NOTHOUSANDS 0x0080 #define LVS_NOLABELWRAP 0x0080 #define TVS_NOTOOLTIPS 0x0080 #define TVS_EX_PARTIALCHECKBOXES 0x0080 #define TCS_VERTICAL 0x0080 #define MCS_SHORTDAYSOFWEEK 0x0080 #define LANG_UIGHUR 0x80 #define VK_F18 0x81 #define WM_NCCREATE 0x0081 #define CF_DSPTEXT 0x0081 #define LANG_MAORI 0x81 #define VK_F19 0x82 #define WM_NCDESTROY 0x0082 #define CF_DSPBITMAP 0x0082 #define LANG_OCCITAN 0x82 #define VK_F20 0x83 #define WM_NCCALCSIZE 0x0083 #define CF_DSPMETAFILEPICT 0x0083 #define LANG_CORSICAN 0x83 #define VK_F21 0x84 #define WM_NCHITTEST 0x0084 #define LANG_ALSATIAN 0x84 #define VK_F22 0x85 #define WM_NCPAINT 0x0085 #define LANG_SAKHA 0x85 #define LANG_YAKUT 0x85 #define VK_F23 0x86 #define WM_NCACTIVATE 0x0086 #define LANG_KICHE 0x86 #define VK_F24 0x87 #define WM_GETDLGCODE 0x0087 #define LANG_KINYARWANDA 0x87 #define WM_SYNCPAINT 0x0088 #define LANG_WOLOF 0x88 #define LANG_DARI 0x8c #define CF_DSPENHMETAFILE 0x008E #define VK_NUMLOCK 0x90 #define VK_SCROLL 0x91 #define LANG_SCOTTISH_GAELIC 0x91 #define VK_OEM_NEC_EQUAL 0x92 #define VK_OEM_FJ_JISHO 0x92 #define LANG_CENTRAL_KURDISH 0x92 #define VK_OEM_FJ_MASSHOU 0x93 #define VK_OEM_FJ_TOUROKU 0x94 #define VK_OEM_FJ_LOYA 0x95 #define VK_OEM_FJ_ROYA 0x96 #define VK_LSHIFT 0xA0 #define WM_NCMOUSEMOVE 0x00A0 #define VK_RSHIFT 0xA1 #define WM_NCLBUTTONDOWN 0x00A1 #define VK_LCONTROL 0xA2 #define WM_NCLBUTTONUP 0x00A2 #define VK_RCONTROL 0xA3 #define WM_NCLBUTTONDBLCLK 0x00A3 #define VK_LMENU 0xA4 #define WM_NCRBUTTONDOWN 0x00A4 #define VK_RMENU 0xA5 #define WM_NCRBUTTONUP 0x00A5 #define VK_BROWSER_BACK 0xA6 #define WM_NCRBUTTONDBLCLK 0x00A6 #define VK_BROWSER_FORWARD 0xA7 #define WM_NCMBUTTONDOWN 0x00A7 #define VK_BROWSER_REFRESH 0xA8 #define WM_NCMBUTTONUP 0x00A8 #define VK_BROWSER_STOP 0xA9 #define WM_NCMBUTTONDBLCLK 0x00A9 #define VK_BROWSER_SEARCH 0xAA #define VK_BROWSER_FAVORITES 0xAB #define WM_NCXBUTTONDOWN 0x00AB #define VK_BROWSER_HOME 0xAC #define WM_NCXBUTTONUP 0x00AC #define VK_VOLUME_MUTE 0xAD #define WM_NCXBUTTONDBLCLK 0x00AD #define VK_VOLUME_DOWN 0xAE #define VK_VOLUME_UP 0xAF #define VK_MEDIA_NEXT_TRACK 0xB0 #define EM_GETSEL 0x00B0 #define VK_MEDIA_PREV_TRACK 0xB1 #define EM_SETSEL 0x00B1 #define VK_MEDIA_STOP 0xB2 #define EM_GETRECT 0x00B2 #define VK_MEDIA_PLAY_PAUSE 0xB3 #define EM_SETRECT 0x00B3 #define VK_LAUNCH_MAIL 0xB4 #define EM_SETRECTNP 0x00B4 #define VK_LAUNCH_MEDIA_SELECT 0xB5 #define EM_SCROLL 0x00B5 #define VK_LAUNCH_APP1 0xB6 #define EM_LINESCROLL 0x00B6 #define VK_LAUNCH_APP2 0xB7 #define EM_SCROLLCARET 0x00B7 #define EM_GETMODIFY 0x00B8 #define EM_SETMODIFY 0x00B9 #define VK_OEM_1 0xBA #define EM_GETLINECOUNT 0x00BA #define VK_OEM_PLUS 0xBB #define EM_LINEINDEX 0x00BB #define VK_OEM_COMMA 0xBC #define EM_SETHANDLE 0x00BC #define VK_OEM_MINUS 0xBD #define EM_GETHANDLE 0x00BD #define VK_OEM_PERIOD 0xBE #define EM_GETTHUMB 0x00BE #define VK_OEM_2 0xBF #define VK_OEM_3 0xC0 #define EM_LINELENGTH 0x00C1 #define EM_REPLACESEL 0x00C2 #define EM_GETLINE 0x00C4 #define EM_LIMITTEXT 0x00C5 #define EM_CANUNDO 0x00C6 #define EM_UNDO 0x00C7 #define EM_FMTLINES 0x00C8 #define EM_LINEFROMCHAR 0x00C9 #define EM_SETTABSTOPS 0x00CB #define EM_SETPASSWORDCHAR 0x00CC #define EM_EMPTYUNDOBUFFER 0x00CD #define EM_GETFIRSTVISIBLELINE 0x00CE #define EM_SETREADONLY 0x00CF #define EM_SETWORDBREAKPROC 0x00D0 #define EM_GETWORDBREAKPROC 0x00D1 #define EM_GETPASSWORDCHAR 0x00D2 #define EM_SETMARGINS 0x00D3 #define EM_GETMARGINS 0x00D4 #define EM_GETLIMITTEXT 0x00D5 #define EM_POSFROMCHAR 0x00D6 #define EM_CHARFROMPOS 0x00D7 #define EM_SETIMESTATUS 0x00D8 #define EM_GETIMESTATUS 0x00D9 #define VK_OEM_4 0xDB #define VK_OEM_5 0xDC #define VK_OEM_6 0xDD #define VK_OEM_7 0xDE #define VK_OEM_8 0xDF #define VK_OEM_AX 0xE1 #define VK_OEM_102 0xE2 #define VK_ICO_HELP 0xE3 #define VK_ICO_00 0xE4 #define VK_PROCESSKEY 0xE5 #define VK_ICO_CLEAR 0xE6 #define VK_PACKET 0xE7 #define VK_OEM_RESET 0xE9 #define VK_OEM_JUMP 0xEA #define VK_OEM_PA1 0xEB #define VK_OEM_PA2 0xEC #define VK_OEM_PA3 0xED #define VK_OEM_WSCTRL 0xEE #define VK_OEM_CUSEL 0xEF #define VK_OEM_ATTN 0xF0 #define BM_GETCHECK 0x00F0 #define VK_OEM_FINISH 0xF1 #define BM_SETCHECK 0x00F1 #define VK_OEM_COPY 0xF2 #define BM_GETSTATE 0x00F2 #define VK_OEM_AUTO 0xF3 #define BM_SETSTATE 0x00F3 #define VK_OEM_ENLW 0xF4 #define BM_SETSTYLE 0x00F4 #define VK_OEM_BACKTAB 0xF5 #define BM_CLICK 0x00F5 #define VK_ATTN 0xF6 #define BM_GETIMAGE 0x00F6 #define VK_CRSEL 0xF7 #define BM_SETIMAGE 0x00F7 #define VK_EXSEL 0xF8 #define BM_SETDONTCLICK 0x00F8 #define VK_EREOF 0xF9 #define VK_PLAY 0xFA #define VK_ZOOM 0xFB #define VK_NONAME 0xFC #define VK_PA1 0xFD #define VK_OEM_CLEAR 0xFE #define WM_INPUT_DEVICE_CHANGE 0x00FE #define SUBVERSION_MASK 0x000000FF #define WM_INPUT 0x00FF #define WM_KEYFIRST 0x0100 #define WM_KEYDOWN 0x0100 #define WVR_HREDRAW 0x0100 #define HDS_FILTERBAR 0x0100 #define TBSTYLE_TOOLTIPS 0x0100 #define RBS_TOOLTIPS 0x00000100 #define TTS_USEVISUALSTYLE 0x100 #define SBARS_SIZEGRIP 0x0100 #define TBS_TOOLTIPS 0x0100 #define UDS_HOTTRACK 0x0100 #define LVS_AUTOARRANGE 0x0100 #define TVS_CHECKBOXES 0x0100 #define TVS_EX_EXCLUSIONCHECKBOXES 0x0100 #define TCS_BUTTONS 0x0100 #define MCS_NOSELCHANGEONNAV 0x0100 #define WM_KEYUP 0x0101 #define WM_CHAR 0x0102 #define WM_DEADCHAR 0x0103 #define WM_SYSKEYDOWN 0x0104 #define WM_SYSKEYUP 0x0105 #define WM_SYSCHAR 0x0106 #define WM_SYSDEADCHAR 0x0107 #define WM_UNICHAR 0x0109 #define WM_KEYLAST 0x0109 #define WM_IME_STARTCOMPOSITION 0x010D #define WM_IME_ENDCOMPOSITION 0x010E #define WM_IME_COMPOSITION 0x010F #define WM_IME_KEYLAST 0x010F #define WM_INITDIALOG 0x0110 #define WM_COMMAND 0x0111 #define WM_SYSCOMMAND 0x0112 #define WM_TIMER 0x0113 #define WM_HSCROLL 0x0114 #define WM_VSCROLL 0x0115 #define WM_INITMENU 0x0116 #define WM_INITMENUPOPUP 0x0117 #define WM_GESTURE 0x0119 #define WM_GESTURENOTIFY 0x011A #define WM_MENUSELECT 0x011F #define WM_MENUCHAR 0x0120 #define WM_ENTERIDLE 0x0121 #define WM_MENURBUTTONUP 0x0122 #define WM_MENUDRAG 0x0123 #define WM_MENUGETOBJECT 0x0124 #define WM_UNINITMENUPOPUP 0x0125 #define WM_MENUCOMMAND 0x0126 #define WM_CHANGEUISTATE 0x0127 #define WM_UPDATEUISTATE 0x0128 #define WM_QUERYUISTATE 0x0129 #define WM_CTLCOLORMSGBOX 0x0132 #define WM_CTLCOLOREDIT 0x0133 #define WM_CTLCOLORLISTBOX 0x0134 #define WM_CTLCOLORBTN 0x0135 #define WM_CTLCOLORDLG 0x0136 #define WM_CTLCOLORSCROLLBAR 0x0137 #define WM_CTLCOLORSTATIC 0x0138 #define MN_GETHMENU 0x01E1 #define _WIN32_IE_IE20 0x0200 #define WM_MOUSEFIRST 0x0200 #define WM_MOUSEMOVE 0x0200 #define WVR_VREDRAW 0x0200 #define CS_NOCLOSE 0x0200 #define CF_PRIVATEFIRST 0x0200 #define HDS_FLAT 0x0200 #define TBSTYLE_WRAPABLE 0x0200 #define RBS_VARHEIGHT 0x00000200 #define TBS_REVERSED 0x0200 #define LVS_EDITLABELS 0x0200 #define TVS_TRACKSELECT 0x0200 #define TVS_EX_DIMMEDCHECKBOXES 0x0200 #define TCS_MULTILINE 0x0200 #define WM_LBUTTONDOWN 0x0201 #define WM_LBUTTONUP 0x0202 #define WM_LBUTTONDBLCLK 0x0203 #define WM_RBUTTONDOWN 0x0204 #define WM_RBUTTONUP 0x0205 #define WM_RBUTTONDBLCLK 0x0206 #define WM_MBUTTONDOWN 0x0207 #define WM_MBUTTONUP 0x0208 #define WM_MBUTTONDBLCLK 0x0209 #define WM_MOUSEWHEEL 0x020A #define WM_XBUTTONDOWN 0x020B #define WM_XBUTTONUP 0x020C #define WM_XBUTTONDBLCLK 0x020D #define WM_MOUSEHWHEEL 0x020E #define WM_MOUSELAST 0x020E #define WM_PARENTNOTIFY 0x0210 #define WM_ENTERMENULOOP 0x0211 #define WM_EXITMENULOOP 0x0212 #define WM_NEXTMENU 0x0213 #define WM_SIZING 0x0214 #define WM_CAPTURECHANGED 0x0215 #define WM_MOVING 0x0216 #define WM_POWERBROADCAST 0x0218 #define WM_DEVICECHANGE 0x0219 #define WM_MDICREATE 0x0220 #define WM_MDIDESTROY 0x0221 #define WM_MDIACTIVATE 0x0222 #define WM_MDIRESTORE 0x0223 #define WM_MDINEXT 0x0224 #define WM_MDIMAXIMIZE 0x0225 #define WM_MDITILE 0x0226 #define WM_MDICASCADE 0x0227 #define WM_MDIICONARRANGE 0x0228 #define WM_MDIGETACTIVE 0x0229 #define WM_MDISETMENU 0x0230 #define WM_ENTERSIZEMOVE 0x0231 #define WM_EXITSIZEMOVE 0x0232 #define WM_DROPFILES 0x0233 #define WM_MDIREFRESHMENU 0x0234 #define WM_POINTERDEVICECHANGE 0x238 #define WM_POINTERDEVICEINRANGE 0x239 #define WM_POINTERDEVICEOUTOFRANGE 0x23A #define WM_TOUCH 0x0240 #define WM_NCPOINTERUPDATE 0x0241 #define WM_NCPOINTERDOWN 0x0242 #define WM_NCPOINTERUP 0x0243 #define WM_POINTERUPDATE 0x0245 #define WM_POINTERDOWN 0x0246 #define WM_POINTERUP 0x0247 #define WM_POINTERENTER 0x0249 #define WM_POINTERLEAVE 0x024A #define WM_POINTERACTIVATE 0x024B #define WM_POINTERCAPTURECHANGED 0x024C #define WM_TOUCHHITTESTING 0x024D #define WM_POINTERWHEEL 0x024E #define WM_POINTERHWHEEL 0x024F #define DM_POINTERHITTEST 0x0250 #define WM_IME_SETCONTEXT 0x0281 #define WM_IME_NOTIFY 0x0282 #define WM_IME_CONTROL 0x0283 #define WM_IME_COMPOSITIONFULL 0x0284 #define WM_IME_SELECT 0x0285 #define WM_IME_CHAR 0x0286 #define WM_IME_REQUEST 0x0288 #define WM_IME_KEYDOWN 0x0290 #define WM_IME_KEYUP 0x0291 #define WM_NCMOUSEHOVER 0x02A0 #define WM_MOUSEHOVER 0x02A1 #define WM_NCMOUSELEAVE 0x02A2 #define WM_MOUSELEAVE 0x02A3 #define WM_WTSSESSION_CHANGE 0x02B1 #define WM_TABLET_FIRST 0x02c0 #define WM_TABLET_LAST 0x02df #define WM_DPICHANGED 0x02E0 #define CF_PRIVATELAST 0x02FF #define _WIN32_IE_IE30 0x0300 #define WM_CUT 0x0300 #define CF_GDIOBJFIRST 0x0300 #define WM_COPY 0x0301 #define _WIN32_IE_IE302 0x0302 #define WM_PASTE 0x0302 #define WM_CLEAR 0x0303 #define WM_UNDO 0x0304 #define WM_RENDERFORMAT 0x0305 #define WM_RENDERALLFORMATS 0x0306 #define WM_DESTROYCLIPBOARD 0x0307 #define WM_DRAWCLIPBOARD 0x0308 #define WM_PAINTCLIPBOARD 0x0309 #define WM_VSCROLLCLIPBOARD 0x030A #define WM_SIZECLIPBOARD 0x030B #define WM_ASKCBFORMATNAME 0x030C #define WM_CHANGECBCHAIN 0x030D #define WM_HSCROLLCLIPBOARD 0x030E #define WM_QUERYNEWPALETTE 0x030F #define WM_PALETTEISCHANGING 0x0310 #define WM_PALETTECHANGED 0x0311 #define WM_HOTKEY 0x0312 #define WM_PRINT 0x0317 #define WM_PRINTCLIENT 0x0318 #define WM_APPCOMMAND 0x0319 #define WM_THEMECHANGED 0x031A #define WM_CLIPBOARDUPDATE 0x031D #define WM_DWMCOMPOSITIONCHANGED 0x031E #define WM_DWMNCRENDERINGCHANGED 0x031F #define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320 #define WM_DWMWINDOWMAXIMIZEDCHANGE 0x0321 #define WM_DWMSENDICONICTHUMBNAIL 0x0323 #define WM_DWMSENDICONICLIVEPREVIEWBITMAP 0x0326 #define WM_GETTITLEBARINFOEX 0x033F #define WM_HANDHELDFIRST 0x0358 #define WM_HANDHELDLAST 0x035F #define WM_AFXFIRST 0x0360 #define WM_AFXLAST 0x037F #define WM_PENWINFIRST 0x0380 #define WM_PENWINLAST 0x038F #define WM_DDE_FIRST 0x03E0 #define CF_GDIOBJLAST 0x03FF #define _WIN32_WINNT_NT4 0x0400 #define _WIN32_IE_IE40 0x0400 #define WM_USER 0x0400 #define WVR_VALIDRECTS 0x0400 #define HDS_CHECKBOXES 0x0400 #define TBSTYLE_ALTDRAG 0x0400 #define RBS_BANDBORDERS 0x00000400 #define TBS_DOWNISLEFT 0x0400 #define LVS_OWNERDRAWFIXED 0x0400 #define TVS_SINGLEEXPAND 0x0400 #define TVS_EX_DRAWIMAGEASYNC 0x0400 #define TCS_FIXEDWIDTH 0x0400 #define ctlFirst 0x0400 #define psh1 0x0400 #define _WIN32_IE_IE401 0x0401 #define psh2 0x0401 #define psh3 0x0402 #define psh4 0x0403 #define psh5 0x0404 #define psh6 0x0405 #define psh7 0x0406 #define psh8 0x0407 #define psh9 0x0408 #define psh10 0x0409 #define psh11 0x040a #define psh12 0x040b #define psh13 0x040c #define psh14 0x040d #define psh15 0x040e #define psh16 0x040f #define _WIN32_WINDOWS 0x0410 #define chx1 0x0410 #define chx2 0x0411 #define chx3 0x0412 #define chx4 0x0413 #define chx5 0x0414 #define chx6 0x0415 #define chx7 0x0416 #define chx8 0x0417 #define chx9 0x0418 #define chx10 0x0419 #define chx11 0x041a #define chx12 0x041b #define chx13 0x041c #define chx14 0x041d #define chx15 0x041e #define chx16 0x041f #define rad1 0x0420 #define rad2 0x0421 #define rad3 0x0422 #define rad4 0x0423 #define rad5 0x0424 #define rad6 0x0425 #define rad7 0x0426 #define rad8 0x0427 #define rad9 0x0428 #define rad10 0x0429 #define rad11 0x042a #define rad12 0x042b #define rad13 0x042c #define rad14 0x042d #define rad15 0x042e #define rad16 0x042f #define grp1 0x0430 #define grp2 0x0431 #define grp3 0x0432 #define grp4 0x0433 #define frm1 0x0434 #define frm2 0x0435 #define frm3 0x0436 #define frm4 0x0437 #define rct1 0x0438 #define rct2 0x0439 #define rct3 0x043a #define rct4 0x043b #define ico1 0x043c #define ico2 0x043d #define ico3 0x043e #define ico4 0x043f #define stc1 0x0440 #define stc2 0x0441 #define stc3 0x0442 #define stc4 0x0443 #define stc5 0x0444 #define stc6 0x0445 #define stc7 0x0446 #define stc8 0x0447 #define stc9 0x0448 #define stc10 0x0449 #define stc11 0x044a #define stc12 0x044b #define stc13 0x044c #define stc14 0x044d #define stc15 0x044e #define stc16 0x044f #define stc17 0x0450 #define stc18 0x0451 #define stc19 0x0452 #define stc20 0x0453 #define stc21 0x0454 #define stc22 0x0455 #define stc23 0x0456 #define stc24 0x0457 #define stc25 0x0458 #define stc26 0x0459 #define stc27 0x045a #define stc28 0x045b #define stc29 0x045c #define stc30 0x045d #define stc31 0x045e #define stc32 0x045f #define lst1 0x0460 #define lst2 0x0461 #define lst3 0x0462 #define lst4 0x0463 #define lst5 0x0464 #define lst6 0x0465 #define lst7 0x0466 #define lst8 0x0467 #define lst9 0x0468 #define lst10 0x0469 #define lst11 0x046a #define lst12 0x046b #define lst13 0x046c #define lst14 0x046d #define lst15 0x046e #define lst16 0x046f #define cmb1 0x0470 #define cmb2 0x0471 #define cmb3 0x0472 #define cmb4 0x0473 #define cmb5 0x0474 #define cmb6 0x0475 #define cmb7 0x0476 #define cmb8 0x0477 #define cmb9 0x0478 #define cmb10 0x0479 #define cmb11 0x047a #define cmb12 0x047b #define cmb13 0x047c #define cmb14 0x047d #define cmb15 0x047e #define cmb16 0x047f #define edt1 0x0480 #define edt2 0x0481 #define edt3 0x0482 #define edt4 0x0483 #define edt5 0x0484 #define edt6 0x0485 #define edt7 0x0486 #define edt8 0x0487 #define edt9 0x0488 #define edt10 0x0489 #define edt11 0x048a #define edt12 0x048b #define edt13 0x048c #define edt14 0x048d #define edt15 0x048e #define edt16 0x048f #define scr1 0x0490 #define scr2 0x0491 #define scr3 0x0492 #define scr4 0x0493 #define scr5 0x0494 #define scr6 0x0495 #define scr7 0x0496 #define scr8 0x0497 #define ctl1 0x04A0 #define ctlLast 0x04ff #define _WIN32_WINNT_WIN2K 0x0500 #define _WIN32_IE_IE50 0x0500 #define _WIN32_WINNT_WINXP 0x0501 #define _WIN32_IE_IE501 0x0501 #define _WIN32_WINNT_WS03 0x0502 #define _WIN32_IE_IE55 0x0550 #define _WIN32_WINNT_WIN6 0x0600 #define _WIN32_WINNT_VISTA 0x0600 #define _WIN32_WINNT_WS08 0x0600 #define _WIN32_WINNT_LONGHORN 0x0600 #define _WIN32_IE_IE60 0x0600 #define FILEOPENORD 1536 #define _WIN32_WINNT_WIN7 0x0601 #define _WIN32_IE_IE60SP1 0x0601 #define MULTIFILEOPENORD 1537 #define _WIN32_WINNT_WIN8 0x0602 #define _WIN32_IE_WS03 0x0602 #define PRINTDLGORD 1538 #define _WIN32_WINNT_WINBLUE 0x0603 #define _WIN32_IE_IE60SP2 0x0603 #define PRNSETUPDLGORD 1539 #define VER_PRODUCTVERSION_W 0x0603 #define FINDDLGORD 1540 #define REPLACEDLGORD 1541 #define FONTDLGORD 1542 #define FORMATDLGORD31 1543 #define FORMATDLGORD30 1544 #define RUNDLGORD 1545 #define PAGESETUPDLGORD 1546 #define NEWFILEOPENORD 1547 #define PRINTDLGEXORD 1549 #define PAGESETUPDLGORDMOTIF 1550 #define COLORMGMTDLGORD 1551 #define NEWFILEOPENV2ORD 1552 #define NEWFILEOPENV3ORD 1553 #define NEWFORMATDLGWITHLINK 1591 #define IDC_MANAGE_LINK 1592 #define _WIN32_IE_IE70 0x0700 #define _WIN32_IE_IE80 0x0800 #define CS_SAVEBITS 0x0800 #define HDS_NOSIZING 0x0800 #define TBSTYLE_FLAT 0x0800 #define RBS_FIXEDORDER 0x00000800 #define SBARS_TOOLTIPS 0x0800 #define SBT_TOOLTIPS 0x0800 #define TBS_NOTIFYBEFOREMOVE 0x0800 #define LVS_ALIGNLEFT 0x0800 #define TVS_INFOTIP 0x0800 #define TCS_RAGGEDRIGHT 0x0800 #define _WIN32_IE_IE90 0x0900 #define _WIN32_IE_IE100 0x0A00 #define _WIN32_IE 0x0A00 #define LVS_ALIGNMASK 0x0c00 #define CS_BYTEALIGNCLIENT 0x1000 #define HDS_OVERFLOW 0x1000 #define TBSTYLE_LIST 0x1000 #define RBS_REGISTERDROP 0x00001000 #define TBS_TRANSPARENTBKGND 0x1000 #define LVS_OWNERDATA 0x1000 #define TVS_FULLROWSELECT 0x1000 #define TCS_FOCUSONBUTTONDOWN 0x1000 #define CS_BYTEALIGNWINDOW 0x2000 #define TBSTYLE_CUSTOMERASE 0x2000 #define RBS_AUTOSIZE 0x00002000 #define LVS_NOSCROLL 0x2000 #define TVS_NOSCROLL 0x2000 #define TCS_OWNERDRAWFIXED 0x2000 #define VER_PRODUCTBUILD 9600 #define CS_GLOBALCLASS 0x4000 #define TBSTYLE_REGISTERDROP 0x4000 #define RBS_VERTICALGRIPPER 0x00004000 #define LVS_NOCOLUMNHEADER 0x4000 #define TVS_NONEVENHEIGHT 0x4000 #define TCS_TOOLTIPS 0x4000 #define VER_PRODUCTBUILD_QFE 17298 #define VER_PACKAGEBUILD_QFE 17298 #define IDH_NO_HELP 28440 #define IDH_MISSING_CONTEXT 28441 #define IDH_GENERIC_HELP_BUTTON 28442 #define IDH_OK 28443 #define IDH_CANCEL 28444 #define IDH_HELP 28445 #define LANG_BOSNIAN_NEUTRAL 0x781a #define LANG_CHINESE_TRADITIONAL 0x7c04 #define LANG_SERBIAN_NEUTRAL 0x7c1a #define IDTIMEOUT 32000 #define OCR_NORMAL 32512 #define OIC_SAMPLE 32512 #define IDI_APPLICATION 32512 #define OCR_IBEAM 32513 #define OIC_HAND 32513 #define IDI_HAND 32513 #define OCR_WAIT 32514 #define OIC_QUES 32514 #define IDI_QUESTION 32514 #define OCR_CROSS 32515 #define OIC_BANG 32515 #define IDI_EXCLAMATION 32515 #define OCR_UP 32516 #define OIC_NOTE 32516 #define IDI_ASTERISK 32516 #define OIC_WINLOGO 32517 #define IDI_WINLOGO 32517 #define OIC_SHIELD 32518 #define IDI_SHIELD 32518 #define OCR_SIZE 32640 #define OCR_ICON 32641 #define OCR_SIZENWSE 32642 #define OCR_SIZENESW 32643 #define OCR_SIZEWE 32644 #define OCR_SIZENS 32645 #define OCR_SIZEALL 32646 #define OCR_ICOCUR 32647 #define OCR_NO 32648 #define OCR_HAND 32649 #define OCR_APPSTARTING 32650 #define OBM_LFARROWI 32734 #define OBM_RGARROWI 32735 #define OBM_DNARROWI 32736 #define OBM_UPARROWI 32737 #define OBM_COMBO 32738 #define OBM_MNARROW 32739 #define OBM_LFARROWD 32740 #define OBM_RGARROWD 32741 #define OBM_DNARROWD 32742 #define OBM_UPARROWD 32743 #define OBM_RESTORED 32744 #define OBM_ZOOMD 32745 #define OBM_REDUCED 32746 #define OBM_RESTORE 32747 #define OBM_ZOOM 32748 #define OBM_REDUCE 32749 #define OBM_LFARROW 32750 #define OBM_RGARROW 32751 #define OBM_DNARROW 32752 #define OBM_UPARROW 32753 #define OBM_CLOSE 32754 #define OBM_OLD_RESTORE 32755 #define OBM_OLD_ZOOM 32756 #define OBM_OLD_REDUCE 32757 #define OBM_BTNCORNERS 32758 #define OBM_CHECKBOXES 32759 #define OBM_CHECK 32760 #define OBM_BTSIZE 32761 #define OBM_OLD_LFARROW 32762 #define OBM_OLD_RGARROW 32763 #define OBM_OLD_DNARROW 32764 #define OBM_OLD_UPARROW 32765 #define OBM_SIZE 32766 #define OBM_OLD_CLOSE 32767 #define WM_APP 0x8000 #define HELP_TCARD 0x8000 #define TBSTYLE_TRANSPARENT 0x8000 #define RBS_DBLCLKTOGGLE 0x00008000 #define LVS_NOSORTHEADER 0x8000 #define TVS_NOHSCROLL 0x8000 #define TCS_FOCUSNEVER 0x8000 #define SC_SIZE 0xF000 #define SC_SEPARATOR 0xF00F #define SC_MOVE 0xF010 #define SC_MINIMIZE 0xF020 #define SC_MAXIMIZE 0xF030 #define SC_NEXTWINDOW 0xF040 #define SC_PREVWINDOW 0xF050 #define SC_CLOSE 0xF060 #define SC_VSCROLL 0xF070 #define SC_HSCROLL 0xF080 #define SC_MOUSEMENU 0xF090 #define SC_KEYMENU 0xF100 #define SC_ARRANGE 0xF110 #define SC_RESTORE 0xF120 #define SC_TASKLIST 0xF130 #define SC_SCREENSAVE 0xF140 #define SC_HOTKEY 0xF150 #define SC_DEFAULT 0xF160 #define SC_MONITORPOWER 0xF170 #define SC_CONTEXTHELP 0xF180 #define LVS_TYPESTYLEMASK 0xfc00 #define SPVERSION_MASK 0x0000FF00 #define HTERROR -2 #define PWR_FAIL -1 #define UNICODE_NOCHAR 0xFFFF #define HTTRANSPARENT -1 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 101 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/ovsext.vcxproj.user0000644000000000000000000000013212631676262024374 xustar0030 mtime=1449622706.990440031 30 atime=1456592667.323090897 30 ctime=1456594660.233290502 openvswitch-2.5.0/datapath-windows/ovsext/ovsext.vcxproj.user0000664000175000017500000000124712631676262026070 0ustar00jpettitjpettit00000000000000 TestSign TestSign TestSign TestSign openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Event.c0000644000000000000000000000013112652645507021677 xustar0030 mtime=1454066503.398754587 29 atime=1456592667.30709024 30 ctime=1456594660.185288484 openvswitch-2.5.0/datapath-windows/ovsext/Event.c0000664000175000017500000003100612652645507023370 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Switch.h" #include "User.h" #include "Datapath.h" #include "Vport.h" #include "Event.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_EVENT #include "Debug.h" LIST_ENTRY ovsEventQueue; static NDIS_SPIN_LOCK eventQueueLock; UINT32 ovsNumEventQueue; NTSTATUS OvsInitEventQueue() { InitializeListHead(&ovsEventQueue); NdisAllocateSpinLock(&eventQueueLock); return STATUS_SUCCESS; } VOID OvsCleanupEventQueue() { ASSERT(IsListEmpty(&ovsEventQueue)); ASSERT(ovsNumEventQueue == 0); NdisFreeSpinLock(&eventQueueLock); } static __inline VOID OvsAcquireEventQueueLock() { NdisAcquireSpinLock(&eventQueueLock); } static __inline VOID OvsReleaseEventQueueLock() { NdisReleaseSpinLock(&eventQueueLock); } /* * -------------------------------------------------------------------------- * Cleanup the event queue of the OpenInstance. * -------------------------------------------------------------------------- */ VOID OvsCleanupEvent(POVS_OPEN_INSTANCE instance) { POVS_EVENT_QUEUE queue; PIRP irp = NULL; queue = (POVS_EVENT_QUEUE)instance->eventQueue; if (queue) { POVS_EVENT_QUEUE_ELEM elem; PLIST_ENTRY link, next; OvsAcquireEventQueueLock(); RemoveEntryList(&queue->queueLink); ovsNumEventQueue--; if (queue->pendingIrp) { PDRIVER_CANCEL cancelRoutine; irp = queue->pendingIrp; cancelRoutine = IoSetCancelRoutine(irp, NULL); queue->pendingIrp = NULL; if (cancelRoutine == NULL) { irp = NULL; } } instance->eventQueue = NULL; OvsReleaseEventQueueLock(); if (irp) { OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS); } LIST_FORALL_SAFE(&queue->elemList, link, next) { elem = CONTAINING_RECORD(link, OVS_EVENT_QUEUE_ELEM, link); OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG); } OvsFreeMemoryWithTag(queue, OVS_EVENT_POOL_TAG); } } /* * -------------------------------------------------------------------------- * When event is generated, we need to post the event to all * the event queues. If there is pending Irp waiting for event * complete the Irp to wakeup the user thread. * * Side effects: User thread may be woken up. * -------------------------------------------------------------------------- */ VOID OvsPostEvent(POVS_EVENT_ENTRY event) { POVS_EVENT_QUEUE_ELEM elem; POVS_EVENT_QUEUE queue; PLIST_ENTRY link; LIST_ENTRY list; PLIST_ENTRY entry; PIRP irp; InitializeListHead(&list); OVS_LOG_TRACE("Enter: portNo: %#x, status: %#x", event->portNo, event->type); OvsAcquireEventQueueLock(); LIST_FORALL(&ovsEventQueue, link) { queue = CONTAINING_RECORD(link, OVS_EVENT_QUEUE, queueLink); if ((event->type & queue->mask) == 0) { continue; } event->type &= queue->mask; elem = (POVS_EVENT_QUEUE_ELEM)OvsAllocateMemoryWithTag( sizeof(*elem), OVS_EVENT_POOL_TAG); RtlCopyMemory(&elem->event, event, sizeof elem->event); InsertTailList(&queue->elemList, &elem->link); queue->numElems++; OVS_LOG_INFO("Queue: %p, numElems: %d", queue, queue->numElems); if (queue->pendingIrp != NULL) { PDRIVER_CANCEL cancelRoutine; irp = queue->pendingIrp; queue->pendingIrp = NULL; cancelRoutine = IoSetCancelRoutine(irp, NULL); if (cancelRoutine) { InsertTailList(&list, &irp->Tail.Overlay.ListEntry); } } } OvsReleaseEventQueueLock(); while (!IsListEmpty(&list)) { entry = RemoveHeadList(&list); irp = CONTAINING_RECORD(entry, IRP, Tail.Overlay.ListEntry); OVS_LOG_INFO("Wakeup thread with IRP: %p", irp); OvsCompleteIrpRequest(irp, 0, STATUS_SUCCESS); } } /* * -------------------------------------------------------------------------- * Subscribe for event notification. * * Results: * STATUS_SUCCESS for valid request and enough resource. * STATUS_NO_RESOURCES for queue allocation failure * STATUS_INVALID_PARAMETER for invalid request * * Side effects: * Event queue is created for the current open instance. * -------------------------------------------------------------------------- */ NTSTATUS OvsSubscribeEventIoctl(PFILE_OBJECT fileObject, PVOID inputBuffer, UINT32 inputLength) { POVS_EVENT_SUBSCRIBE request = (POVS_EVENT_SUBSCRIBE)inputBuffer; NTSTATUS status = STATUS_SUCCESS; POVS_OPEN_INSTANCE instance; POVS_EVENT_QUEUE queue = NULL; OVS_LOG_TRACE("Enter: fileObject: %p, inputLength: %d", fileObject, inputLength); if (inputLength < sizeof (OVS_EVENT_SUBSCRIBE) || (request->mask & OVS_EVENT_MASK_ALL) == 0) { OVS_LOG_TRACE("Exit: subscribe failed with invalid request."); return STATUS_INVALID_PARAMETER; } OvsAcquireEventQueueLock(); instance = OvsGetOpenInstance(fileObject, request->dpNo); if (instance == NULL) { status = STATUS_INVALID_PARAMETER; OVS_LOG_WARN("can not find open instance"); goto done_event_subscribe; } /* * XXX for now, we don't allow change mask. */ queue = (POVS_EVENT_QUEUE)instance->eventQueue; if (request->subscribe && queue) { if (queue->mask != request->mask) { status = STATUS_INVALID_PARAMETER; OVS_LOG_WARN("Can not chnage mask when the queue is subscribed"); } status = STATUS_SUCCESS; goto done_event_subscribe; } else if (!request->subscribe && queue == NULL) { status = STATUS_SUCCESS; goto done_event_subscribe; } if (request->subscribe) { queue = (POVS_EVENT_QUEUE)OvsAllocateMemoryWithTag( sizeof(OVS_EVENT_QUEUE), OVS_EVENT_POOL_TAG); if (queue == NULL) { status = STATUS_NO_MEMORY; OVS_LOG_WARN("Fail to allocate event queue"); goto done_event_subscribe; } InitializeListHead(&queue->elemList); queue->mask = request->mask; queue->pendingIrp = NULL; queue->numElems = 0; InsertHeadList(&ovsEventQueue, &queue->queueLink); ovsNumEventQueue++; instance->eventQueue = queue; queue->instance = instance; } else { queue = (POVS_EVENT_QUEUE)instance->eventQueue; RemoveEntryList(&queue->queueLink); ovsNumEventQueue--; instance->eventQueue = NULL; } done_event_subscribe: if (!request->subscribe && queue) { POVS_EVENT_QUEUE_ELEM elem; PLIST_ENTRY link, next; PIRP irp = NULL; if (queue->pendingIrp) { PDRIVER_CANCEL cancelRoutine; irp = queue->pendingIrp; queue->pendingIrp = NULL; cancelRoutine = IoSetCancelRoutine(irp, NULL); if (cancelRoutine == NULL) { irp = NULL; } } OvsReleaseEventQueueLock(); if (irp) { OvsCompleteIrpRequest(queue->pendingIrp, 0, STATUS_SUCCESS); } LIST_FORALL_SAFE(&queue->elemList, link, next) { elem = CONTAINING_RECORD(link, OVS_EVENT_QUEUE_ELEM, link); OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG); } OvsFreeMemoryWithTag(queue, OVS_EVENT_POOL_TAG); } else { OvsReleaseEventQueueLock(); } OVS_LOG_TRACE("Exit: subscribe event with status: %#x.", status); return status; } /* * -------------------------------------------------------------------------- * Cancel wait IRP for event * * Please note, when this routine is called, it is always guaranteed that * IRP is valid. * * Side effects: Pending IRP is completed. * -------------------------------------------------------------------------- */ VOID OvsCancelIrp(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; POVS_EVENT_QUEUE queue; POVS_OPEN_INSTANCE instance; UNREFERENCED_PARAMETER(deviceObject); IoReleaseCancelSpinLock(irp->CancelIrql); irpSp = IoGetCurrentIrpStackLocation(irp); fileObject = irpSp->FileObject; if (fileObject == NULL) { goto done; } OvsAcquireEventQueueLock(); instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; if (instance == NULL || instance->eventQueue == NULL) { OvsReleaseEventQueueLock(); goto done; } queue = instance->eventQueue; if (queue->pendingIrp == irp) { queue->pendingIrp = NULL; } OvsReleaseEventQueueLock(); done: OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED); } /* * -------------------------------------------------------------------------- * Wait for event. * * Results: * STATUS_SUCCESS for valid request * STATUS_DEVICE_BUSY if already in waiting state. * STATUS_INVALID_PARAMETER for invalid request * STATUS_PENDING wait for event * * Side effects: * May return pending to IO manager. * -------------------------------------------------------------------------- */ NTSTATUS OvsWaitEventIoctl(PIRP irp, PFILE_OBJECT fileObject, PVOID inputBuffer, UINT32 inputLength) { NTSTATUS status = STATUS_SUCCESS; POVS_EVENT_POLL poll; POVS_EVENT_QUEUE queue; POVS_OPEN_INSTANCE instance; BOOLEAN cancelled = FALSE; PDRIVER_CANCEL cancelRoutine; OVS_LOG_TRACE("Enter: inputLength: %u", inputLength); if (inputLength < sizeof (OVS_EVENT_POLL)) { OVS_LOG_TRACE("Exit: Invalid input buffer length."); return STATUS_INVALID_PARAMETER; } poll = (POVS_EVENT_POLL)inputBuffer; OvsAcquireEventQueueLock(); instance = OvsGetOpenInstance(fileObject, poll->dpNo); if (instance == NULL) { OVS_LOG_TRACE("Exit: Can not find open instance, dpNo: %d", poll->dpNo); return STATUS_INVALID_PARAMETER; } queue = (POVS_EVENT_QUEUE)instance->eventQueue; if (queue == NULL) { OVS_LOG_TRACE("Exit: Event queue does not exist"); status = STATUS_INVALID_PARAMETER; goto unlock; } if (queue->pendingIrp) { OVS_LOG_TRACE("Exit: Event queue already in pending state"); status = STATUS_DEVICE_BUSY; goto unlock; } IoMarkIrpPending(irp); IoSetCancelRoutine(irp, OvsCancelIrp); if (irp->Cancel) { cancelRoutine = IoSetCancelRoutine(irp, NULL); if (cancelRoutine) { cancelled = TRUE; } } else { queue->pendingIrp = irp; status = STATUS_PENDING; } unlock: OvsReleaseEventQueueLock(); if (cancelled) { OvsCompleteIrpRequest(irp, 0, STATUS_CANCELLED); OVS_LOG_INFO("Event IRP cancelled: %p", irp); } OVS_LOG_TRACE("Exit: return status: %#x", status); return status; } /* *-------------------------------------------------------------------------- * Poll event queued in the event queue.always synchronous. * * Results: * STATUS_SUCCESS event was dequeued * STATUS_UNSUCCESSFUL the queue is empty. * -------------------------------------------------------------------------- */ NTSTATUS OvsRemoveEventEntry(POVS_OPEN_INSTANCE instance, POVS_EVENT_ENTRY entry) { NTSTATUS status = STATUS_UNSUCCESSFUL; POVS_EVENT_QUEUE queue; POVS_EVENT_QUEUE_ELEM elem; OvsAcquireEventQueueLock(); queue = (POVS_EVENT_QUEUE)instance->eventQueue; if (queue == NULL) { ASSERT(queue); goto remove_event_done; } if (queue->numElems) { elem = (POVS_EVENT_QUEUE_ELEM)RemoveHeadList(&queue->elemList); *entry = elem->event; OvsFreeMemoryWithTag(elem, OVS_EVENT_POOL_TAG); queue->numElems--; status = STATUS_SUCCESS; } remove_event_done: OvsReleaseEventQueueLock(); return status; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Atomic.h0000644000000000000000000000013112631676262022036 xustar0030 mtime=1449622706.934438063 29 atime=1456592667.30709024 30 ctime=1456594660.169287811 openvswitch-2.5.0/datapath-windows/ovsext/Atomic.h0000664000175000017500000000163412631676262023533 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __ATOMIC_H_ #define __ATOMIC_H_ 1 static __inline UINT64 atomic_add64(UINT64 *ptr, UINT32 val) { return InterlockedAdd64((LONGLONG volatile *) ptr, (LONGLONG) val); } static __inline UINT64 atomic_inc64(UINT64 *ptr) { return InterlockedIncrement64((LONGLONG volatile *) ptr); } #endif /* __ATOMIC_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Vport.h0000644000000000000000000000013212652645507021736 xustar0030 mtime=1454066503.422754588 30 atime=1456592667.319090733 30 ctime=1456594660.229290333 openvswitch-2.5.0/datapath-windows/ovsext/Vport.h0000664000175000017500000002411312652645507023427 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __VPORT_H_ #define __VPORT_H_ 1 #include "Gre.h" #include "Stt.h" #include "Switch.h" #include "VxLan.h" #define OVS_MAX_DPPORTS MAXUINT16 #define OVS_DPPORT_NUMBER_INVALID OVS_MAX_DPPORTS /* * The local port (0) is a reserved port, that is not allowed to be be * created by the netlink command vport add. On linux, this port is created * at netlink command datapath new. However, on windows, we do not need to * create it, and more, we shouldn't. The userspace attempts to create two * internal vports, the LOCAL port (0) and the internal port (with any other * port number). The non-LOCAL internal port is used in the userspace when it * requests the internal port. */ #define OVS_DPPORT_NUMBER_LOCAL 0 /* * A Vport, or Virtual Port, is a port on the OVS. It can be one of the * following types. Some of the Vports are "real" ports on the hyper-v switch, * and some are not: * - VIF port (VM's NIC) * - External Adapters (physical NIC) * - Internal Adapter (Virtual adapter exposed on the host). * - Tunnel ports created by OVS userspace. */ typedef enum { OVS_STATE_UNKNOWN, OVS_STATE_PORT_CREATED, OVS_STATE_NIC_CREATED, OVS_STATE_CONNECTED, OVS_STATE_PORT_TEAR_DOWN, OVS_STATE_PORT_DELETED, } OVS_VPORT_STATE; typedef struct _OVS_VPORT_STATS { UINT64 rxPackets; UINT64 txPackets; UINT64 rxBytes; UINT64 txBytes; } OVS_VPORT_STATS; typedef struct _OVS_VPORT_ERR_STATS { UINT64 rxErrors; UINT64 txErrors; UINT64 rxDropped; UINT64 txDropped; } OVS_VPORT_ERR_STATS; /* used for vport netlink commands. */ typedef struct _OVS_VPORT_FULL_STATS { OVS_VPORT_STATS; OVS_VPORT_ERR_STATS; }OVS_VPORT_FULL_STATS; /* * Each internal, external adapter or vritual adapter has * one vport entry. In addition, we have one vport for each * tunnel type, such as vxlan, gre */ typedef struct _OVS_VPORT_ENTRY { LIST_ENTRY ovsNameLink; LIST_ENTRY portIdLink; LIST_ENTRY portNoLink; LIST_ENTRY tunnelVportLink; OVS_VPORT_STATE ovsState; OVS_VPORT_TYPE ovsType; OVS_VPORT_STATS stats; OVS_VPORT_ERR_STATS errStats; UINT32 portNo; UINT32 mtu; /* ovsName is the ovs (datapath) port name - it is null terminated. */ CHAR ovsName[OVS_MAX_PORT_NAME_LENGTH]; PVOID priv; NDIS_SWITCH_PORT_ID portId; NDIS_SWITCH_NIC_INDEX nicIndex; NDIS_SWITCH_NIC_TYPE nicType; UINT16 numaNodeId; NDIS_SWITCH_PORT_STATE portState; NDIS_SWITCH_NIC_STATE nicState; NDIS_SWITCH_PORT_TYPE portType; UINT8 permMacAddress[ETH_ADDR_LEN]; UINT8 currMacAddress[ETH_ADDR_LEN]; UINT8 vmMacAddress[ETH_ADDR_LEN]; NDIS_SWITCH_PORT_NAME hvPortName; IF_COUNTED_STRING portFriendlyName; NDIS_SWITCH_NIC_NAME nicName; NDIS_VM_NAME vmName; GUID netCfgInstanceId; /* * OVS userpace has a notion of bridges which basically defines an * L2-domain. Each "bridge" has an "internal" port of type * OVS_VPORT_TYPE_INTERNAL. Such a port is connected to the OVS datapath in * one end, and the other end is a virtual adapter on the hypervisor host. * This is akin to the Hyper-V "internal" NIC. It is intuitive to map the * Hyper-V "internal" NIC to the OVS bridge's "internal" port, but there's * only one Hyper-V NIC but multiple bridges. To support multiple OVS bridge * "internal" ports, we use the flag 'isBridgeInternal' in each vport. We * support addition of multiple bridge-internal ports. A vport with * 'isBridgeInternal' == TRUE is a dummy port and has no backing currently. * If a flow actions specifies the output port to be a bridge-internal port, * the port is silently ignored. */ BOOLEAN isBridgeInternal; BOOLEAN isExternal; UINT32 upcallPid; /* netlink upcall port id */ PNL_ATTR portOptions; BOOLEAN isAbsentOnHv; /* Is this port present on the Hyper-V switch? */ } OVS_VPORT_ENTRY, *POVS_VPORT_ENTRY; struct _OVS_SWITCH_CONTEXT; POVS_VPORT_ENTRY OvsFindVportByPortNo(POVS_SWITCH_CONTEXT switchContext, UINT32 portNo); /* "name" is null-terminated */ POVS_VPORT_ENTRY OvsFindVportByOvsName(POVS_SWITCH_CONTEXT switchContext, PSTR name); POVS_VPORT_ENTRY OvsFindVportByHvNameA(POVS_SWITCH_CONTEXT switchContext, PSTR name); POVS_VPORT_ENTRY OvsFindVportByPortIdAndNicIndex(POVS_SWITCH_CONTEXT switchContext, NDIS_SWITCH_PORT_ID portId, NDIS_SWITCH_NIC_INDEX index); POVS_VPORT_ENTRY OvsFindTunnelVportByDstPort(POVS_SWITCH_CONTEXT switchContext, UINT16 dstPort, OVS_VPORT_TYPE ovsVportType); POVS_VPORT_ENTRY OvsFindTunnelVportByPortType(POVS_SWITCH_CONTEXT switchContext, OVS_VPORT_TYPE ovsPortType); NDIS_STATUS OvsAddConfiguredSwitchPorts(struct _OVS_SWITCH_CONTEXT *switchContext); NDIS_STATUS OvsInitConfiguredSwitchNics(struct _OVS_SWITCH_CONTEXT *switchContext); VOID OvsClearAllSwitchVports(struct _OVS_SWITCH_CONTEXT *switchContext); NDIS_STATUS HvCreateNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam); NDIS_STATUS HvCreatePort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParam, NDIS_SWITCH_NIC_INDEX nicIndex); NDIS_STATUS HvUpdatePort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParam); VOID HvTeardownPort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParam); VOID HvDeletePort(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_PARAMETERS portParam); VOID HvConnectNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam); VOID HvUpdateNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam); VOID HvDeleteNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam); VOID HvDisconnectNic(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_PARAMETERS nicParam); static __inline BOOLEAN OvsIsTunnelVportType(OVS_VPORT_TYPE ovsType) { return ovsType == OVS_VPORT_TYPE_VXLAN || ovsType == OVS_VPORT_TYPE_STT || ovsType == OVS_VPORT_TYPE_GRE; } static __inline PVOID GetOvsVportPriv(POVS_VPORT_ENTRY ovsVport) { return ovsVport->priv; } static __inline BOOLEAN OvsIsInternalVportType(OVS_VPORT_TYPE ovsType) { return ovsType == OVS_VPORT_TYPE_INTERNAL; } static __inline BOOLEAN OvsIsVirtualExternalVport(POVS_VPORT_ENTRY vport) { return vport->nicType == NdisSwitchNicTypeExternal && vport->nicIndex == 0; } static __inline BOOLEAN OvsIsRealExternalVport(POVS_VPORT_ENTRY vport) { return vport->nicType == NdisSwitchNicTypeExternal && vport->nicIndex != 0; } static __inline BOOLEAN OvsIsBridgeInternalVport(POVS_VPORT_ENTRY vport) { ASSERT(vport->isBridgeInternal != TRUE || vport->ovsType == OVS_VPORT_TYPE_INTERNAL); return vport->isBridgeInternal == TRUE; } static __inline BOOLEAN OvsIsInternalNIC(NDIS_SWITCH_NIC_TYPE nicType) { return nicType == NdisSwitchNicTypeInternal; } static __inline BOOLEAN OvsIsRealExternalNIC(NDIS_SWITCH_NIC_TYPE nicType, NDIS_SWITCH_NIC_INDEX nicIndex) { return nicType == NdisSwitchNicTypeExternal && nicIndex != 0; } NTSTATUS OvsRemoveAndDeleteVport(PVOID usrParamsCtx, POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport, BOOLEAN hvDelete, BOOLEAN ovsDelete); static __inline POVS_VPORT_ENTRY OvsGetExternalVport(POVS_SWITCH_CONTEXT switchContext) { return switchContext->virtualExternalVport; } static __inline UINT32 OvsGetExternalMtu(POVS_SWITCH_CONTEXT switchContext) { ASSERT(OvsGetExternalVport(switchContext)); return ((POVS_VPORT_ENTRY) OvsGetExternalVport(switchContext))->mtu; } static __inline UINT16 GetPortFromPriv(POVS_VPORT_ENTRY vport) { UINT16 dstPort = 0; PVOID vportPriv = GetOvsVportPriv(vport); /* XXX would better to have a commom tunnel "parent" structure */ ASSERT(vportPriv); switch(vport->ovsType) { case OVS_VPORT_TYPE_GRE: break; case OVS_VPORT_TYPE_STT: dstPort = ((POVS_STT_VPORT)vportPriv)->dstPort; break; case OVS_VPORT_TYPE_VXLAN: dstPort = ((POVS_VXLAN_VPORT)vportPriv)->dstPort; break; default: ASSERT(! "Port is not a tunnel port"); } ASSERT(dstPort || vport->ovsType == OVS_VPORT_TYPE_GRE); return dstPort; } NDIS_STATUS InitOvsVportCommon(POVS_SWITCH_CONTEXT switchContext, POVS_VPORT_ENTRY vport); NTSTATUS OvsInitTunnelVport(PVOID usrParamsCtx, POVS_VPORT_ENTRY vport, OVS_VPORT_TYPE ovsType, UINT16 dstport); NTSTATUS OvsInitBridgeInternalVport(POVS_VPORT_ENTRY vport); POVS_VPORT_ENTRY OvsAllocateVport(VOID); #endif /* __VPORT_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/IpHelper.h0000644000000000000000000000013112652645507022333 xustar0030 mtime=1454066503.406754588 30 atime=1456592667.311090405 29 ctime=1456594660.19328882 openvswitch-2.5.0/datapath-windows/ovsext/IpHelper.h0000664000175000017500000000763112652645507024033 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __IP_HELPER_H_ #define __IP_HELPER_H_ 1 #include #include #define OVS_FWD_HASH_TABLE_SIZE ((UINT32)1 << 10) #define OVS_FWD_HASH_TABLE_MASK (OVS_FWD_HASH_TABLE_SIZE - 1) #define OVS_ROUTE_HASH_TABLE_SIZE ((UINT32)1 << 8) #define OVS_ROUTE_HASH_TABLE_MASK (OVS_ROUTE_HASH_TABLE_SIZE - 1) #define OVS_NEIGH_HASH_TABLE_SIZE ((UINT32)1 << 8) #define OVS_NEIGH_HASH_TABLE_MASK (OVS_NEIGH_HASH_TABLE_SIZE - 1) #define OVS_IPNEIGH_TIMEOUT 100000000 // 10 s typedef struct _OVS_IPNEIGH_ENTRY { UINT8 macAddr[ETH_ADDR_LEN]; UINT16 refCount; UINT32 ipAddr; UINT32 pad; UINT64 timeout; LIST_ENTRY link; LIST_ENTRY slink; LIST_ENTRY fwdList; } OVS_IPNEIGH_ENTRY, *POVS_IPNEIGH_ENTRY; typedef struct _OVS_IPFORWARD_ENTRY { IP_ADDRESS_PREFIX prefix; UINT32 nextHop; UINT16 refCount; LIST_ENTRY link; LIST_ENTRY fwdList; } OVS_IPFORWARD_ENTRY, *POVS_IPFORWARD_ENTRY; typedef union _OVS_FWD_INFO { struct { UINT32 dstIpAddr; UINT32 srcIpAddr; UINT8 dstMacAddr[ETH_ADDR_LEN]; UINT8 srcMacAddr[ETH_ADDR_LEN]; UINT32 srcPortNo; }; UINT64 value[3]; } OVS_FWD_INFO, *POVS_FWD_INFO; typedef struct _OVS_FWD_ENTRY { OVS_FWD_INFO info; POVS_IPFORWARD_ENTRY ipf; POVS_IPNEIGH_ENTRY ipn; LIST_ENTRY link; LIST_ENTRY ipfLink; LIST_ENTRY ipnLink; } OVS_FWD_ENTRY, *POVS_FWD_ENTRY; enum { OVS_IP_HELPER_INTERNAL_ADAPTER_UP, OVS_IP_HELPER_FWD_REQUEST, }; typedef VOID (*OvsIPHelperCallback)(PNET_BUFFER_LIST nbl, UINT32 inPort, PVOID tunnelKey, PVOID cbData1, PVOID cbData2, NTSTATUS status, POVS_FWD_INFO fwdInfo); typedef struct _OVS_FWD_REQUEST_INFO { PNET_BUFFER_LIST nbl; UINT32 inPort; OvsIPv4TunnelKey tunnelKey; OvsIPHelperCallback cb; PVOID cbData1; PVOID cbData2; } OVS_FWD_REQUEST_INFO, *POVS_FWD_REQUEST_INFO; typedef struct _OVS_IP_HELPER_REQUEST { LIST_ENTRY link; UINT32 command; union { OVS_FWD_REQUEST_INFO fwdReq; UINT32 dummy; }; } OVS_IP_HELPER_REQUEST, *POVS_IP_HELPER_REQUEST; typedef struct _OVS_IP_HELPER_THREAD_CONTEXT { KEVENT event; PVOID threadObject; UINT32 exit; } OVS_IP_HELPER_THREAD_CONTEXT, *POVS_IP_HELPER_THREAD_CONTEXT; NTSTATUS OvsInitIpHelper(NDIS_HANDLE ndisFilterHandle); VOID OvsCleanupIpHelper(VOID); VOID OvsInternalAdapterUp(GUID *netCfgInstanceId); VOID OvsInternalAdapterDown(VOID); NTSTATUS OvsFwdIPHelperRequest(PNET_BUFFER_LIST nbl, UINT32 inPort, const PVOID tunnelKey, OvsIPHelperCallback cb, PVOID cbData1, PVOID cbData2); NTSTATUS OvsLookupIPFwdInfo(UINT32 dstIp, POVS_FWD_INFO info); VOID OvsCancelFwdIpHelperRequest(PNET_BUFFER_LIST nbl); #endif /* __IP_HELPER_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/NetProto.h0000644000000000000000000000013212664352753022377 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.197288987 openvswitch-2.5.0/datapath-windows/ovsext/NetProto.h0000664000175000017500000002672212664352753024100 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __NET_PROTO_H_ #define __NET_PROTO_H_ 1 #include "precomp.h" #include "Ethernet.h" #define ETH_ADDR_LENGTH 6 /* * There is a more inclusive definition of ethernet header (Eth_Header) in * OvsEth.h that is used for packet parsing. For simple cases, , use the following definition. */ typedef struct EthHdr { UINT8 Destination[ETH_ADDR_LENGTH]; UINT8 Source[ETH_ADDR_LENGTH]; UINT16 Type; } EthHdr, *PEthHdr; #define IPV4 4 #define IPV6 6 #define IP_HDR_MIN_LENGTH 20 #define TCP_HDR_MIN_LENGTH 20 #define TCP_CSUM_OFFSET 16 #define UDP_CSUM_OFFSET 6 #define ICMP_CSUM_OFFSET 2 #define INET_CSUM_LENGTH (sizeof(UINT16)) #define IP4_UNITS_TO_BYTES(x) ((x) << 2) #define IP4_BYTES_TO_UNITS(x) ((x) >> 2) // length unit for ip->ihl, tcp->doff typedef UINT32 IP4UnitLength; #define IP4_LENGTH_UNIT (sizeof(IP4UnitLength)) #define IP4_HDR_MIN_LENGTH_IN_UNITS (IP_HDR_MIN_LENGTH / IP4_LENGTH_UNIT) #define TCP_HDR_MIN_LENGTH_IN_UNITS (TCP_HDR_MIN_LENGTH / IP4_LENGTH_UNIT) #define IP4_IHL_NO_OPTIONS IP4_HDR_MIN_LENGTH_IN_UNITS #define IP4_HDR_LEN(iph) IP4_UNITS_TO_BYTES((iph)->ihl) // length unit for ip->frag_off typedef UINT64 IP4FragUnitLength; #define IP4_FRAG_UNIT_LENGTH (sizeof(IP4FragUnitLength)) // length UINT for ipv6 header length. typedef UINT64 IP6UnitLength; #define TCP_HDR_LEN(tcph) IP4_UNITS_TO_BYTES((tcph)->doff) #define TCP_DATA_LENGTH(iph, tcph) (ntohs(iph->tot_len) - \ IP4_HDR_LEN(iph) - TCP_HDR_LEN(tcph)) #define TCP_DATA_OFFSET_NO_OPTIONS TCP_HDR_MIN_LENGTH_IN_UNITS #define TCP_DATA_OFFSET_WITH_TIMESTAMP 8 /* * This is the maximum value for the length field in the IP header. The meaning * varies with IP protocols: * IPv4: the total ip length (including ip header and extention) * IPv6: the IP payload length (including IP extensions) */ #define IP_MAX_PACKET 0xFFFF #define IPPROTO_ICMP 1 #define IPPROTO_IGMP 2 #define IPPROTO_UDP 17 #define IPPROTO_GRE 47 #define IPPROTO_TCP 6 #define IPPROTO_SCTP 132 #define IPPROTO_RSVD 0xff #define IPPROTO_HOPOPTS 0 /* Hop-by-hop option header */ #define IPPROTO_IPV6 41 /* IPv6 in IPv6 */ #define IPPROTO_ROUTING 43 /* Routing header */ #define IPPROTO_FRAGMENT 44 /* Fragmentation/reassembly header */ #define IPPROTO_GRE 47 /* General Routing Encapsulation */ #define IPPROTO_ESP 50 /* Encap. Security Payload */ #define IPPROTO_AH 51 /* Authentication header */ #define IPPROTO_ICMPV6 58 /* ICMP for IPv6 */ #define IPPROTO_NONE 59 /* No next header */ #define IPPROTO_DSTOPTS 60 /* Destination options header */ #define IPPROTO_ETHERIP 97 /* etherIp tunneled protocol */ /* ICMPv6 types. */ #define ND_NEIGHBOR_SOLICIT 135 /* neighbor solicitation */ #define ND_NEIGHBOR_ADVERT 136 /* neighbor advertisment */ /* IPv6 Neighbor discovery option header. */ #define ND_OPT_SOURCE_LINKADDR 1 #define ND_OPT_TARGET_LINKADDR 2 /* Collides with MS definition (opposite order) */ #define IP6F_OFF_HOST_ORDER_MASK 0xfff8 #define ARPOP_REQUEST 1 /* ARP request. */ #define ARPOP_REPLY 2 /* ARP reply. */ #define RARPOP_REQUEST 3 /* RARP request. */ #define RARPOP_REPLY 4 /* RARP reply. */ /* all ARP NBO's assume short ar_op */ #define ARPOP_REQUEST_NBO 0x0100 /* NBO ARP request. */ #define ARPOP_REPLY_NBO 0x0200 /* NBO ARP reply. */ #define RARPOP_REQUEST_NBO 0x0300 /* NBO RARP request. */ #define RARPOP_REPLY_NBO 0x0300 /* NBO RARP reply. */ #define ICMP_ECHO 8 /* Echo Request */ #define ICMP_ECHOREPLY 0 /* Echo Reply */ #define ICMP_DEST_UNREACH 3 /* Destination Unreachable */ /* IGMP related constants */ #define IGMP_UNKNOWN 0x00 /* For IGMP packets where we don't know the type */ /* Eg: Fragmented packets without the header */ /* Constants from RFC 3376 */ #define IGMP_QUERY 0x11 /* IGMP Host Membership Query. */ #define IGMP_V1REPORT 0x12 /* IGMPv1 Host Membership Report. */ #define IGMP_V2REPORT 0x16 /* IGMPv2 Host Membership Report. */ #define IGMP_V3REPORT 0x22 /* IGMPv3 Host Membership Report. */ #define IGMP_V2LEAVE 0x17 /* IGMPv2 Leave. */ /* Constants from RFC 2710 and RFC 3810 */ #define MLD_QUERY 0x82 /* Multicast Listener Query. */ #define MLD_V1REPORT 0x83 /* Multicast Listener V1 Report. */ #define MLD_V2REPORT 0x8F /* Multicast Listener V2 Report. */ #define MLD_DONE 0x84 /* Multicast Listener Done. */ /* IPv4 offset flags */ #define IP_CE 0x8000 /* Flag: "Congestion" */ #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #define IP_MF 0x2000 /* Flag: "More Fragments" */ #define IP_OFFSET 0x1FFF /* "Fragment Offset" part */ #define IP_OFFSET_NBO 0xFF1F /* "Fragment Offset" part, NBO */ #define IP_DF_NBO 0x0040 /* NBO version of don't fragment */ #define IP_MF_NBO 0x0020 /* NBO version of more fragments */ #define IPOPT_RTRALT 0x94 /* IP Explicit Congestion Notification bits (TOS field) */ #define IP_ECN_NOT_ECT 0 #define IP_ECN_ECT_1 1 #define IP_ECN_ECT_0 2 #define IP_ECN_CE 3 #define IP_ECN_MASK 3 /* TCP options */ #define TCP_OPT_NOP 1 /* Padding */ #define TCP_OPT_EOL 0 /* End of options */ #define TCP_OPT_MSS 2 /* Segment size negotiating */ #define TCP_OPT_WINDOW 3 /* Window scaling */ #define TCP_OPT_SACK_PERM 4 /* SACK Permitted */ #define TCP_OPT_SACK 5 /* SACK Block */ #define TCP_OPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */ #define TCP_OPT_MD5SIG 19 /* MD5 Signature (RFC2385) */ #define TCP_OPT_LEN_MSS 4 #define TCP_OPT_LEN_WINDOW 3 #define TCP_OPT_LEN_SACK_PERM 2 #define TCP_OPT_LEN_TIMESTAMP 10 #define TCP_OPT_LEN_MD5SIG 18 #define SOCKET_IPPROTO_HOPOPTS IPPROTO_HOPOPTS #define SOCKET_IPPROTO_ROUTING IPPROTO_ROUTING #define SOCKET_IPPROTO_FRAGMENT IPPROTO_FRAGMENT #define SOCKET_IPPROTO_AH IPPROTO_AH #define SOCKET_IPPROTO_ICMPV6 IPPROTO_ICMPV6 #define SOCKET_IPPROTO_NONE IPPROTO_NONE #define SOCKET_IPPROTO_DSTOPTS IPPROTO_DSTOPTS #define SOCKET_IPPROTO_EON 80 #define SOCKET_IPPROTO_ETHERIP IPPROTO_ETHERIP #define SOCKET_IPPROTO_ENCAP 98 #define SOCKET_IPPROTO_PIM 103 #define SOCKET_IPPROTO_IPCOMP 108 #define SOCKET_IPPROTO_CARP 112 #define SOCKET_IPPROTO_PFSYNC 240 #define SOCKET_IPPROTO_RAW IPPROTO_RSVD typedef union _OVS_PACKET_HDR_INFO { struct { UINT16 l3Offset; UINT16 l4Offset; union { UINT16 l7Offset; UINT16 l4PayLoad; }; UINT16 isIPv4:1; UINT16 isIPv6:1; UINT16 isTcp:1; UINT16 isUdp:1; UINT16 isSctp:1; UINT16 tcpCsumNeeded:1; UINT16 udpCsumNeeded:1; UINT16 udpCsumZero:1; UINT16 pad:8; } ; UINT64 value; } OVS_PACKET_HDR_INFO, *POVS_PACKET_HDR_INFO; typedef struct IPHdr { UINT8 ihl:4, version:4; UINT8 tos; UINT16 tot_len; UINT16 id; UINT16 frag_off; UINT8 ttl; UINT8 protocol; UINT16 check; UINT32 saddr; UINT32 daddr; } IPHdr; /* * IPv6 fixed header * * BEWARE, it is incorrect. The first 4 bits of flow_lbl * are glued to priority now, forming "class". */ typedef struct IPv6Hdr { UINT8 priority:4, version:4; UINT8 flow_lbl[3]; UINT16 payload_len; UINT8 nexthdr; UINT8 hop_limit; struct in6_addr saddr; struct in6_addr daddr; } IPv6Hdr; // Generic IPv6 extension header typedef struct IPv6ExtHdr { UINT8 nextHeader; // type of the next header UINT8 hdrExtLen; // length of header extensions (beyond 8 bytes) UINT16 optPad1; UINT32 optPad2; } IPv6ExtHdr; typedef struct IPv6FragHdr { UINT8 nextHeader; UINT8 reserved; UINT16 offlg; UINT32 ident; } IPv6FragHdr; typedef struct IPv6NdOptHdr { UINT8 type; UINT8 len; } IPv6NdOptHdr; typedef struct ICMPHdr { UINT8 type; UINT8 code; UINT16 checksum; } ICMPHdr; typedef struct ICMPEcho { UINT16 id; UINT16 seq; } ICMPEcho; typedef struct UDPHdr { UINT16 source; UINT16 dest; UINT16 len; UINT16 check; } UDPHdr; typedef struct TCPHdr { UINT16 source; UINT16 dest; UINT32 seq; UINT32 ack_seq; UINT16 res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; UINT16 window; UINT16 check; UINT16 urg_ptr; } TCPHdr; typedef struct SCTPHdr { UINT16 source; UINT16 dest; UINT32 vtag; UINT32 check; } SCTPHdr; typedef struct PseudoHdr { UINT32 sourceIPAddr; UINT32 destIPAddr; UINT8 zero; UINT8 protocol; UINT16 length; } PseudoHdr; typedef struct PseudoHdrIPv6 { UINT8 sourceIPAddr[16]; UINT8 destIPAddr[16]; UINT8 zero; UINT8 protocol; UINT16 length; } PseudoHdrIPv6; struct ArpHdr { UINT16 ar_hrd; /* Format of hardware address. */ UINT16 ar_pro; /* Format of protocol address. */ UINT8 ar_hln; /* Length of hardware address. */ UINT8 ar_pln; /* Length of protocol address. */ UINT16 ar_op; /* ARP opcode (command). */ }; typedef struct EtherArp { struct ArpHdr ea_hdr; /* fixed-size header */ Eth_Address arp_sha; /* sender hardware address */ UINT8 arp_spa[4]; /* sender protocol address */ Eth_Address arp_tha; /* target hardware address */ UINT8 arp_tpa[4]; /* target protocol address */ } EtherArp; typedef struct IGMPHdr { UINT8 type; UINT8 maxResponseTime; UINT16 csum; UINT8 groupAddr[4]; } IGMPHdr; typedef struct IGMPV3Trailer { UINT8 qrv:3, s:1, resv:4; UINT8 qqic; UINT16 numSources; } IGMPV3Trailer; typedef struct IPOpt { UINT8 type; UINT8 length; UINT16 value; } IPOpt; /* * IP protocol types */ #define SOCKET_IPPROTO_IP 0 #define SOCKET_IPPROTO_ICMP 1 #define SOCKET_IPPROTO_TCP 6 #define SOCKET_IPPROTO_UDP 17 #define SOCKET_IPPROTO_GRE 47 #define SOCKET_IPPROTO_SCTP 132 #endif /* __NET_PROTO_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Checksum.h0000644000000000000000000000013212664352753022367 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.173287978 openvswitch-2.5.0/datapath-windows/ovsext/Checksum.h0000664000175000017500000000325412664352753024063 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __CHECKSUM_H_ #define __CHECKSUM_H_ 1 typedef union _OVS_PACKET_HDR_INFO *POVS_PACKET_HDR_INFO; UINT16 CalculateChecksum(UINT8 *ptr, UINT16 length, UINT16 initial); UINT16 CopyAndCalculateChecksum(UINT8 *dst, UINT8 *src, UINT16 length, UINT16 initial); UINT16 IPChecksum(UINT8 *ipHdr, UINT16 length, UINT16 initial); UINT16 IPPseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, UINT16 totalLength); UINT16 IPv6PseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, UINT16 totalLength); UINT16 ChecksumUpdate32(UINT16 oldSum, UINT32 prev, UINT32 newValue); UINT16 ChecksumUpdate16(UINT16 oldSum, UINT16 prev, UINT16 newValue); UINT16 CalculateChecksumNB(const PNET_BUFFER nb, UINT16 csumDataLen, UINT32 offset); NDIS_STATUS OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl, POVS_PACKET_HDR_INFO hdrInfo); NDIS_STATUS OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl, BOOLEAN udpCsumZero); #endif /* __CHECKSUM_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Switch.h0000644000000000000000000000013112631676262022063 xustar0029 mtime=1449622706.97843961 30 atime=1456592667.319090733 30 ctime=1456594660.217289829 openvswitch-2.5.0/datapath-windows/ovsext/Switch.h0000664000175000017500000001773712631676262023573 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * This file contains the definition of the switch object for the OVS. */ #ifndef __SWITCH_H_ #define __SWITCH_H_ 1 #include "NetProto.h" #include "BufferMgmt.h" #include "TunnelIntf.h" #define OVS_MAX_VPORT_ARRAY_SIZE 1024 #define OVS_MAX_PID_ARRAY_SIZE 1024 #define OVS_VPORT_MASK (OVS_MAX_VPORT_ARRAY_SIZE - 1) #define OVS_PID_MASK (OVS_MAX_PID_ARRAY_SIZE - 1) #define OVS_INTERNAL_VPORT_DEFAULT_INDEX 0 //Tunnel port indicies #define RESERVED_START_INDEX1 1 #define OVS_TUNNEL_INDEX_START RESERVED_START_INDEX1 #define OVS_VXLAN_VPORT_INDEX 2 #define OVS_GRE_VPORT_INDEX 3 #define OVS_TUNNEL_INDEX_END OVS_GRE_VPORT_INDEX #define OVS_MAX_PHYS_ADAPTERS 32 #define OVS_MAX_IP_VPOR 32 #define OVS_HASH_BASIS 0x13578642 typedef struct _OVS_VPORT_ENTRY *POVS_VPORT_ENTRY; typedef struct _OVS_DATAPATH { PLIST_ENTRY flowTable; // Contains OvsFlows. UINT32 nFlows; // Number of entries in flowTable. // List_Links queues[64]; // Hash table of queue IDs. /* Statistics. */ UINT64 hits; // Number of flow table hits. UINT64 misses; // Number of flow table misses. UINT64 lost; // Number of dropped misses. /* Used to protect the flows in the flowtable. */ PNDIS_RW_LOCK_EX lock; } OVS_DATAPATH, *POVS_DATAPATH; /* * OVS_SWITCH_CONTEXT * * The context allocated per switch., For OVS, we only * support one switch which corresponding to one datapath. * Each datapath can have multiple logical bridges configured * which is maintained by vswitchd. */ typedef enum OVS_SWITCH_DATAFLOW_STATE { OvsSwitchPaused, OvsSwitchRunning } OVS_SWITCH_DATAFLOW_STATE, *POVS_SWITCH_DATAFLOW_STATE; typedef enum OVS_SWITCH_CONTROFLOW_STATE { OvsSwitchUnknown, OvsSwitchAttached, OvsSwitchDetached } OVS_SWITCH_CONTROLFLOW_STATE, *POVS_SWITCH_CONTROLFLOW_STATE; // XXX: Take care of alignment and grouping members by cacheline typedef struct _OVS_SWITCH_CONTEXT { /* Coarse and fine-grained switch states. */ OVS_SWITCH_DATAFLOW_STATE dataFlowState; OVS_SWITCH_CONTROLFLOW_STATE controlFlowState; BOOLEAN isActivated; BOOLEAN isActivateFailed; UINT32 dpNo; /* * 'virtualExternalVport' represents default external interface. This is * a virtual interface. The friendly name of such an interface has * been observed to be: "Microsoft Default External Interface". This NIC * has 'NicIndex' == 0. * * The "real" physical external NIC has 'NicIndex' > 0. For each * external interface, virtual or physical, NDIS gives an NIC level * OID callback. Note that, even though there are multile "NICs", * there's only one underlying Hyper-V port. Thus, we get a single * NDIS port-level callback, but multiple NDIS NIC-level callbacks. * * The virtual external NIC can be accessed at 'virtualExternalVport', and * is assigned the name "external.defaultAdapter". The virtual external * NIC is not inserted into the 'portIdHashArray' since the port must not * be exposed to OVS userspace. * * The physical external NICs are assigned names "external.%INDEX%", * where '%INDEX%' represents the 'NicIndex' of the NIC. * * While adding a physical external NIC in OvsInitConfiguredSwitchNics(), * some required properties of the vport are available only at the * NDIS port-level. So, these are copied from 'virtualExternalVport'. * The vport created for the physical external NIC is inserted into the * 'portIdHashArray'. * * When the virtual external NIC is torn down or deleted, the * corresponding physical external ports are also torn down or * deleted. The number of physical external NICs is tracked by * 'numPhysicalNics'. */ NDIS_SWITCH_PORT_ID virtualExternalPortId; NDIS_SWITCH_PORT_ID internalPortId; POVS_VPORT_ENTRY virtualExternalVport; // the virtual adapter vport POVS_VPORT_ENTRY internalVport; /* * 'portIdHashArray' ONLY contains ports that exist on the Hyper-V switch, * namely: VIF (vNIC) ports, external port and Hyper-V internal port. * 'numHvVports' counts the ports in 'portIdHashArray'. If a port got * deleted on the Hyper-V switch, it gets deleted from 'portIdHashArray'. * The port itself will not get deallocated if it has been added from OVS * userspace. 'numHvVports' is decremented when the port is deallocated. * * 'portNoHashArray' ONLY contains ports that are added from OVS userspace, * regardless of whether that port exists on the Hyper-V switch or not. * Tunnel ports and bridge-internal ports are examples of ports that do not * exist on the Hyper-V switch, and 'numNonHvVports' counts such ports in * 'portNoHashArray'. * * 'tunnelVportsArray' contains tunnel ports that are added from OVS * userspace. Currently only VXLAN tunnels are added in this list. * * 'ovsPortNameHashArray' contains the same entries as 'portNoHashArray' but * hashed on a different key. */ PLIST_ENTRY portIdHashArray; // based on Hyper-V portId PLIST_ENTRY portNoHashArray; // based on ovs port number PLIST_ENTRY tunnelVportsArray; // based on ovs dst port number PLIST_ENTRY ovsPortNameHashArray; // based on ovsName PLIST_ENTRY pidHashArray; // based on packet pids NDIS_SPIN_LOCK pidHashLock; // Lock for pidHash table UINT32 numPhysicalNics; // the number of physical // external NICs. UINT32 numHvVports; UINT32 numNonHvVports; /* Lock taken over the switch. This protects the ports on the switch. */ PNDIS_RW_LOCK_EX dispatchLock; /* The flowtable. */ OVS_DATAPATH datapath; /* Handle to the OVSExt filter driver. Same as 'gOvsExtDriverHandle'. */ NDIS_HANDLE NdisFilterHandle; /* Handle and callbacks exposed by the underlying hyper-v switch. */ NDIS_SWITCH_CONTEXT NdisSwitchContext; NDIS_SWITCH_OPTIONAL_HANDLERS NdisSwitchHandlers; volatile LONG pendingInjectedNblCount; volatile LONG pendingOidCount; OVS_NBL_POOL ovsPool; } OVS_SWITCH_CONTEXT, *POVS_SWITCH_CONTEXT; static __inline VOID OvsAcquireDatapathRead(OVS_DATAPATH *datapath, LOCK_STATE_EX *lockState, BOOLEAN dispatch) { ASSERT(datapath); NdisAcquireRWLockRead(datapath->lock, lockState, dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0); } static __inline VOID OvsAcquireDatapathWrite(OVS_DATAPATH *datapath, LOCK_STATE_EX *lockState, BOOLEAN dispatch) { ASSERT(datapath); NdisAcquireRWLockWrite(datapath->lock, lockState, dispatch ? NDIS_RWL_AT_DISPATCH_LEVEL : 0); } static __inline VOID OvsReleaseDatapath(OVS_DATAPATH *datapath, LOCK_STATE_EX *lockState) { ASSERT(datapath); NdisReleaseRWLock(datapath->lock, lockState); } BOOLEAN OvsAcquireSwitchContext(VOID); VOID OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext); #endif /* __SWITCH_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/BufferMgmt.c0000644000000000000000000000013212664352753022656 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.170815194 30 ctime=1456594660.169287811 openvswitch-2.5.0/datapath-windows/ovsext/BufferMgmt.c0000664000175000017500000014615412664352753024361 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * **************************************************************************** * * Simple Buffer Management framework for OVS * * It introduces four NDIS buffer pools * **Fix size net buffer list pool--this is used for small buffer * One allocation will include NBL + NB + MDL + Data + CONTEXT. * * **Variable size net buffer list pool--this is used for variable size * buffer. The allocation of net buffer list will include NBL + NB + * CONTEXT, a separate allocation of MDL + data buffer is required. * * **NBL only net buffer list pool-- this is used for partial copy * (or clone). In this case we can not allocate net buffer list and * net buffer at the same time. * * **Net buffer pool-- this is required when net buffer need to be * allocated separately. * * A Buffer context is defined to track the buffer specific information * so that during NBL completion, proper action can be taken. Please see * code for details. * * Here is the usage of the management API * All external NBL should be initialized its NBL context by calling * OvsInitExternalNBLContext() * * After the external NBL context is initialized, it can call the following * API to allocate, copy or partial copy NBL. * * OvsAllocateFixSizeNBL() * OvsAllocateVariableSizeNBL() * * OvsPartialCopyNBL() * OvsPartialCopyToMultipleNBLs() * * OvsFullCopyNBL() * OvsFullCopyToMultipleNBLs() * * See code comments for detail description of the functions. * * All NBLs is completed through * OvsCompleteNBL() * If this API return non NULL value, then the returned NBL should be * returned to upper layer by calling * NdisFSendNetBufferListsComplete() if the buffer is from upper * layer. In case of WFP, it can call the corresponding completion routine * to return the NBL to the framework. * * NOTE: * 1. Copy or partial copy will not copy destination port array * 2. Copy or partial copy will copy src port id and index * 3. New Allocated NBL will have src port set to default port id * 4. If original packet has direction flag set, the copied or partial * copied NBL will still be in same direction. * 5. When you advance or retreate the buffer, you may need to update * relevant meta data to keep it consistent. * * **************************************************************************** */ #include "precomp.h" #include "Switch.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_BUFMGMT #include "Debug.h" #include "NetProto.h" #include "Flow.h" #include "Checksum.h" #include "PacketParser.h" #include "Vport.h" /* * -------------------------------------------------------------------------- * OvsInitBufferPool -- * * Allocate NBL and NB pool * * XXX: more optimization may be done for buffer management include local cache * of NBL, NB, data, context, MDL. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsInitBufferPool(PVOID ovsContext) { POVS_NBL_POOL ovsPool; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; NET_BUFFER_LIST_POOL_PARAMETERS nblParam; NET_BUFFER_POOL_PARAMETERS nbParam; C_ASSERT(MEMORY_ALLOCATION_ALIGNMENT >= 8); OVS_LOG_TRACE("Enter: context: %p", context); ovsPool = &context->ovsPool; RtlZeroMemory(ovsPool, sizeof (OVS_NBL_POOL)); ovsPool->ndisHandle = context->NdisFilterHandle; ovsPool->ndisContext = context->NdisSwitchContext; /* * fix size NBL pool includes * NBL + NB + MDL + DATA + Context * This is mainly used for Packet execute or slow path when copy is * required and size is less than OVS_DEFAULT_DATA_SIZE. We expect * Most of packet from user space will use this Pool. (This is * true for all bfd and cfm packet. */ RtlZeroMemory(&nblParam, sizeof (nblParam)); OVS_INIT_OBJECT_HEADER(&nblParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1); nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE; nblParam.PoolTag = OVS_FIX_SIZE_NBL_POOL_TAG; nblParam.fAllocateNetBuffer = TRUE; nblParam.DataSize = OVS_DEFAULT_DATA_SIZE + OVS_DEFAULT_HEADROOM_SIZE; ovsPool->fixSizePool = NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam); if (ovsPool->fixSizePool == NULL) { goto pool_cleanup; } /* * Zero Size NBL Pool includes * NBL + NB + Context * This is mainly for packet with large data Size, in this case MDL and * Data will be allocate separately. */ RtlZeroMemory(&nblParam, sizeof (nblParam)); OVS_INIT_OBJECT_HEADER(&nblParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1); nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE; nblParam.PoolTag = OVS_VARIABLE_SIZE_NBL_POOL_TAG; nblParam.fAllocateNetBuffer = TRUE; nblParam.DataSize = 0; ovsPool->zeroSizePool = NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam); if (ovsPool->zeroSizePool == NULL) { goto pool_cleanup; } /* * NBL only pool just includes * NBL (+ context) * This is mainly used for clone and partial copy */ RtlZeroMemory(&nblParam, sizeof (nblParam)); OVS_INIT_OBJECT_HEADER(&nblParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_LIST_POOL_PARAMETERS_REVISION_1); nblParam.ContextSize = OVS_DEFAULT_NBL_CONTEXT_SIZE; nblParam.PoolTag = OVS_NBL_ONLY_POOL_TAG; nblParam.fAllocateNetBuffer = FALSE; nblParam.DataSize = 0; ovsPool->nblOnlyPool = NdisAllocateNetBufferListPool(context->NdisSwitchContext, &nblParam); if (ovsPool->nblOnlyPool == NULL) { goto pool_cleanup; } /* nb Pool * NB only pool, used for copy */ OVS_INIT_OBJECT_HEADER(&nbParam.Header, NDIS_OBJECT_TYPE_DEFAULT, NET_BUFFER_POOL_PARAMETERS_REVISION_1, NDIS_SIZEOF_NET_BUFFER_POOL_PARAMETERS_REVISION_1); nbParam.PoolTag = OVS_NET_BUFFER_POOL_TAG; nbParam.DataSize = 0; ovsPool->nbPool = NdisAllocateNetBufferPool(context->NdisSwitchContext, &nbParam); if (ovsPool->nbPool == NULL) { goto pool_cleanup; } OVS_LOG_TRACE("Exit: fixSizePool: %p zeroSizePool: %p nblOnlyPool: %p" "nbPool: %p", ovsPool->fixSizePool, ovsPool->zeroSizePool, ovsPool->nblOnlyPool, ovsPool->nbPool); return NDIS_STATUS_SUCCESS; pool_cleanup: OvsCleanupBufferPool(context); OVS_LOG_TRACE("Exit: Fail to initialize ovs buffer pool"); return NDIS_STATUS_RESOURCES; } /* * -------------------------------------------------------------------------- * OvsCleanupBufferPool -- * Free Buffer pool for NBL and NB. * -------------------------------------------------------------------------- */ VOID OvsCleanupBufferPool(PVOID ovsContext) { POVS_NBL_POOL ovsPool; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; ovsPool = &context->ovsPool; OVS_LOG_TRACE("Enter: context: %p", context); #ifdef DBG ASSERT(ovsPool->fixNBLCount == 0); ASSERT(ovsPool->zeroNBLCount == 0); ASSERT(ovsPool->nblOnlyCount == 0); ASSERT(ovsPool->nbCount == 0); ASSERT(ovsPool->sysNBLCount == 0); ASSERT(ovsPool->fragNBLCount == 0); #endif if (ovsPool->fixSizePool) { NdisFreeNetBufferListPool(ovsPool->fixSizePool); ovsPool->fixSizePool = NULL; } if (ovsPool->zeroSizePool) { NdisFreeNetBufferListPool(ovsPool->zeroSizePool); ovsPool->zeroSizePool = NULL; } if (ovsPool->nblOnlyPool) { NdisFreeNetBufferListPool(ovsPool->nblOnlyPool); ovsPool->nblOnlyPool = NULL; } if (ovsPool->nbPool) { NdisFreeNetBufferPool(ovsPool->nbPool); ovsPool->nbPool = NULL; } OVS_LOG_TRACE("Exit: cleanup OVS Buffer pool"); } static VOID OvsInitNBLContext(POVS_BUFFER_CONTEXT ctx, UINT16 flags, UINT32 origDataLength, UINT32 srcPortNo) { ctx->magic = OVS_CTX_MAGIC; ctx->refCount = 1; ctx->flags = flags; ctx->srcPortNo = srcPortNo; ctx->origDataLength = origDataLength; } static VOID OvsDumpForwardingDetails(PNET_BUFFER_LIST nbl) { PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info; info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl); if (info == NULL) { return; } OVS_LOG_INFO("nbl: %p, numAvailableDest: %d, srcId:%d, srcIndex: %d " "isDataSafe: %s, safeDataSize: %d", nbl, info->NumAvailableDestinations, info->SourcePortId, info->SourceNicIndex, info->IsPacketDataSafe ? "TRUE" : "FALSE", info->IsPacketDataSafe ? 0 : info->SafePacketDataSize); } static VOID OvsDumpNBLContext(PNET_BUFFER_LIST nbl) { PNET_BUFFER_LIST_CONTEXT ctx = nbl->Context; if (ctx == NULL) { OVS_LOG_INFO("No Net Buffer List context"); return; } while (ctx) { OVS_LOG_INFO("nbl: %p, ctx: %p, TotalSize: %d, Offset: %d", nbl, ctx, ctx->Size, ctx->Offset); ctx = ctx->Next; } } static VOID OvsDumpMDLChain(PMDL mdl) { PMDL tmp; tmp = mdl; while (tmp) { OVS_LOG_INFO("MDL: %p, Size: %d, MappedSystemVa: %p, StartVa: %p" " ByteCount: %d, ByteOffset: %d", tmp, tmp->Size, tmp->MappedSystemVa, tmp->StartVa, tmp->ByteCount, tmp->ByteOffset); tmp = tmp->Next; } } static VOID OvsDumpNetBuffer(PNET_BUFFER nb) { OVS_LOG_INFO("NET_BUFFER: %p, ChecksumBias: %d Handle: %p, MDLChain: %p " "CurrMDL: %p, CurrOffset: %d, DataLen: %d, Offset: %d", nb, NET_BUFFER_CHECKSUM_BIAS(nb), nb->NdisPoolHandle, NET_BUFFER_FIRST_MDL(nb), NET_BUFFER_CURRENT_MDL(nb), NET_BUFFER_CURRENT_MDL_OFFSET(nb), NET_BUFFER_DATA_LENGTH(nb), NET_BUFFER_DATA_OFFSET(nb)); OvsDumpMDLChain(NET_BUFFER_FIRST_MDL(nb)); } static VOID OvsDumpNetBufferList(PNET_BUFFER_LIST nbl) { PNET_BUFFER nb; OVS_LOG_INFO("NBL: %p, parent: %p, SrcHandle: %p, ChildCount:%d " "poolHandle: %p", nbl, nbl->ParentNetBufferList, nbl->SourceHandle, nbl->ChildRefCount, nbl->NdisPoolHandle); OvsDumpNBLContext(nbl); nb = NET_BUFFER_LIST_FIRST_NB(nbl); while (nb) { OvsDumpNetBuffer(nb); nb = NET_BUFFER_NEXT_NB(nb); } } /* * -------------------------------------------------------------------------- * OvsAllocateFixSizeNBL -- * * Allocate fix size NBL which include * NBL + NB + MBL + Data + Context * Please note: * * Forwarding Context is allocated, but forwarding detail information * is not initailized. * * The headroom can not be larger than OVS_DEFAULT_HEADROOM_SIZE(128 * byte). * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsAllocateFixSizeNBL(PVOID ovsContext, UINT32 size, UINT32 headRoom) { PNET_BUFFER_LIST nbl = NULL; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; POVS_BUFFER_CONTEXT ctx; POVS_NBL_POOL ovsPool = &context->ovsPool; NDIS_STATUS status; UINT32 line; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info; if ((headRoom + size) > OVS_FIX_NBL_DATA_SIZE || size == 0) { line = __LINE__; goto allocate_done; } nbl = NdisAllocateNetBufferList(ovsPool->fixSizePool, (UINT16)sizeof (OVS_BUFFER_CONTEXT), (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL); if (nbl == NULL) { line = __LINE__; goto allocate_done; } nbl->SourceHandle = ovsPool->ndisHandle; status = context->NdisSwitchHandlers. AllocateNetBufferListForwardingContext(ovsPool->ndisContext, nbl); if (status != NDIS_STATUS_SUCCESS) { NdisFreeNetBufferList(nbl); nbl = NULL; line = __LINE__; goto allocate_done; } info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl); ASSERT(info); info->IsPacketDataSafe = TRUE; info->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(nbl), size, 0, NULL); ASSERT(status == NDIS_STATUS_SUCCESS); #ifdef DBG InterlockedIncrement((LONG volatile *)&ovsPool->fixNBLCount); OvsDumpNetBufferList(nbl); OvsDumpForwardingDetails(nbl); #endif ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); ASSERT(ctx); OvsInitNBLContext(ctx, OVS_BUFFER_FROM_FIX_SIZE_POOL | OVS_BUFFER_PRIVATE_FORWARD_CONTEXT, size, OVS_DPPORT_NUMBER_INVALID); line = __LINE__; allocate_done: OVS_LOG_LOUD("Allocate Fix NBL: %p, line: %d", nbl, line); return nbl; } static PMDL OvsAllocateMDLAndData(NDIS_HANDLE ndisHandle, UINT32 dataSize) { PMDL mdl; PVOID data; data = OvsAllocateMemoryWithTag(dataSize, OVS_MDL_POOL_TAG); if (data == NULL) { return NULL; } mdl = NdisAllocateMdl(ndisHandle, data, dataSize); if (mdl == NULL) { OvsFreeMemoryWithTag(data, OVS_MDL_POOL_TAG); } return mdl; } static VOID OvsFreeMDLAndData(PMDL mdl) { PVOID data; data = MmGetMdlVirtualAddress(mdl); NdisFreeMdl(mdl); OvsFreeMemoryWithTag(data, OVS_MDL_POOL_TAG); } /* * -------------------------------------------------------------------------- * OvsAllocateVariableSizeNBL -- * * Allocate variable size NBL, the NBL looks like * NBL + NB + Context * MDL + Data * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsAllocateVariableSizeNBL(PVOID ovsContext, UINT32 size, UINT32 headRoom) { PNET_BUFFER_LIST nbl = NULL; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; POVS_NBL_POOL ovsPool = &context->ovsPool; POVS_BUFFER_CONTEXT ctx; UINT32 realSize; PMDL mdl; NDIS_STATUS status; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO info; if (size == 0) { return NULL; } realSize = MEM_ALIGN_SIZE(size + headRoom); mdl = OvsAllocateMDLAndData(ovsPool->ndisHandle, realSize); if (mdl == NULL) { return NULL; } nbl = NdisAllocateNetBufferAndNetBufferList(ovsPool->zeroSizePool, (UINT16)sizeof (OVS_BUFFER_CONTEXT), (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL, mdl, realSize, 0); if (nbl == NULL) { OvsFreeMDLAndData(mdl); return NULL; } nbl->SourceHandle = ovsPool->ndisHandle; status = context->NdisSwitchHandlers. AllocateNetBufferListForwardingContext(ovsPool->ndisContext, nbl); if (status != NDIS_STATUS_SUCCESS) { /* * do we need to remove mdl from nbl XXX */ OvsFreeMDLAndData(mdl); NdisFreeNetBufferList(nbl); return NULL; } info = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(nbl); ASSERT(info); info->IsPacketDataSafe = TRUE; info->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; status = NdisRetreatNetBufferDataStart(NET_BUFFER_LIST_FIRST_NB(nbl), size, 0, NULL); ASSERT(status == NDIS_STATUS_SUCCESS); #ifdef DBG InterlockedIncrement((LONG volatile *)&ovsPool->zeroNBLCount); OvsDumpNetBufferList(nbl); OvsDumpForwardingDetails(nbl); #endif ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); OvsInitNBLContext(ctx, OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA | OVS_BUFFER_PRIVATE_FORWARD_CONTEXT | OVS_BUFFER_FROM_ZERO_SIZE_POOL, size, OVS_DPPORT_NUMBER_INVALID); OVS_LOG_LOUD("Allocate variable size NBL: %p", nbl); return nbl; } /* * -------------------------------------------------------------------------- * OvsInitExternalNBLContext -- * * For NBL not allocated by OVS, it will allocate and initialize * the NBL context. * -------------------------------------------------------------------------- */ POVS_BUFFER_CONTEXT OvsInitExternalNBLContext(PVOID ovsContext, PNET_BUFFER_LIST nbl, BOOLEAN isRecv) { NDIS_HANDLE poolHandle; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; POVS_BUFFER_CONTEXT ctx; PNET_BUFFER nb; NDIS_STATUS status; UINT16 flags; poolHandle = NdisGetPoolFromNetBufferList(nbl); if (poolHandle == context->ovsPool.ndisHandle || nbl->SourceHandle == context->ovsPool.ndisHandle) { return (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); } status = NdisAllocateNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT), OVS_DEFAULT_NBL_CONTEXT_FILL, OVS_OTHER_POOL_TAG); if (status != NDIS_STATUS_SUCCESS) { return NULL; } #ifdef DBG OvsDumpNBLContext(nbl); InterlockedIncrement((LONG volatile *)&context->ovsPool.sysNBLCount); #endif flags = isRecv ? OVS_BUFFER_RECV_BUFFER : OVS_BUFFER_SEND_BUFFER; flags |= OVS_BUFFER_NEED_COMPLETE | OVS_BUFFER_PRIVATE_CONTEXT; ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); nb = NET_BUFFER_LIST_FIRST_NB(nbl); /* * we use first nb to decide whether we need advance or retreat during * complete. */ OvsInitNBLContext(ctx, flags, NET_BUFFER_DATA_LENGTH(nb), OVS_DPPORT_NUMBER_INVALID); return ctx; } /* * -------------------------------------------------------------------------- * OvsAllocateNBLContext * * Create NBL buffer context and forwarding context. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsAllocateNBLContext(POVS_SWITCH_CONTEXT context, PNET_BUFFER_LIST nbl) { POVS_NBL_POOL ovsPool = &context->ovsPool; NDIS_STATUS status; status = NdisAllocateNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT), OVS_DEFAULT_NBL_CONTEXT_FILL, OVS_OTHER_POOL_TAG); if (status != NDIS_STATUS_SUCCESS) { return NDIS_STATUS_FAILURE; } nbl->SourceHandle = ovsPool->ndisHandle; status = context->NdisSwitchHandlers. AllocateNetBufferListForwardingContext(ovsPool->ndisContext, nbl); if (status != NDIS_STATUS_SUCCESS) { NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT)); return NDIS_STATUS_FAILURE; } return status; } /* * -------------------------------------------------------------------------- * OvsFreeNBLContext * * Free the NBL buffer context and forwarding context. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsFreeNBLContext(POVS_SWITCH_CONTEXT context, PNET_BUFFER_LIST nbl) { POVS_NBL_POOL ovsPool = &context->ovsPool; context->NdisSwitchHandlers. FreeNetBufferListForwardingContext(ovsPool->ndisContext, nbl); NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT)); return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsCopyNBLInfo * * Copy NBL info from src to dst * -------------------------------------------------------------------------- */ NDIS_STATUS OvsCopyNBLInfo(PNET_BUFFER_LIST srcNbl, PNET_BUFFER_LIST dstNbl, POVS_BUFFER_CONTEXT srcCtx, UINT32 copySize, BOOLEAN copyNblInfo) { PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO srcInfo, dstInfo; NDIS_STATUS status = NDIS_STATUS_SUCCESS; srcInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(srcNbl); dstInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(dstNbl); if (srcInfo) { #ifdef OVS_USE_COPY_NET_BUFFER_LIST_INFO status = context->NdisSwitchHandlers. CopyNetBufferListInfo(ovsPool->ndisContext, dstNbl, srcNbl, 0); if (status != NDIS_STATUS_SUCCESS) { return status; } #else dstInfo->SourcePortId = srcInfo->SourcePortId; dstInfo->SourceNicIndex = srcInfo->SourceNicIndex; if (copyNblInfo) { if (srcCtx->flags & OVS_BUFFER_RECV_BUFFER) { NdisCopyReceiveNetBufferListInfo(dstNbl, srcNbl); } else if (srcCtx->flags & OVS_BUFFER_SEND_BUFFER) { NdisCopySendNetBufferListInfo(dstNbl, srcNbl); } } #endif dstInfo->IsPacketDataSafe = srcInfo->IsPacketDataSafe; if (!srcInfo->IsPacketDataSafe && copySize > srcInfo->SafePacketDataSize) { srcInfo->SafePacketDataSize = copySize; } } else { /* * Assume all data are safe */ dstInfo->IsPacketDataSafe = TRUE; dstInfo->SourcePortId = NDIS_SWITCH_DEFAULT_PORT_ID; } return status; } /* * -------------------------------------------------------------------------- * OvsPartialCopyNBL -- * * Partial copy NBL, if there is multiple NB in NBL, each one will be * copied. We also reserve headroom for the new NBL. * * Please note, * NBL should have OVS_BUFFER_CONTEXT setup before calling * this function. * The NBL should already have ref to itself so that during copy * it will not be freed. * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsPartialCopyNBL(PVOID ovsContext, PNET_BUFFER_LIST nbl, UINT32 copySize, UINT32 headRoom, BOOLEAN copyNblInfo) { PNET_BUFFER_LIST newNbl; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; NDIS_STATUS status; PNET_BUFFER srcNb, dstNb; ULONG byteCopied; POVS_NBL_POOL ovsPool = &context->ovsPool; POVS_BUFFER_CONTEXT srcCtx, dstCtx; UINT16 flags; srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) { OVS_LOG_INFO("src nbl must have ctx initialized"); ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC); return NULL; } if (copySize) { NdisAdvanceNetBufferListDataStart(nbl, copySize, FALSE, NULL); } newNbl = NdisAllocateCloneNetBufferList(nbl, ovsPool->nblOnlyPool, NULL, 0); if (copySize) { status = NdisRetreatNetBufferListDataStart(nbl, copySize, 0, NULL, NULL); ASSERT(status == NDIS_STATUS_SUCCESS); } if (newNbl == NULL) { return NULL; } /* * Allocate private memory for copy */ if (copySize + headRoom) { status = NdisRetreatNetBufferListDataStart(newNbl, copySize + headRoom, 0, NULL, NULL); if (status != NDIS_STATUS_SUCCESS) { goto retreat_error; } if (headRoom) { NdisAdvanceNetBufferListDataStart(newNbl, headRoom, FALSE, NULL); } if (copySize) { srcNb = NET_BUFFER_LIST_FIRST_NB(nbl); dstNb = NET_BUFFER_LIST_FIRST_NB(newNbl); while (srcNb) { status = NdisCopyFromNetBufferToNetBuffer(dstNb, 0, copySize, srcNb, 0, &byteCopied); if (status != NDIS_STATUS_SUCCESS || copySize != byteCopied) { goto nbl_context_error; } srcNb = NET_BUFFER_NEXT_NB(srcNb); dstNb = NET_BUFFER_NEXT_NB(dstNb); } } } status = OvsAllocateNBLContext(context, newNbl); if (status != NDIS_STATUS_SUCCESS) { goto nbl_context_error; } status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, copySize, copyNblInfo); if (status != NDIS_STATUS_SUCCESS) { goto copy_list_info_error; } #ifdef DBG InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount); #endif newNbl->ParentNetBufferList = nbl; dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl); ASSERT(dstCtx != NULL); flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER); flags |= OVS_BUFFER_FROM_NBL_ONLY_POOL | OVS_BUFFER_PRIVATE_CONTEXT | OVS_BUFFER_PRIVATE_FORWARD_CONTEXT; srcNb = NET_BUFFER_LIST_FIRST_NB(nbl); OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(srcNb) - copySize, OVS_DPPORT_NUMBER_INVALID); InterlockedIncrement((LONG volatile *)&srcCtx->refCount); #ifdef DBG OvsDumpNetBufferList(nbl); OvsDumpForwardingDetails(nbl); OvsDumpNetBufferList(newNbl); OvsDumpForwardingDetails(newNbl); #endif OVS_LOG_LOUD("Partial Copy new NBL: %p", newNbl); return newNbl; copy_list_info_error: OvsFreeNBLContext(context, newNbl); nbl_context_error: if (copySize) { NdisAdvanceNetBufferListDataStart(newNbl, copySize, TRUE, NULL); } retreat_error: NdisFreeCloneNetBufferList(newNbl, 0); return NULL; } /* * -------------------------------------------------------------------------- * OvsPartialCopyToMultipleNBLs -- * * This is similar to OvsPartialCopyNBL() except that each NB will * have its own NBL. * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsPartialCopyToMultipleNBLs(PVOID ovsContext, PNET_BUFFER_LIST nbl, UINT32 copySize, UINT32 headRoom, BOOLEAN copyNblInfo) { PNET_BUFFER nb, nextNb = NULL, firstNb, prevNb; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; PNET_BUFFER_LIST firstNbl = NULL, newNbl, prevNbl = NULL; nb = NET_BUFFER_LIST_FIRST_NB(nbl); if (NET_BUFFER_NEXT_NB(nb) == NULL) { return OvsPartialCopyNBL(context, nbl, copySize, headRoom, copyNblInfo); } firstNb = nb; prevNb = nb; while (nb) { nextNb = NET_BUFFER_NEXT_NB(nb); NET_BUFFER_NEXT_NB(nb) = NULL; NET_BUFFER_LIST_FIRST_NB(nbl) = nb; newNbl = OvsPartialCopyNBL(context, nbl, copySize, headRoom, copyNblInfo); if (newNbl == NULL) { goto cleanup; } if (prevNbl == NULL) { firstNbl = newNbl; } else { NET_BUFFER_LIST_NEXT_NBL(prevNbl) = newNbl; NET_BUFFER_NEXT_NB(prevNb) = nb; } prevNbl = newNbl; prevNb = nb; nb = nextNb; } NET_BUFFER_LIST_FIRST_NB(nbl) = firstNb; return firstNbl; cleanup: NET_BUFFER_NEXT_NB(prevNb) = nb; NET_BUFFER_NEXT_NB(nb) = nextNb; NET_BUFFER_LIST_FIRST_NB(nbl) = firstNb; newNbl = firstNbl; while (newNbl) { firstNbl = NET_BUFFER_LIST_NEXT_NBL(newNbl); NET_BUFFER_LIST_NEXT_NBL(newNbl) = NULL; OvsCompleteNBL(context, newNbl, TRUE); newNbl = firstNbl; } return NULL; } static PNET_BUFFER_LIST OvsCopySinglePacketNBL(PVOID ovsContext, PNET_BUFFER_LIST nbl, PNET_BUFFER nb, UINT32 headRoom, BOOLEAN copyNblInfo) { UINT32 size; ULONG copiedSize; POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; PNET_BUFFER_LIST newNbl; PNET_BUFFER newNb; NDIS_STATUS status; POVS_BUFFER_CONTEXT srcCtx, dstCtx; size = NET_BUFFER_DATA_LENGTH(nb); if ((size + headRoom) <= OVS_FIX_NBL_DATA_SIZE) { newNbl = OvsAllocateFixSizeNBL(context, size, headRoom); } else { newNbl = OvsAllocateVariableSizeNBL(context, size, headRoom); } if (newNbl == NULL) { return NULL; } newNb = NET_BUFFER_LIST_FIRST_NB(newNbl); status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, size, nb, 0, &copiedSize); srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); if (status == NDIS_STATUS_SUCCESS) { status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, copiedSize, copyNblInfo); } if (status != NDIS_STATUS_SUCCESS || copiedSize != size) { OvsCompleteNBL(context, newNbl, TRUE); return NULL; } dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl); ASSERT(dstCtx && srcCtx); ASSERT(srcCtx->magic == OVS_CTX_MAGIC && dstCtx->magic == OVS_CTX_MAGIC); dstCtx->flags |= srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER); #ifdef DBG OvsDumpNetBufferList(newNbl); OvsDumpForwardingDetails(newNbl); #endif OVS_LOG_LOUD("Copy single nb to new NBL: %p", newNbl); return newNbl; } /* * -------------------------------------------------------------------------- * OvsFullCopyNBL -- * * Copy the NBL to a new NBL including data. * * Notes: * The NBL can have multiple NBs, but the final result is one NBL. * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsFullCopyNBL(PVOID ovsContext, PNET_BUFFER_LIST nbl, UINT32 headRoom, BOOLEAN copyNblInfo) { POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; POVS_NBL_POOL ovsPool = &context->ovsPool; PNET_BUFFER_LIST newNbl; PNET_BUFFER nb, newNb, firstNb = NULL, prevNb = NULL; POVS_BUFFER_CONTEXT dstCtx, srcCtx; PMDL mdl; NDIS_STATUS status; UINT32 size, totalSize; ULONG copiedSize; UINT16 flags; PNDIS_SWITCH_FORWARDING_DETAIL_NET_BUFFER_LIST_INFO dstInfo; srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) { OVS_LOG_INFO("src nbl must have ctx initialized"); ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC); return NULL; } nb = NET_BUFFER_LIST_FIRST_NB(nbl); if (NET_BUFFER_NEXT_NB(nb) == NULL) { return OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo); } newNbl = NdisAllocateNetBufferList(ovsPool->nblOnlyPool, (UINT16)sizeof (OVS_BUFFER_CONTEXT), (UINT16)OVS_DEFAULT_NBL_CONTEXT_FILL); if (newNbl == NULL) { return NULL; } while (nb) { size = NET_BUFFER_DATA_LENGTH(nb); totalSize = MEM_ALIGN_SIZE(size + headRoom); mdl = OvsAllocateMDLAndData(ovsPool->ndisHandle, totalSize); if (mdl == NULL) { goto nblcopy_error; } newNb = NdisAllocateNetBuffer(ovsPool->nbPool, mdl, totalSize, 0); if (newNb == NULL) { OvsFreeMDLAndData(mdl); goto nblcopy_error; } if (firstNb == NULL) { firstNb = newNb; } else { NET_BUFFER_NEXT_NB(prevNb) = newNb; } prevNb = newNb; #ifdef DBG InterlockedIncrement((LONG volatile *)&ovsPool->nbCount); #endif status = NdisRetreatNetBufferDataStart(newNb, size, 0, NULL); ASSERT(status == NDIS_STATUS_SUCCESS); status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, size, nb, 0, &copiedSize); if (status != NDIS_STATUS_SUCCESS || size != copiedSize) { goto nblcopy_error; } nb = NET_BUFFER_NEXT_NB(nb); } NET_BUFFER_LIST_FIRST_NB(newNbl) = firstNb; newNbl->SourceHandle = ovsPool->ndisHandle; status = context->NdisSwitchHandlers. AllocateNetBufferListForwardingContext(ovsPool->ndisContext, newNbl); if (status != NDIS_STATUS_SUCCESS) { goto nblcopy_error; } status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, 0, copyNblInfo); if (status != NDIS_STATUS_SUCCESS) { goto nblcopy_error; } dstInfo = NET_BUFFER_LIST_SWITCH_FORWARDING_DETAIL(newNbl); dstInfo->IsPacketDataSafe = TRUE; dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl); flags = srcCtx->flags & (OVS_BUFFER_RECV_BUFFER | OVS_BUFFER_SEND_BUFFER); flags |= OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA | OVS_BUFFER_PRIVATE_NET_BUFFER | OVS_BUFFER_FROM_NBL_ONLY_POOL | OVS_BUFFER_PRIVATE_FORWARD_CONTEXT; OvsInitNBLContext(dstCtx, flags, NET_BUFFER_DATA_LENGTH(firstNb), OVS_DPPORT_NUMBER_INVALID); #ifdef DBG OvsDumpNetBufferList(nbl); OvsDumpForwardingDetails(nbl); InterlockedIncrement((LONG volatile *)&ovsPool->nblOnlyCount); #endif OVS_LOG_LOUD("newNbl: %p", newNbl); return newNbl; nblcopy_error: while (firstNb) { #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->nbCount); #endif prevNb = firstNb; firstNb = NET_BUFFER_NEXT_NB(prevNb); mdl = NET_BUFFER_FIRST_MDL(prevNb); NET_BUFFER_FIRST_MDL(prevNb) = NULL; NdisFreeNetBuffer(prevNb); OvsFreeMDLAndData(mdl); } NdisFreeNetBufferList(newNbl); OVS_LOG_ERROR("OvsFullCopyNBL failed"); return NULL; } /* * -------------------------------------------------------------------------- * GetSegmentHeaderInfo * * Extract header size and sequence number for the segment. * -------------------------------------------------------------------------- */ static NDIS_STATUS GetSegmentHeaderInfo(PNET_BUFFER_LIST nbl, const POVS_PACKET_HDR_INFO hdrInfo, UINT32 *hdrSize, UINT32 *seqNumber) { TCPHdr tcpStorage; const TCPHdr *tcp; /* Parse the orginal Eth/IP/TCP header */ tcp = OvsGetPacketBytes(nbl, sizeof *tcp, hdrInfo->l4Offset, &tcpStorage); if (tcp == NULL) { return NDIS_STATUS_FAILURE; } *seqNumber = ntohl(tcp->seq); *hdrSize = hdrInfo->l4Offset + TCP_HDR_LEN(tcp); return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * FixSegmentHeader * * Fix IP length, IP checksum, TCP sequence number and TCP checksum * in the segment. * -------------------------------------------------------------------------- */ static NDIS_STATUS FixSegmentHeader(PNET_BUFFER nb, UINT16 segmentSize, UINT32 seqNumber, BOOLEAN lastPacket, UINT16 packetCounter) { EthHdr *dstEth; IPHdr *dstIP; TCPHdr *dstTCP; PMDL mdl; PUINT8 bufferStart; mdl = NET_BUFFER_FIRST_MDL(nb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(mdl, LowPagePriority); if (!bufferStart) { return NDIS_STATUS_RESOURCES; } dstEth = (EthHdr *)(bufferStart + NET_BUFFER_CURRENT_MDL_OFFSET(nb)); ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb) >= sizeof(EthHdr) + sizeof(IPHdr) + sizeof(TCPHdr)); dstIP = (IPHdr *)((PCHAR)dstEth + sizeof *dstEth); dstTCP = (TCPHdr *)((PCHAR)dstIP + dstIP->ihl * 4); ASSERT((INT)MmGetMdlByteCount(mdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb) >= sizeof(EthHdr) + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP)); /* Fix IP length and checksum */ ASSERT(dstIP->protocol == IPPROTO_TCP); dstIP->tot_len = htons(segmentSize + dstIP->ihl * 4 + TCP_HDR_LEN(dstTCP)); dstIP->id += packetCounter; dstIP->check = 0; dstIP->check = IPChecksum((UINT8 *)dstIP, dstIP->ihl * 4, 0); /* Fix TCP checksum */ dstTCP->seq = htonl(seqNumber); /* * Set the TCP FIN and PSH bit only for the last packet * More information can be found under: * https://msdn.microsoft.com/en-us/library/windows/hardware/ff568840%28v=vs.85%29.aspx */ if (dstTCP->fin) { dstTCP->fin = lastPacket; } if (dstTCP->psh) { dstTCP->psh = lastPacket; } UINT16 csumLength = segmentSize + TCP_HDR_LEN(dstTCP); dstTCP->check = IPPseudoChecksum(&dstIP->saddr, &dstIP->daddr, IPPROTO_TCP, csumLength); dstTCP->check = CalculateChecksumNB(nb, csumLength, sizeof *dstEth + dstIP->ihl * 4); return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsTcpSegmentyNBL -- * * Segment TCP payload, and prepend each segment with ether/IP/TCP header. * Leave headRoom for additional encap. * * Please note, * NBL should have OVS_BUFFER_CONTEXT setup before calling * this function. * The NBL should already have ref to itself so that during copy * it will not be freed. * Currently this API assert there is only one NB in an NBL, it needs * to be fixed if we receive multiple NBs in an NBL. * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsTcpSegmentNBL(PVOID ovsContext, PNET_BUFFER_LIST nbl, POVS_PACKET_HDR_INFO hdrInfo, UINT32 mss, UINT32 headRoom) { POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; #ifdef DBG POVS_NBL_POOL ovsPool = &context->ovsPool; #endif POVS_BUFFER_CONTEXT dstCtx, srcCtx; UINT32 size, hdrSize, seqNumber; PNET_BUFFER_LIST newNbl; PNET_BUFFER nb, newNb; NDIS_STATUS status; UINT16 segmentSize; ULONG copiedSize; UINT16 packetCounter = 0; srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) { OVS_LOG_INFO("src nbl must have ctx initialized"); ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC); return NULL; } nb = NET_BUFFER_LIST_FIRST_NB(nbl); ASSERT(NET_BUFFER_NEXT_NB(nb) == NULL); /* Figure out the segment header size */ status = GetSegmentHeaderInfo(nbl, hdrInfo, &hdrSize, &seqNumber); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_INFO("Cannot parse NBL header"); return NULL; } size = NET_BUFFER_DATA_LENGTH(nb) - hdrSize; /* XXX add to ovsPool counters? */ newNbl = NdisAllocateFragmentNetBufferList(nbl, NULL, NULL, hdrSize, mss, hdrSize + headRoom , 0, 0); if (newNbl == NULL) { return NULL; } /* Now deal with TCP payload */ for (newNb = NET_BUFFER_LIST_FIRST_NB(newNbl); newNb != NULL; newNb = NET_BUFFER_NEXT_NB(newNb)) { segmentSize = (size > mss ? mss : size) & 0xffff; if (headRoom) { NdisAdvanceNetBufferDataStart(newNb, headRoom, FALSE, NULL); } /* Now copy the eth/IP/TCP header and fix up */ status = NdisCopyFromNetBufferToNetBuffer(newNb, 0, hdrSize, nb, 0, &copiedSize); if (status != NDIS_STATUS_SUCCESS || hdrSize != copiedSize) { goto nblcopy_error; } status = FixSegmentHeader(newNb, segmentSize, seqNumber, NET_BUFFER_NEXT_NB(newNb) == NULL, packetCounter); if (status != NDIS_STATUS_SUCCESS) { goto nblcopy_error; } /* Move on to the next segment */ size -= segmentSize; seqNumber += segmentSize; packetCounter++; } status = OvsAllocateNBLContext(context, newNbl); if (status != NDIS_STATUS_SUCCESS) { goto nblcopy_error; } status = OvsCopyNBLInfo(nbl, newNbl, srcCtx, hdrSize + headRoom, FALSE); if (status != NDIS_STATUS_SUCCESS) { goto nbl_context_error; } newNbl->ParentNetBufferList = nbl; /* Remember it's a fragment NBL so we can free it properly */ dstCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(newNbl); ASSERT(dstCtx != NULL); dstCtx->flags = OVS_BUFFER_FRAGMENT | OVS_BUFFER_PRIVATE_CONTEXT | OVS_BUFFER_PRIVATE_FORWARD_CONTEXT | OVS_BUFFER_SEND_BUFFER; dstCtx->refCount = 1; dstCtx->magic = OVS_CTX_MAGIC; dstCtx->dataOffsetDelta = hdrSize + headRoom; InterlockedIncrement((LONG volatile *)&srcCtx->refCount); #ifdef DBG InterlockedIncrement((LONG volatile *)&ovsPool->fragNBLCount); OvsDumpNetBufferList(nbl); OvsDumpForwardingDetails(nbl); OvsDumpNetBufferList(newNbl); OvsDumpForwardingDetails(newNbl); #endif OVS_LOG_TRACE("Segment nbl %p to newNbl: %p", nbl, newNbl); return newNbl; nbl_context_error: OvsFreeNBLContext(context, newNbl); nblcopy_error: #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount); #endif NdisFreeFragmentNetBufferList(newNbl, hdrSize + headRoom, 0); return NULL; } /* * -------------------------------------------------------------------------- * OvsAllocateNBLFromBuffer -- * * This function allocates all the stuff necessary for creating an NBL from the * input buffer of specified length, namely, a nonpaged data buffer of size * length, an MDL from it, and a NB and NBL from it. It does not allocate an NBL * context yet. It also copies data from the specified buffer to the NBL. * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsAllocateNBLFromBuffer(PVOID context, PVOID buffer, ULONG length) { POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)context; UINT8 *data = NULL; PNET_BUFFER_LIST nbl = NULL; PNET_BUFFER nb; PMDL mdl; if (length > OVS_DEFAULT_DATA_SIZE) { nbl = OvsAllocateVariableSizeNBL(switchContext, length, OVS_DEFAULT_HEADROOM_SIZE); } else { nbl = OvsAllocateFixSizeNBL(switchContext, length, OVS_DEFAULT_HEADROOM_SIZE); } if (nbl == NULL) { return NULL; } nb = NET_BUFFER_LIST_FIRST_NB(nbl); mdl = NET_BUFFER_CURRENT_MDL(nb); data = (PUINT8)MmGetSystemAddressForMdlSafe(mdl, LowPagePriority) + NET_BUFFER_CURRENT_MDL_OFFSET(nb); if (!data) { OvsCompleteNBL(switchContext, nbl, TRUE); return NULL; } NdisMoveMemory(data, buffer, length); return nbl; } /* * -------------------------------------------------------------------------- * OvsFullCopyToMultipleNBLs -- * * Copy NBL to multiple NBLs, each NB will have its own NBL * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsFullCopyToMultipleNBLs(PVOID ovsContext, PNET_BUFFER_LIST nbl, UINT32 headRoom, BOOLEAN copyNblInfo) { POVS_SWITCH_CONTEXT context = (POVS_SWITCH_CONTEXT)ovsContext; PNET_BUFFER_LIST firstNbl, currNbl, newNbl; PNET_BUFFER nb; POVS_BUFFER_CONTEXT srcCtx; srcCtx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); if (srcCtx == NULL || srcCtx->magic != OVS_CTX_MAGIC) { OVS_LOG_INFO("src nbl must have ctx initialized"); ASSERT(srcCtx && srcCtx->magic == OVS_CTX_MAGIC); return NULL; } nb = NET_BUFFER_LIST_FIRST_NB(nbl); newNbl = OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo); if (newNbl == NULL || NET_BUFFER_NEXT_NB(nb) == NULL) { return newNbl; } else { firstNbl = newNbl; currNbl = newNbl; } while (nb) { newNbl = OvsCopySinglePacketNBL(context, nbl, nb, headRoom, copyNblInfo); if (newNbl == NULL) { goto copymultiple_error; } NET_BUFFER_LIST_NEXT_NBL(currNbl) = newNbl; currNbl = newNbl; nb = NET_BUFFER_NEXT_NB(nb); } return firstNbl; copymultiple_error: while (firstNbl) { currNbl = firstNbl; firstNbl = NET_BUFFER_LIST_NEXT_NBL(firstNbl); NET_BUFFER_LIST_NEXT_NBL(currNbl) = NULL; OvsCompleteNBL(context, currNbl, TRUE); } return NULL; } /* * -------------------------------------------------------------------------- * OvsCompleteNBL -- * * This function tries to free the NBL allocated by OVS buffer * management module. If it trigger the completion of the parent * NBL, it will recursively call itself. If it trigger the completion * of external NBL, it will be returned to the caller. The caller * is responsible to call API to return to upper layer. * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsCompleteNBL(POVS_SWITCH_CONTEXT context, PNET_BUFFER_LIST nbl, BOOLEAN updateRef) { POVS_BUFFER_CONTEXT ctx; UINT16 flags; PNET_BUFFER_LIST parent; NDIS_STATUS status; NDIS_HANDLE poolHandle; LONG value; POVS_NBL_POOL ovsPool = &context->ovsPool; PNET_BUFFER nb; ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC); OVS_LOG_TRACE("Enter: nbl: %p, ctx: %p, refCount: %d, updateRef:%d", nbl, ctx, ctx->refCount, updateRef); if (updateRef) { value = InterlockedDecrement((LONG volatile *)&ctx->refCount); if (value != 0) { return NULL; } } else { /* * This is a special case, the refCount must be zero */ ASSERT(ctx->refCount == 0); } nb = NET_BUFFER_LIST_FIRST_NB(nbl); flags = ctx->flags; if (!(flags & OVS_BUFFER_FRAGMENT) && NET_BUFFER_DATA_LENGTH(nb) != ctx->origDataLength) { UINT32 diff; if (NET_BUFFER_DATA_LENGTH(nb) < ctx->origDataLength) { diff = ctx->origDataLength -NET_BUFFER_DATA_LENGTH(nb); status = NdisRetreatNetBufferListDataStart(nbl, diff, 0, NULL, NULL); ASSERT(status == NDIS_STATUS_SUCCESS); } else { diff = NET_BUFFER_DATA_LENGTH(nb) - ctx->origDataLength; NdisAdvanceNetBufferListDataStart(nbl, diff, TRUE, NULL); } } if (ctx->flags & OVS_BUFFER_PRIVATE_CONTEXT) { NdisFreeNetBufferListContext(nbl, sizeof (OVS_BUFFER_CONTEXT)); } if (flags & OVS_BUFFER_NEED_COMPLETE) { /* * return to caller for completion */ #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->sysNBLCount); #endif return nbl; } if (flags & OVS_BUFFER_PRIVATE_FORWARD_CONTEXT) { context->NdisSwitchHandlers. FreeNetBufferListForwardingContext(ovsPool->ndisContext, nbl); } if (flags & (OVS_BUFFER_PRIVATE_MDL | OVS_BUFFER_PRIVATE_DATA)) { PNET_BUFFER nb = NET_BUFFER_LIST_FIRST_NB(nbl); while (nb) { PMDL mdl = NET_BUFFER_FIRST_MDL(nb); NET_BUFFER_FIRST_MDL(nb) = NULL; ASSERT(mdl->Next == NULL); OvsFreeMDLAndData(mdl); nb = NET_BUFFER_NEXT_NB(nb); } } if (flags & OVS_BUFFER_PRIVATE_NET_BUFFER) { PNET_BUFFER nb, nextNb; nb = NET_BUFFER_LIST_FIRST_NB(nbl); while (nb) { nextNb = NET_BUFFER_NEXT_NB(nb); NdisFreeNetBuffer(nb); #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->nbCount); #endif nb = nextNb; } NET_BUFFER_LIST_FIRST_NB(nbl) = NULL; } parent = nbl->ParentNetBufferList; poolHandle = NdisGetPoolFromNetBufferList(nbl); if (flags & OVS_BUFFER_FROM_FIX_SIZE_POOL) { ASSERT(poolHandle == ovsPool->fixSizePool); #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->fixNBLCount); #endif NdisFreeNetBufferList(nbl); } else if (flags & OVS_BUFFER_FROM_ZERO_SIZE_POOL) { ASSERT(poolHandle == ovsPool->zeroSizePool); #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->zeroNBLCount); #endif NdisFreeNetBufferList(nbl); } else if (flags & OVS_BUFFER_FROM_NBL_ONLY_POOL) { ASSERT(poolHandle == ovsPool->nblOnlyPool); #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->nblOnlyCount); #endif NdisFreeCloneNetBufferList(nbl, 0); } else if (flags & OVS_BUFFER_FRAGMENT) { OVS_LOG_TRACE("Free fragment %p parent %p", nbl, parent); #ifdef DBG InterlockedDecrement((LONG volatile *)&ovsPool->fragNBLCount); #endif NdisFreeFragmentNetBufferList(nbl, ctx->dataOffsetDelta, 0); } if (parent != NULL) { ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(parent); ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC); value = InterlockedDecrement((LONG volatile *)&ctx->refCount); if (value == 0) { return OvsCompleteNBL(context, parent, FALSE); } } return NULL; } /* * -------------------------------------------------------------------------- * OvsSetCtxSourcePortNo -- * Setter function which stores the source port of an NBL in the NBL * Context Info. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsSetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 portNo) { POVS_BUFFER_CONTEXT ctx; ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); if (ctx == NULL) { ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC); return STATUS_INVALID_PARAMETER; } ctx->srcPortNo = portNo; return NDIS_STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsGetCtxSourcePortNo -- * Get source port of an NBL from its Context Info. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsGetCtxSourcePortNo(PNET_BUFFER_LIST nbl, UINT32 *portNo) { POVS_BUFFER_CONTEXT ctx; ctx = (POVS_BUFFER_CONTEXT)NET_BUFFER_LIST_CONTEXT_DATA_START(nbl); if (ctx == NULL || portNo == NULL) { ASSERT(ctx && ctx->magic == OVS_CTX_MAGIC); return STATUS_INVALID_PARAMETER; } *portNo = ctx->srcPortNo; return NDIS_STATUS_SUCCESS; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Switch.c0000644000000000000000000000013212664352753022061 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594660.213289661 openvswitch-2.5.0/datapath-windows/ovsext/Switch.c0000664000175000017500000005160212664352753023555 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * This file contains the implementation of the management functionality of the * OVS. */ #include "precomp.h" #include "Switch.h" #include "Vport.h" #include "Event.h" #include "Flow.h" #include "IpHelper.h" #include "Oid.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_SWITCH #include "Debug.h" POVS_SWITCH_CONTEXT gOvsSwitchContext; LONG volatile gOvsInAttach; UINT64 ovsTimeIncrementPerTick; extern NDIS_HANDLE gOvsExtDriverHandle; extern NDIS_HANDLE gOvsExtDriverObject; extern PDEVICE_OBJECT gOvsDeviceObject; /* * Reference count used to prevent premature deallocation of the global switch * context structure, gOvsSwitchContext. */ volatile LONG gOvsSwitchContextRefCount = 0; static NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle, POVS_SWITCH_CONTEXT *switchContextOut); static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext); static VOID OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext); static VOID OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext); static NDIS_STATUS OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext); /* * -------------------------------------------------------------------------- * Implements filter driver's FilterAttach function. * * This function allocates the switch context, and initializes its necessary * members. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsExtAttach(NDIS_HANDLE ndisFilterHandle, NDIS_HANDLE filterDriverContext, PNDIS_FILTER_ATTACH_PARAMETERS attachParameters) { NDIS_STATUS status = NDIS_STATUS_FAILURE; NDIS_FILTER_ATTRIBUTES ovsExtAttributes; POVS_SWITCH_CONTEXT switchContext = NULL; UNREFERENCED_PARAMETER(filterDriverContext); OVS_LOG_TRACE("Enter: ndisFilterHandle %p", ndisFilterHandle); ASSERT(filterDriverContext == (NDIS_HANDLE)gOvsExtDriverObject); if (attachParameters->MiniportMediaType != NdisMedium802_3) { status = NDIS_STATUS_INVALID_PARAMETER; goto cleanup; } if (gOvsExtDriverHandle == NULL) { OVS_LOG_TRACE("Exit: OVSEXT driver is not loaded."); ASSERT(FALSE); goto cleanup; } if (gOvsSwitchContext) { OVS_LOG_TRACE("Exit: Failed to create OVS Switch, only one datapath is" "supported, %p.", gOvsSwitchContext); goto cleanup; } if (InterlockedCompareExchange(&gOvsInAttach, 1, 0)) { /* Just fail the request. */ OVS_LOG_TRACE("Exit: Failed to create OVS Switch, since another attach" "instance is in attach process."); goto cleanup; } status = OvsInitIpHelper(ndisFilterHandle); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Exit: Failed to initialize IP helper."); goto cleanup; } status = OvsCreateSwitch(ndisFilterHandle, &switchContext); if (status != NDIS_STATUS_SUCCESS) { OvsCleanupIpHelper(); goto cleanup; } ASSERT(switchContext); /* * Register the switch context with NDIS so NDIS can pass it back to the * FilterXXX callback functions as the 'FilterModuleContext' parameter. */ RtlZeroMemory(&ovsExtAttributes, sizeof(NDIS_FILTER_ATTRIBUTES)); ovsExtAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1; ovsExtAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES); ovsExtAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES; ovsExtAttributes.Flags = 0; NDIS_DECLARE_FILTER_MODULE_CONTEXT(OVS_SWITCH_CONTEXT); status = NdisFSetAttributes(ndisFilterHandle, switchContext, &ovsExtAttributes); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_ERROR("Failed to set attributes."); OvsCleanupIpHelper(); goto cleanup; } /* Setup the state machine. */ switchContext->controlFlowState = OvsSwitchAttached; switchContext->dataFlowState = OvsSwitchPaused; gOvsSwitchContextRefCount = 1; gOvsSwitchContext = switchContext; KeMemoryBarrier(); cleanup: gOvsInAttach = FALSE; if (status != NDIS_STATUS_SUCCESS) { if (switchContext != NULL) { OvsDeleteSwitch(switchContext); } } OVS_LOG_TRACE("Exit: status %x", status); return status; } /* * -------------------------------------------------------------------------- * This function allocated the switch context, and initializes its necessary * members. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsCreateSwitch(NDIS_HANDLE ndisFilterHandle, POVS_SWITCH_CONTEXT *switchContextOut) { NDIS_STATUS status; POVS_SWITCH_CONTEXT switchContext; NDIS_SWITCH_CONTEXT hostSwitchContext; NDIS_SWITCH_OPTIONAL_HANDLERS hostSwitchHandler; OVS_LOG_TRACE("Enter: Create switch object"); switchContext = (POVS_SWITCH_CONTEXT) OvsAllocateMemoryWithTag( sizeof(OVS_SWITCH_CONTEXT), OVS_SWITCH_POOL_TAG); if (switchContext == NULL) { status = NDIS_STATUS_RESOURCES; goto create_switch_done; } RtlZeroMemory(switchContext, sizeof(OVS_SWITCH_CONTEXT)); /* Initialize the switch. */ hostSwitchHandler.Header.Type = NDIS_OBJECT_TYPE_SWITCH_OPTIONAL_HANDLERS; hostSwitchHandler.Header.Size = NDIS_SIZEOF_SWITCH_OPTIONAL_HANDLERS_REVISION_1; hostSwitchHandler.Header.Revision = NDIS_SWITCH_OPTIONAL_HANDLERS_REVISION_1; status = NdisFGetOptionalSwitchHandlers(ndisFilterHandle, &hostSwitchContext, &hostSwitchHandler); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_ERROR("OvsExtAttach: Extension is running in " "non-switch environment."); OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG); goto create_switch_done; } switchContext->NdisFilterHandle = ndisFilterHandle; switchContext->NdisSwitchContext = hostSwitchContext; RtlCopyMemory(&switchContext->NdisSwitchHandlers, &hostSwitchHandler, sizeof(NDIS_SWITCH_OPTIONAL_HANDLERS)); status = OvsInitSwitchContext(switchContext); if (status != NDIS_STATUS_SUCCESS) { OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG); switchContext = NULL; goto create_switch_done; } status = OvsInitTunnelFilter(gOvsExtDriverObject, gOvsDeviceObject); if (status != NDIS_STATUS_SUCCESS) { OvsUninitSwitchContext(switchContext); goto create_switch_done; } status = OvsInitSttDefragmentation(); if (status != STATUS_SUCCESS) { OVS_LOG_ERROR("Exit: Failed to initialize Stt Defragmentation"); goto create_switch_done; } *switchContextOut = switchContext; create_switch_done: OVS_LOG_TRACE("Exit: switchContext: %p status: %#lx", switchContext, status); return status; } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterDetach function. * -------------------------------------------------------------------------- */ _Use_decl_annotations_ VOID OvsExtDetach(NDIS_HANDLE filterModuleContext) { POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext; OVS_LOG_TRACE("Enter: filterModuleContext %p", filterModuleContext); ASSERT(switchContext->dataFlowState == OvsSwitchPaused); switchContext->controlFlowState = OvsSwitchDetached; KeMemoryBarrier(); while(switchContext->pendingOidCount > 0) { NdisMSleep(1000); } OvsDeleteSwitch(switchContext); OvsCleanupIpHelper(); OvsCleanupSttDefragmentation(); /* This completes the cleanup, and a new attach can be handled now. */ OVS_LOG_TRACE("Exit: OvsDetach Successfully"); } /* * -------------------------------------------------------------------------- * This function deletes the switch by freeing all memory previously allocated. * XXX need synchronization with other path. * -------------------------------------------------------------------------- */ VOID OvsDeleteSwitch(POVS_SWITCH_CONTEXT switchContext) { UINT32 dpNo = (UINT32) -1; OVS_LOG_TRACE("Enter: switchContext:%p", switchContext); if (switchContext) { dpNo = switchContext->dpNo; OvsClearAllSwitchVports(switchContext); OvsUninitTunnelFilter(gOvsExtDriverObject); OvsUninitSwitchContext(switchContext); } OVS_LOG_TRACE("Exit: deleted switch %p dpNo: %d", switchContext, dpNo); } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterRestart function. * -------------------------------------------------------------------------- */ _Use_decl_annotations_ NDIS_STATUS OvsExtRestart(NDIS_HANDLE filterModuleContext, PNDIS_FILTER_RESTART_PARAMETERS filterRestartParameters) { POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext; NDIS_STATUS status = NDIS_STATUS_SUCCESS; BOOLEAN switchActive; UNREFERENCED_PARAMETER(filterRestartParameters); OVS_LOG_TRACE("Enter: filterModuleContext %p", filterModuleContext); /* Activate the switch if this is the first restart. */ if (!switchContext->isActivated && !switchContext->isActivateFailed) { status = OvsQuerySwitchActivationComplete(switchContext, &switchActive); if (status != NDIS_STATUS_SUCCESS) { switchContext->isActivateFailed = TRUE; status = NDIS_STATUS_RESOURCES; goto cleanup; } if (switchActive) { status = OvsActivateSwitch(switchContext); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_WARN("Failed to activate switch, dpNo:%d", switchContext->dpNo); status = NDIS_STATUS_RESOURCES; goto cleanup; } } } ASSERT(switchContext->dataFlowState == OvsSwitchPaused); switchContext->dataFlowState = OvsSwitchRunning; cleanup: OVS_LOG_TRACE("Exit: Restart switch:%p, dpNo: %d, status: %#x", switchContext, switchContext->dpNo, status); return status; } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterPause function * -------------------------------------------------------------------------- */ NDIS_STATUS OvsExtPause(NDIS_HANDLE filterModuleContext, PNDIS_FILTER_PAUSE_PARAMETERS pauseParameters) { POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext; UNREFERENCED_PARAMETER(pauseParameters); OVS_LOG_TRACE("Enter: filterModuleContext %p", filterModuleContext); ASSERT(switchContext->dataFlowState == OvsSwitchRunning); switchContext->dataFlowState = OvsSwitchPaused; KeMemoryBarrier(); while(switchContext->pendingOidCount > 0) { NdisMSleep(1000); } OVS_LOG_TRACE("Exit: OvsDetach Successfully"); return NDIS_STATUS_SUCCESS; } static NDIS_STATUS OvsInitSwitchContext(POVS_SWITCH_CONTEXT switchContext) { int i; NTSTATUS status; OVS_LOG_TRACE("Enter: switchContext: %p", switchContext); switchContext->dispatchLock = NdisAllocateRWLock(switchContext->NdisFilterHandle); switchContext->portNoHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG); switchContext->ovsPortNameHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG); switchContext->portIdHashArray= (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG); switchContext->pidHashArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_MAX_PID_ARRAY_SIZE, OVS_SWITCH_POOL_TAG); switchContext->tunnelVportsArray = (PLIST_ENTRY)OvsAllocateMemoryWithTag( sizeof(LIST_ENTRY) * OVS_MAX_VPORT_ARRAY_SIZE, OVS_SWITCH_POOL_TAG); status = OvsAllocateFlowTable(&switchContext->datapath, switchContext); if (status == NDIS_STATUS_SUCCESS) { status = OvsInitBufferPool(switchContext); } if (status != NDIS_STATUS_SUCCESS || switchContext->dispatchLock == NULL || switchContext->portNoHashArray == NULL || switchContext->ovsPortNameHashArray == NULL || switchContext->portIdHashArray== NULL || switchContext->pidHashArray == NULL || switchContext->tunnelVportsArray == NULL) { if (switchContext->dispatchLock) { NdisFreeRWLock(switchContext->dispatchLock); } if (switchContext->portNoHashArray) { OvsFreeMemoryWithTag(switchContext->portNoHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->ovsPortNameHashArray) { OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->portIdHashArray) { OvsFreeMemoryWithTag(switchContext->portIdHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->pidHashArray) { OvsFreeMemoryWithTag(switchContext->pidHashArray, OVS_SWITCH_POOL_TAG); } if (switchContext->tunnelVportsArray) { OvsFreeMemory(switchContext->tunnelVportsArray); } OvsDeleteFlowTable(&switchContext->datapath); OvsCleanupBufferPool(switchContext); OVS_LOG_TRACE("Exit: Failed to init switchContext"); return NDIS_STATUS_RESOURCES; } for (i = 0; i < OVS_MAX_VPORT_ARRAY_SIZE; i++) { InitializeListHead(&switchContext->ovsPortNameHashArray[i]); InitializeListHead(&switchContext->portIdHashArray[i]); InitializeListHead(&switchContext->portNoHashArray[i]); InitializeListHead(&switchContext->tunnelVportsArray[i]); } for (i = 0; i < OVS_MAX_PID_ARRAY_SIZE; i++) { InitializeListHead(&switchContext->pidHashArray[i]); } NdisAllocateSpinLock(&(switchContext->pidHashLock)); switchContext->isActivated = FALSE; switchContext->isActivateFailed = FALSE; switchContext->dpNo = OVS_DP_NUMBER; ovsTimeIncrementPerTick = KeQueryTimeIncrement() / 10000; OVS_LOG_TRACE("Exit: Succesfully initialized switchContext: %p", switchContext); return NDIS_STATUS_SUCCESS; } static VOID OvsUninitSwitchContext(POVS_SWITCH_CONTEXT switchContext) { OvsReleaseSwitchContext(switchContext); } /* * -------------------------------------------------------------------------- * Frees up the contents of and also the switch context. * -------------------------------------------------------------------------- */ static VOID OvsDeleteSwitchContext(POVS_SWITCH_CONTEXT switchContext) { OVS_LOG_TRACE("Enter: Delete switchContext:%p", switchContext); /* We need to do cleanup for tunnel port here. */ ASSERT(switchContext->numHvVports == 0); ASSERT(switchContext->numNonHvVports == 0); NdisFreeRWLock(switchContext->dispatchLock); switchContext->dispatchLock = NULL; NdisFreeSpinLock(&(switchContext->pidHashLock)); OvsFreeMemoryWithTag(switchContext->ovsPortNameHashArray, OVS_SWITCH_POOL_TAG); switchContext->ovsPortNameHashArray = NULL; OvsFreeMemoryWithTag(switchContext->portIdHashArray, OVS_SWITCH_POOL_TAG); switchContext->portIdHashArray = NULL; OvsFreeMemoryWithTag(switchContext->portNoHashArray, OVS_SWITCH_POOL_TAG); switchContext->portNoHashArray = NULL; OvsFreeMemoryWithTag(switchContext->pidHashArray, OVS_SWITCH_POOL_TAG); switchContext->pidHashArray = NULL; OvsFreeMemory(switchContext->tunnelVportsArray); switchContext->tunnelVportsArray = NULL; OvsDeleteFlowTable(&switchContext->datapath); OvsCleanupBufferPool(switchContext); OvsFreeMemoryWithTag(switchContext, OVS_SWITCH_POOL_TAG); OVS_LOG_TRACE("Exit: Delete switchContext: %p", switchContext); } VOID OvsReleaseSwitchContext(POVS_SWITCH_CONTEXT switchContext) { LONG ref = 0; LONG newRef = 0; LONG icxRef = 0; do { ref = gOvsSwitchContextRefCount; newRef = (0 == ref) ? 0 : ref - 1; icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount, newRef, ref); } while (icxRef != ref); if (ref == 1) { OvsDeleteSwitchContext(switchContext); gOvsSwitchContext = NULL; } } BOOLEAN OvsAcquireSwitchContext(VOID) { LONG ref = 0; LONG newRef = 0; LONG icxRef = 0; BOOLEAN ret = FALSE; do { ref = gOvsSwitchContextRefCount; newRef = (0 == ref) ? 0 : ref + 1; icxRef = InterlockedCompareExchange(&gOvsSwitchContextRefCount, newRef, ref); } while (icxRef != ref); if (ref != 0) { ret = TRUE; } return ret; } /* * -------------------------------------------------------------------------- * This function activates the switch by initializing it with all the runtime * state. First it queries all of the MAC addresses set as custom switch policy * to allow sends from, and adds tme to the property list. Then it queries the * NIC list and verifies it can support all of the NICs currently connected to * the switch, and adds the NICs to the NIC list. * -------------------------------------------------------------------------- */ static NDIS_STATUS OvsActivateSwitch(POVS_SWITCH_CONTEXT switchContext) { NDIS_STATUS status; ASSERT(!switchContext->isActivated); OVS_LOG_TRACE("Enter: activate switch %p, dpNo: %ld", switchContext, switchContext->dpNo); switchContext->isActivated = TRUE; status = OvsAddConfiguredSwitchPorts(switchContext); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_WARN("Failed to add configured switch ports"); goto cleanup; } status = OvsInitConfiguredSwitchNics(switchContext); if (status != NDIS_STATUS_SUCCESS) { OVS_LOG_WARN("Failed to add configured vports"); OvsClearAllSwitchVports(switchContext); goto cleanup; } cleanup: if (status != NDIS_STATUS_SUCCESS) { switchContext->isActivated = TRUE; } OVS_LOG_TRACE("Exit: activate switch:%p, isActivated: %s, status = %lx", switchContext, (switchContext->isActivated ? "TRUE" : "FALSE"), status); return status; } /* * -------------------------------------------------------------------------- * Implements filter driver's FilterNetPnPEvent function. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsExtNetPnPEvent(NDIS_HANDLE filterModuleContext, PNET_PNP_EVENT_NOTIFICATION netPnPEvent) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; POVS_SWITCH_CONTEXT switchContext = (POVS_SWITCH_CONTEXT)filterModuleContext; BOOLEAN switchActive; OVS_LOG_TRACE("Enter: filterModuleContext: %p, NetEvent: %d", filterModuleContext, (netPnPEvent->NetPnPEvent).NetEvent); /* * The only interesting event is the NetEventSwitchActivate. It provides * an asynchronous notification of the switch completing activation. */ if (netPnPEvent->NetPnPEvent.NetEvent == NetEventSwitchActivate) { status = OvsQuerySwitchActivationComplete(switchContext, &switchActive); if (status != NDIS_STATUS_SUCCESS) { switchContext->isActivateFailed = TRUE; } else { ASSERT(switchContext->isActivated == FALSE); if (switchContext->isActivated == FALSE && switchActive == TRUE) { status = OvsActivateSwitch(switchContext); OVS_LOG_TRACE("OvsExtNetPnPEvent: activated switch: %p " "status: %s", switchContext, status ? "TRUE" : "FALSE"); } } } if (status == NDIS_STATUS_SUCCESS) { status = NdisFNetPnPEvent(switchContext->NdisFilterHandle, netPnPEvent); } OVS_LOG_TRACE("Exit: OvsExtNetPnPEvent"); return status; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Oid.h0000644000000000000000000000013212631676262021336 xustar0030 mtime=1449622706.966439188 30 atime=1456592667.311090405 30 ctime=1456594660.205289325 openvswitch-2.5.0/datapath-windows/ovsext/Oid.h0000664000175000017500000000227612631676262023035 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __OID_H_ #define __OID_H_ 1 NDIS_STATUS OvsQuerySwitchActivationComplete(POVS_SWITCH_CONTEXT switchContext, BOOLEAN *switchActive); NDIS_STATUS OvsGetPortsOnSwitch(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_PORT_ARRAY *portArrayOut); NDIS_STATUS OvsGetNicsOnSwitch(POVS_SWITCH_CONTEXT switchContext, PNDIS_SWITCH_NIC_ARRAY *nicArrayOut); VOID OvsFreeSwitchPortsArray(PNDIS_SWITCH_PORT_ARRAY portsArray); VOID OvsFreeSwitchNicsArray(PNDIS_SWITCH_NIC_ARRAY nicsArray); #endif /* __OID_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Datapath.c0000644000000000000000000000013112652645507022344 xustar0030 mtime=1454066503.398754587 29 atime=1456592667.30709024 30 ctime=1456594660.173287978 openvswitch-2.5.0/datapath-windows/ovsext/Datapath.c0000664000175000017500000014605012652645507024043 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * XXX: OVS_USE_NL_INTERFACE is being used to keep the legacy DPIF interface * alive while we transition over to the netlink based interface. * OVS_USE_NL_INTERFACE = 0 => legacy inteface to use with dpif-windows.c * OVS_USE_NL_INTERFACE = 1 => netlink inteface to use with ported dpif-linux.c */ #include "precomp.h" #include "Switch.h" #include "User.h" #include "Datapath.h" #include "Jhash.h" #include "Vport.h" #include "Event.h" #include "User.h" #include "PacketIO.h" #include "NetProto.h" #include "Flow.h" #include "User.h" #include "Vxlan.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_DATAPATH #include "Debug.h" #define NETLINK_FAMILY_NAME_LEN 48 /* * Netlink messages are grouped by family (aka type), and each family supports * a set of commands, and can be passed both from kernel -> userspace or * vice-versa. To call into the kernel, userspace uses a device operation which * is outside of a netlink message. * * Each command results in the invocation of a handler function to implement the * request functionality. * * Expectedly, only certain combinations of (device operation, netlink family, * command) are valid. * * Here, we implement the basic infrastructure to perform validation on the * incoming message, version checking, and also to invoke the corresponding * handler to do the heavy-lifting. */ /* * Handler for a given netlink command. Not all the parameters are used by all * the handlers. */ typedef NTSTATUS(NetlinkCmdHandler)(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); typedef struct _NETLINK_CMD { UINT16 cmd; NetlinkCmdHandler *handler; UINT32 supportedDevOp; /* Supported device operations. */ BOOLEAN validateDpIndex; /* Does command require a valid DP argument. */ } NETLINK_CMD, *PNETLINK_CMD; /* A netlink family is a group of commands. */ typedef struct _NETLINK_FAMILY { CHAR *name; UINT16 id; UINT8 version; UINT8 pad1; UINT16 maxAttr; UINT16 pad2; NETLINK_CMD *cmds; /* Array of netlink commands and handlers. */ UINT16 opsCount; } NETLINK_FAMILY, *PNETLINK_FAMILY; /* Handlers for the various netlink commands. */ static NetlinkCmdHandler OvsPendEventCmdHandler, OvsSubscribeEventCmdHandler, OvsReadEventCmdHandler, OvsNewDpCmdHandler, OvsGetDpCmdHandler, OvsSetDpCmdHandler; NetlinkCmdHandler OvsGetNetdevCmdHandler, OvsGetVportCmdHandler, OvsSetVportCmdHandler, OvsNewVportCmdHandler, OvsDeleteVportCmdHandler, OvsPendPacketCmdHandler, OvsSubscribePacketCmdHandler, OvsReadPacketCmdHandler; static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); static NTSTATUS HandleGetDpDump(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); static NTSTATUS HandleDpTransactionCommon( POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); static NTSTATUS OvsGetPidHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); /* * The various netlink families, along with the supported commands. Most of * these families and commands are part of the openvswitch specification for a * netlink datapath. In addition, each platform can implement a few families * and commands as extensions. */ /* Netlink control family: this is a Windows specific family. */ NETLINK_CMD nlControlFamilyCmdOps[] = { { .cmd = OVS_CTRL_CMD_WIN_PEND_REQ, .handler = OvsPendEventCmdHandler, .supportedDevOp = OVS_WRITE_DEV_OP, .validateDpIndex = TRUE, }, { .cmd = OVS_CTRL_CMD_WIN_PEND_PACKET_REQ, .handler = OvsPendPacketCmdHandler, .supportedDevOp = OVS_WRITE_DEV_OP, .validateDpIndex = TRUE, }, { .cmd = OVS_CTRL_CMD_MC_SUBSCRIBE_REQ, .handler = OvsSubscribeEventCmdHandler, .supportedDevOp = OVS_WRITE_DEV_OP, .validateDpIndex = TRUE, }, { .cmd = OVS_CTRL_CMD_PACKET_SUBSCRIBE_REQ, .handler = OvsSubscribePacketCmdHandler, .supportedDevOp = OVS_WRITE_DEV_OP, .validateDpIndex = TRUE, }, { .cmd = OVS_CTRL_CMD_EVENT_NOTIFY, .handler = OvsReadEventCmdHandler, .supportedDevOp = OVS_READ_DEV_OP, .validateDpIndex = FALSE, }, { .cmd = OVS_CTRL_CMD_READ_NOTIFY, .handler = OvsReadPacketCmdHandler, .supportedDevOp = OVS_READ_DEV_OP, .validateDpIndex = FALSE, } }; NETLINK_FAMILY nlControlFamilyOps = { .name = OVS_WIN_CONTROL_FAMILY, .id = OVS_WIN_NL_CTRL_FAMILY_ID, .version = OVS_WIN_CONTROL_VERSION, .maxAttr = OVS_WIN_CONTROL_ATTR_MAX, .cmds = nlControlFamilyCmdOps, .opsCount = ARRAY_SIZE(nlControlFamilyCmdOps) }; /* Netlink datapath family. */ NETLINK_CMD nlDatapathFamilyCmdOps[] = { { .cmd = OVS_DP_CMD_NEW, .handler = OvsNewDpCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = FALSE }, { .cmd = OVS_DP_CMD_GET, .handler = OvsGetDpCmdHandler, .supportedDevOp = OVS_WRITE_DEV_OP | OVS_READ_DEV_OP | OVS_TRANSACTION_DEV_OP, .validateDpIndex = FALSE }, { .cmd = OVS_DP_CMD_SET, .handler = OvsSetDpCmdHandler, .supportedDevOp = OVS_WRITE_DEV_OP | OVS_READ_DEV_OP | OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE } }; NETLINK_FAMILY nlDatapathFamilyOps = { .name = OVS_DATAPATH_FAMILY, .id = OVS_WIN_NL_DATAPATH_FAMILY_ID, .version = OVS_DATAPATH_VERSION, .maxAttr = OVS_DP_ATTR_MAX, .cmds = nlDatapathFamilyCmdOps, .opsCount = ARRAY_SIZE(nlDatapathFamilyCmdOps) }; /* Netlink packet family. */ NETLINK_CMD nlPacketFamilyCmdOps[] = { { .cmd = OVS_PACKET_CMD_EXECUTE, .handler = OvsNlExecuteCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE } }; NETLINK_FAMILY nlPacketFamilyOps = { .name = OVS_PACKET_FAMILY, .id = OVS_WIN_NL_PACKET_FAMILY_ID, .version = OVS_PACKET_VERSION, .maxAttr = OVS_PACKET_ATTR_MAX, .cmds = nlPacketFamilyCmdOps, .opsCount = ARRAY_SIZE(nlPacketFamilyCmdOps) }; /* Netlink vport family. */ NETLINK_CMD nlVportFamilyCmdOps[] = { { .cmd = OVS_VPORT_CMD_GET, .handler = OvsGetVportCmdHandler, .supportedDevOp = OVS_WRITE_DEV_OP | OVS_READ_DEV_OP | OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE }, { .cmd = OVS_VPORT_CMD_NEW, .handler = OvsNewVportCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE }, { .cmd = OVS_VPORT_CMD_SET, .handler = OvsSetVportCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE }, { .cmd = OVS_VPORT_CMD_DEL, .handler = OvsDeleteVportCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE }, }; NETLINK_FAMILY nlVportFamilyOps = { .name = OVS_VPORT_FAMILY, .id = OVS_WIN_NL_VPORT_FAMILY_ID, .version = OVS_VPORT_VERSION, .maxAttr = OVS_VPORT_ATTR_MAX, .cmds = nlVportFamilyCmdOps, .opsCount = ARRAY_SIZE(nlVportFamilyCmdOps) }; /* Netlink flow family. */ NETLINK_CMD nlFlowFamilyCmdOps[] = { { .cmd = OVS_FLOW_CMD_NEW, .handler = OvsFlowNlCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE }, { .cmd = OVS_FLOW_CMD_SET, .handler = OvsFlowNlCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE }, { .cmd = OVS_FLOW_CMD_DEL, .handler = OvsFlowNlCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = TRUE }, { .cmd = OVS_FLOW_CMD_GET, .handler = OvsFlowNlGetCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP | OVS_WRITE_DEV_OP | OVS_READ_DEV_OP, .validateDpIndex = TRUE }, }; NETLINK_FAMILY nlFLowFamilyOps = { .name = OVS_FLOW_FAMILY, .id = OVS_WIN_NL_FLOW_FAMILY_ID, .version = OVS_FLOW_VERSION, .maxAttr = OVS_FLOW_ATTR_MAX, .cmds = nlFlowFamilyCmdOps, .opsCount = ARRAY_SIZE(nlFlowFamilyCmdOps) }; /* Netlink netdev family. */ NETLINK_CMD nlNetdevFamilyCmdOps[] = { { .cmd = OVS_WIN_NETDEV_CMD_GET, .handler = OvsGetNetdevCmdHandler, .supportedDevOp = OVS_TRANSACTION_DEV_OP, .validateDpIndex = FALSE }, }; NETLINK_FAMILY nlNetdevFamilyOps = { .name = OVS_WIN_NETDEV_FAMILY, .id = OVS_WIN_NL_NETDEV_FAMILY_ID, .version = OVS_WIN_NETDEV_VERSION, .maxAttr = OVS_WIN_NETDEV_ATTR_MAX, .cmds = nlNetdevFamilyCmdOps, .opsCount = ARRAY_SIZE(nlNetdevFamilyCmdOps) }; static NTSTATUS MapIrpOutputBuffer(PIRP irp, UINT32 bufferLength, UINT32 requiredLength, PVOID *buffer); static NTSTATUS ValidateNetlinkCmd(UINT32 devOp, POVS_OPEN_INSTANCE instance, POVS_MESSAGE ovsMsg, NETLINK_FAMILY *nlFamilyOps); static NTSTATUS InvokeNetlinkCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, NETLINK_FAMILY *nlFamilyOps, UINT32 *replyLen); /* Handles to the device object for communication with userspace. */ NDIS_HANDLE gOvsDeviceHandle; PDEVICE_OBJECT gOvsDeviceObject; _Dispatch_type_(IRP_MJ_CREATE) _Dispatch_type_(IRP_MJ_CLOSE) DRIVER_DISPATCH OvsOpenCloseDevice; _Dispatch_type_(IRP_MJ_CLEANUP) DRIVER_DISPATCH OvsCleanupDevice; _Dispatch_type_(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH OvsDeviceControl; #ifdef ALLOC_PRAGMA #pragma alloc_text(INIT, OvsCreateDeviceObject) #pragma alloc_text(PAGE, OvsOpenCloseDevice) #pragma alloc_text(PAGE, OvsCleanupDevice) #pragma alloc_text(PAGE, OvsDeviceControl) #endif // ALLOC_PRAGMA /* * We might hit this limit easily since userspace opens a netlink descriptor for * each thread, and at least one descriptor per vport. Revisit this later. */ #define OVS_MAX_OPEN_INSTANCES 512 #define OVS_SYSTEM_DP_NAME "ovs-system" POVS_OPEN_INSTANCE ovsOpenInstanceArray[OVS_MAX_OPEN_INSTANCES]; UINT32 ovsNumberOfOpenInstances; extern POVS_SWITCH_CONTEXT gOvsSwitchContext; NDIS_SPIN_LOCK ovsCtrlLockObj; PNDIS_SPIN_LOCK gOvsCtrlLock; NTSTATUS InitUserDumpState(POVS_OPEN_INSTANCE instance, POVS_MESSAGE ovsMsg) { /* Clear the dumpState from a previous dump sequence. */ ASSERT(instance->dumpState.ovsMsg == NULL); ASSERT(ovsMsg); instance->dumpState.ovsMsg = (POVS_MESSAGE)OvsAllocateMemoryWithTag(sizeof(OVS_MESSAGE), OVS_DATAPATH_POOL_TAG); if (instance->dumpState.ovsMsg == NULL) { return STATUS_NO_MEMORY; } RtlCopyMemory(instance->dumpState.ovsMsg, ovsMsg, sizeof *instance->dumpState.ovsMsg); RtlZeroMemory(instance->dumpState.index, sizeof instance->dumpState.index); return STATUS_SUCCESS; } VOID FreeUserDumpState(POVS_OPEN_INSTANCE instance) { if (instance->dumpState.ovsMsg != NULL) { OvsFreeMemoryWithTag(instance->dumpState.ovsMsg, OVS_DATAPATH_POOL_TAG); RtlZeroMemory(&instance->dumpState, sizeof instance->dumpState); } } VOID OvsInit() { gOvsCtrlLock = &ovsCtrlLockObj; NdisAllocateSpinLock(gOvsCtrlLock); OvsInitEventQueue(); } VOID OvsCleanup() { OvsCleanupEventQueue(); if (gOvsCtrlLock) { NdisFreeSpinLock(gOvsCtrlLock); gOvsCtrlLock = NULL; } } VOID OvsAcquireCtrlLock() { NdisAcquireSpinLock(gOvsCtrlLock); } VOID OvsReleaseCtrlLock() { NdisReleaseSpinLock(gOvsCtrlLock); } /* * -------------------------------------------------------------------------- * Creates the communication device between user and kernel, and also * initializes the data associated data structures. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsCreateDeviceObject(NDIS_HANDLE ovsExtDriverHandle) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; UNICODE_STRING deviceName; UNICODE_STRING symbolicDeviceName; PDRIVER_DISPATCH dispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1]; NDIS_DEVICE_OBJECT_ATTRIBUTES deviceAttributes; OVS_LOG_TRACE("ovsExtDriverHandle: %p", ovsExtDriverHandle); RtlZeroMemory(dispatchTable, (IRP_MJ_MAXIMUM_FUNCTION + 1) * sizeof (PDRIVER_DISPATCH)); dispatchTable[IRP_MJ_CREATE] = OvsOpenCloseDevice; dispatchTable[IRP_MJ_CLOSE] = OvsOpenCloseDevice; dispatchTable[IRP_MJ_CLEANUP] = OvsCleanupDevice; dispatchTable[IRP_MJ_DEVICE_CONTROL] = OvsDeviceControl; NdisInitUnicodeString(&deviceName, OVS_DEVICE_NAME_NT); NdisInitUnicodeString(&symbolicDeviceName, OVS_DEVICE_NAME_DOS); RtlZeroMemory(&deviceAttributes, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES)); OVS_INIT_OBJECT_HEADER(&deviceAttributes.Header, NDIS_OBJECT_TYPE_DEVICE_OBJECT_ATTRIBUTES, NDIS_DEVICE_OBJECT_ATTRIBUTES_REVISION_1, sizeof (NDIS_DEVICE_OBJECT_ATTRIBUTES)); deviceAttributes.DeviceName = &deviceName; deviceAttributes.SymbolicName = &symbolicDeviceName; deviceAttributes.MajorFunctions = dispatchTable; deviceAttributes.ExtensionSize = sizeof (OVS_DEVICE_EXTENSION); status = NdisRegisterDeviceEx(ovsExtDriverHandle, &deviceAttributes, &gOvsDeviceObject, &gOvsDeviceHandle); if (status != NDIS_STATUS_SUCCESS) { POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(gOvsDeviceObject); ASSERT(gOvsDeviceObject != NULL); ASSERT(gOvsDeviceHandle != NULL); if (ovsExt) { ovsExt->numberOpenInstance = 0; } } else { OvsRegisterSystemProvider((PVOID)gOvsDeviceObject); } OVS_LOG_TRACE("DeviceObject: %p", gOvsDeviceObject); return status; } VOID OvsDeleteDeviceObject() { if (gOvsDeviceHandle) { #ifdef DBG POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION) NdisGetDeviceReservedExtension(gOvsDeviceObject); if (ovsExt) { ASSERT(ovsExt->numberOpenInstance == 0); } #endif ASSERT(gOvsDeviceObject); NdisDeregisterDeviceEx(gOvsDeviceHandle); gOvsDeviceHandle = NULL; gOvsDeviceObject = NULL; OvsUnregisterSystemProvider(); } } POVS_OPEN_INSTANCE OvsGetOpenInstance(PFILE_OBJECT fileObject, UINT32 dpNo) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; ASSERT(instance); ASSERT(instance->fileObject == fileObject); if (gOvsSwitchContext->dpNo != dpNo) { return NULL; } return instance; } POVS_OPEN_INSTANCE OvsFindOpenInstance(PFILE_OBJECT fileObject) { UINT32 i, j; for (i = 0, j = 0; i < OVS_MAX_OPEN_INSTANCES && j < ovsNumberOfOpenInstances; i++) { if (ovsOpenInstanceArray[i]) { if (ovsOpenInstanceArray[i]->fileObject == fileObject) { return ovsOpenInstanceArray[i]; } j++; } } return NULL; } NTSTATUS OvsAddOpenInstance(POVS_DEVICE_EXTENSION ovsExt, PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)OvsAllocateMemoryWithTag(sizeof(OVS_OPEN_INSTANCE), OVS_DATAPATH_POOL_TAG); UINT32 i; if (instance == NULL) { return STATUS_NO_MEMORY; } OvsAcquireCtrlLock(); ASSERT(OvsFindOpenInstance(fileObject) == NULL); if (ovsNumberOfOpenInstances >= OVS_MAX_OPEN_INSTANCES) { OvsReleaseCtrlLock(); OvsFreeMemoryWithTag(instance, OVS_DATAPATH_POOL_TAG); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(instance, sizeof (OVS_OPEN_INSTANCE)); for (i = 0; i < OVS_MAX_OPEN_INSTANCES; i++) { if (ovsOpenInstanceArray[i] == NULL) { ovsOpenInstanceArray[i] = instance; ovsNumberOfOpenInstances++; instance->cookie = i; break; } } ASSERT(i < OVS_MAX_OPEN_INSTANCES); instance->fileObject = fileObject; ASSERT(fileObject->FsContext == NULL); instance->pid = (UINT32)InterlockedIncrement((LONG volatile *)&ovsExt->pidCount); if (instance->pid == 0) { /* XXX: check for rollover. */ } fileObject->FsContext = instance; OvsReleaseCtrlLock(); return STATUS_SUCCESS; } static VOID OvsCleanupOpenInstance(PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; ASSERT(instance); ASSERT(fileObject == instance->fileObject); OvsCleanupEvent(instance); OvsCleanupPacketQueue(instance); } VOID OvsRemoveOpenInstance(PFILE_OBJECT fileObject) { POVS_OPEN_INSTANCE instance; ASSERT(fileObject->FsContext); instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; ASSERT(instance->cookie < OVS_MAX_OPEN_INSTANCES); OvsAcquireCtrlLock(); fileObject->FsContext = NULL; ASSERT(ovsOpenInstanceArray[instance->cookie] == instance); ovsOpenInstanceArray[instance->cookie] = NULL; ovsNumberOfOpenInstances--; OvsReleaseCtrlLock(); ASSERT(instance->eventQueue == NULL); ASSERT (instance->packetQueue == NULL); FreeUserDumpState(instance); OvsFreeMemoryWithTag(instance, OVS_DATAPATH_POOL_TAG); } NTSTATUS OvsCompleteIrpRequest(PIRP irp, ULONG_PTR infoPtr, NTSTATUS status) { irp->IoStatus.Information = infoPtr; irp->IoStatus.Status = status; IoCompleteRequest(irp, IO_NO_INCREMENT); return status; } NTSTATUS OvsOpenCloseDevice(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_SUCCESS; PFILE_OBJECT fileObject; POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject); ASSERT(deviceObject == gOvsDeviceObject); ASSERT(ovsExt != NULL); irpSp = IoGetCurrentIrpStackLocation(irp); fileObject = irpSp->FileObject; OVS_LOG_TRACE("DeviceObject: %p, fileObject:%p, instance: %u", deviceObject, fileObject, ovsExt->numberOpenInstance); switch (irpSp->MajorFunction) { case IRP_MJ_CREATE: status = OvsAddOpenInstance(ovsExt, fileObject); if (STATUS_SUCCESS == status) { InterlockedIncrement((LONG volatile *)&ovsExt->numberOpenInstance); } break; case IRP_MJ_CLOSE: ASSERT(ovsExt->numberOpenInstance > 0); OvsRemoveOpenInstance(fileObject); InterlockedDecrement((LONG volatile *)&ovsExt->numberOpenInstance); break; default: ASSERT(0); } return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status); } _Use_decl_annotations_ NTSTATUS OvsCleanupDevice(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; PFILE_OBJECT fileObject; NTSTATUS status = STATUS_SUCCESS; #ifdef DBG POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject); if (ovsExt) { ASSERT(ovsExt->numberOpenInstance > 0); } #else UNREFERENCED_PARAMETER(deviceObject); #endif ASSERT(deviceObject == gOvsDeviceObject); irpSp = IoGetCurrentIrpStackLocation(irp); fileObject = irpSp->FileObject; ASSERT(irpSp->MajorFunction == IRP_MJ_CLEANUP); OvsCleanupOpenInstance(fileObject); return OvsCompleteIrpRequest(irp, (ULONG_PTR)0, status); } /* * -------------------------------------------------------------------------- * IOCTL function handler for the device. * -------------------------------------------------------------------------- */ NTSTATUS OvsDeviceControl(PDEVICE_OBJECT deviceObject, PIRP irp) { PIO_STACK_LOCATION irpSp; NTSTATUS status = STATUS_SUCCESS; PFILE_OBJECT fileObject; PVOID inputBuffer = NULL; PVOID outputBuffer = NULL; UINT32 inputBufferLen, outputBufferLen; UINT32 code, replyLen = 0; POVS_OPEN_INSTANCE instance; UINT32 devOp; OVS_MESSAGE ovsMsgReadOp; POVS_MESSAGE ovsMsg; NETLINK_FAMILY *nlFamilyOps; OVS_USER_PARAMS_CONTEXT usrParamsCtx; #ifdef DBG POVS_DEVICE_EXTENSION ovsExt = (POVS_DEVICE_EXTENSION)NdisGetDeviceReservedExtension(deviceObject); ASSERT(deviceObject == gOvsDeviceObject); ASSERT(ovsExt); ASSERT(ovsExt->numberOpenInstance > 0); #else UNREFERENCED_PARAMETER(deviceObject); #endif irpSp = IoGetCurrentIrpStackLocation(irp); ASSERT(irpSp->MajorFunction == IRP_MJ_DEVICE_CONTROL); ASSERT(irpSp->FileObject != NULL); fileObject = irpSp->FileObject; instance = (POVS_OPEN_INSTANCE)fileObject->FsContext; code = irpSp->Parameters.DeviceIoControl.IoControlCode; inputBufferLen = irpSp->Parameters.DeviceIoControl.InputBufferLength; outputBufferLen = irpSp->Parameters.DeviceIoControl.OutputBufferLength; inputBuffer = irp->AssociatedIrp.SystemBuffer; /* Check if the extension is enabled. */ if (NULL == gOvsSwitchContext) { status = STATUS_NOT_FOUND; goto exit; } if (!OvsAcquireSwitchContext()) { status = STATUS_NOT_FOUND; goto exit; } /* * Validate the input/output buffer arguments depending on the type of the * operation. */ switch (code) { case OVS_IOCTL_GET_PID: /* Both input buffer and output buffer use the same location. */ outputBuffer = irp->AssociatedIrp.SystemBuffer; if (outputBufferLen != 0) { InitUserParamsCtx(irp, instance, 0, NULL, inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &usrParamsCtx); ASSERT(outputBuffer); } else { status = STATUS_NDIS_INVALID_LENGTH; goto done; } status = OvsGetPidHandler(&usrParamsCtx, &replyLen); goto done; case OVS_IOCTL_TRANSACT: /* Both input buffer and output buffer are mandatory. */ if (outputBufferLen != 0) { status = MapIrpOutputBuffer(irp, outputBufferLen, sizeof *ovsMsg, &outputBuffer); if (status != STATUS_SUCCESS) { goto done; } ASSERT(outputBuffer); } else { status = STATUS_NDIS_INVALID_LENGTH; goto done; } if (inputBufferLen < sizeof (*ovsMsg)) { status = STATUS_NDIS_INVALID_LENGTH; goto done; } ovsMsg = inputBuffer; devOp = OVS_TRANSACTION_DEV_OP; break; case OVS_IOCTL_READ_EVENT: case OVS_IOCTL_READ_PACKET: /* * Output buffer is mandatory. These IOCTLs are used to read events and * packets respectively. It is convenient to have separate ioctls. */ if (outputBufferLen != 0) { status = MapIrpOutputBuffer(irp, outputBufferLen, sizeof *ovsMsg, &outputBuffer); if (status != STATUS_SUCCESS) { goto done; } ASSERT(outputBuffer); } else { status = STATUS_NDIS_INVALID_LENGTH; goto done; } inputBuffer = NULL; inputBufferLen = 0; ovsMsg = &ovsMsgReadOp; RtlZeroMemory(ovsMsg, sizeof *ovsMsg); ovsMsg->nlMsg.nlmsgLen = sizeof *ovsMsg; ovsMsg->nlMsg.nlmsgType = nlControlFamilyOps.id; ovsMsg->nlMsg.nlmsgPid = instance->pid; /* An "artificial" command so we can use NL family function table*/ ovsMsg->genlMsg.cmd = (code == OVS_IOCTL_READ_EVENT) ? OVS_CTRL_CMD_EVENT_NOTIFY : OVS_CTRL_CMD_READ_NOTIFY; ovsMsg->genlMsg.version = nlControlFamilyOps.version; devOp = OVS_READ_DEV_OP; break; case OVS_IOCTL_READ: /* Output buffer is mandatory. */ if (outputBufferLen != 0) { status = MapIrpOutputBuffer(irp, outputBufferLen, sizeof *ovsMsg, &outputBuffer); if (status != STATUS_SUCCESS) { goto done; } ASSERT(outputBuffer); } else { status = STATUS_NDIS_INVALID_LENGTH; goto done; } /* * Operate in the mode that read ioctl is similar to ReadFile(). This * might change as the userspace code gets implemented. */ inputBuffer = NULL; inputBufferLen = 0; /* * For implementing read (ioctl or otherwise), we need to store some * state in the instance to indicate the command that started the dump * operation. The state can setup 'ovsMsgReadOp' appropriately. Note * that 'ovsMsgReadOp' is needed only in this function to call into the * appropriate handler. The handler itself can access the state in the * instance. * * In the absence of a dump start, return 0 bytes. */ if (instance->dumpState.ovsMsg == NULL) { replyLen = 0; status = STATUS_SUCCESS; goto done; } RtlCopyMemory(&ovsMsgReadOp, instance->dumpState.ovsMsg, sizeof (ovsMsgReadOp)); /* Create an NL message for consumption. */ ovsMsg = &ovsMsgReadOp; devOp = OVS_READ_DEV_OP; break; case OVS_IOCTL_WRITE: /* Input buffer is mandatory. */ if (inputBufferLen < sizeof (*ovsMsg)) { status = STATUS_NDIS_INVALID_LENGTH; goto done; } ovsMsg = inputBuffer; devOp = OVS_WRITE_DEV_OP; break; default: status = STATUS_INVALID_DEVICE_REQUEST; goto done; } ASSERT(ovsMsg); switch (ovsMsg->nlMsg.nlmsgType) { case OVS_WIN_NL_CTRL_FAMILY_ID: nlFamilyOps = &nlControlFamilyOps; break; case OVS_WIN_NL_DATAPATH_FAMILY_ID: nlFamilyOps = &nlDatapathFamilyOps; break; case OVS_WIN_NL_FLOW_FAMILY_ID: nlFamilyOps = &nlFLowFamilyOps; break; case OVS_WIN_NL_PACKET_FAMILY_ID: nlFamilyOps = &nlPacketFamilyOps; break; case OVS_WIN_NL_VPORT_FAMILY_ID: nlFamilyOps = &nlVportFamilyOps; break; case OVS_WIN_NL_NETDEV_FAMILY_ID: nlFamilyOps = &nlNetdevFamilyOps; break; default: status = STATUS_INVALID_PARAMETER; goto done; } /* * For read operation, avoid duplicate validation since 'ovsMsg' is either * "artificial" or was copied from a previously validated 'ovsMsg'. */ if (devOp != OVS_READ_DEV_OP) { status = ValidateNetlinkCmd(devOp, instance, ovsMsg, nlFamilyOps); if (status != STATUS_SUCCESS) { goto done; } } InitUserParamsCtx(irp, instance, devOp, ovsMsg, inputBuffer, inputBufferLen, outputBuffer, outputBufferLen, &usrParamsCtx); status = InvokeNetlinkCmdHandler(&usrParamsCtx, nlFamilyOps, &replyLen); done: OvsReleaseSwitchContext(gOvsSwitchContext); exit: /* Should not complete a pending IRP unless proceesing is completed. */ if (status == STATUS_PENDING) { return status; } return OvsCompleteIrpRequest(irp, (ULONG_PTR)replyLen, status); } /* * -------------------------------------------------------------------------- * Function to validate a netlink command. Only certain combinations of * (device operation, netlink family, command) are valid. * -------------------------------------------------------------------------- */ static NTSTATUS ValidateNetlinkCmd(UINT32 devOp, POVS_OPEN_INSTANCE instance, POVS_MESSAGE ovsMsg, NETLINK_FAMILY *nlFamilyOps) { NTSTATUS status = STATUS_INVALID_PARAMETER; UINT16 i; for (i = 0; i < nlFamilyOps->opsCount; i++) { if (nlFamilyOps->cmds[i].cmd == ovsMsg->genlMsg.cmd) { /* Validate if the command is valid for the device operation. */ if ((devOp & nlFamilyOps->cmds[i].supportedDevOp) == 0) { status = STATUS_INVALID_PARAMETER; goto done; } /* Validate the version. */ if (nlFamilyOps->version > ovsMsg->genlMsg.version) { status = STATUS_INVALID_PARAMETER; goto done; } /* Validate the DP for commands that require a DP. */ if (nlFamilyOps->cmds[i].validateDpIndex == TRUE) { if (ovsMsg->ovsHdr.dp_ifindex != (INT)gOvsSwitchContext->dpNo) { status = STATUS_INVALID_PARAMETER; goto done; } } /* Validate the PID. */ if (ovsMsg->nlMsg.nlmsgPid != instance->pid) { status = STATUS_INVALID_PARAMETER; goto done; } status = STATUS_SUCCESS; break; } } done: return status; } /* * -------------------------------------------------------------------------- * Function to invoke the netlink command handler. The function also stores * the return value of the handler function to construct a 'NL_ERROR' message, * and in turn returns success to the caller. * -------------------------------------------------------------------------- */ static NTSTATUS InvokeNetlinkCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, NETLINK_FAMILY *nlFamilyOps, UINT32 *replyLen) { NTSTATUS status = STATUS_INVALID_PARAMETER; UINT16 i; for (i = 0; i < nlFamilyOps->opsCount; i++) { if (nlFamilyOps->cmds[i].cmd == usrParamsCtx->ovsMsg->genlMsg.cmd) { NetlinkCmdHandler *handler = nlFamilyOps->cmds[i].handler; ASSERT(handler); if (handler) { status = handler(usrParamsCtx, replyLen); } break; } } /* * Netlink socket semantics dictate that the return value of the netlink * function should be an error ONLY under fatal conditions. If the message * made it all the way to the handler function, it is not a fatal condition. * Absorb the error returned by the handler function into a 'struct * NL_ERROR' and populate the 'output buffer' to return to userspace. * * This behavior is obviously applicable only to netlink commands that * specify an 'output buffer'. For other commands, we return the error as * is. * * 'STATUS_PENDING' is a special return value and userspace is equipped to * handle it. */ if (status != STATUS_SUCCESS && status != STATUS_PENDING) { if (usrParamsCtx->devOp != OVS_WRITE_DEV_OP && *replyLen == 0) { NL_ERROR nlError = NlMapStatusToNlErr(status); OVS_MESSAGE msgInTmp = { 0 }; POVS_MESSAGE msgIn = NULL; POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; if (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_CTRL_CMD_EVENT_NOTIFY || usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_CTRL_CMD_READ_NOTIFY) { /* There's no input buffer associated with such requests. */ NL_BUFFER nlBuffer; msgIn = &msgInTmp; NlBufInit(&nlBuffer, (PCHAR)msgIn, sizeof *msgIn); NlFillNlHdr(&nlBuffer, nlFamilyOps->id, 0, 0, usrParamsCtx->ovsInstance->pid); } else { msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; } ASSERT(msgIn); ASSERT(msgError); NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } if (*replyLen != 0) { status = STATUS_SUCCESS; } } #ifdef DBG if (usrParamsCtx->devOp != OVS_WRITE_DEV_OP) { ASSERT(status == STATUS_PENDING || *replyLen != 0 || status == STATUS_SUCCESS); } #endif return status; } /* * -------------------------------------------------------------------------- * Handler for 'OVS_IOCTL_GET_PID'. * * Each handle on the device is assigned a unique PID when the handle is * created. This function passes the PID to userspace using METHOD_BUFFERED * method. * -------------------------------------------------------------------------- */ static NTSTATUS OvsGetPidHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS status = STATUS_SUCCESS; PUINT32 msgOut = (PUINT32)usrParamsCtx->outputBuffer; if (usrParamsCtx->outputLength >= sizeof *msgOut) { POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; RtlZeroMemory(msgOut, sizeof *msgOut); RtlCopyMemory(msgOut, &instance->pid, sizeof(*msgOut)); *replyLen = sizeof *msgOut; } else { *replyLen = sizeof *msgOut; status = STATUS_NDIS_INVALID_LENGTH; } return status; } /* * -------------------------------------------------------------------------- * Utility function to fill up information about the datapath in a reply to * userspace. * -------------------------------------------------------------------------- */ static NTSTATUS OvsDpFillInfo(POVS_SWITCH_CONTEXT ovsSwitchContext, POVS_MESSAGE msgIn, PNL_BUFFER nlBuf) { BOOLEAN writeOk; OVS_MESSAGE msgOutTmp; OVS_DATAPATH *datapath = &ovsSwitchContext->datapath; PNL_MSG_HDR nlMsg; ASSERT(NlBufAt(nlBuf, 0, 0) != 0 && NlBufRemLen(nlBuf) >= sizeof *msgIn); msgOutTmp.nlMsg.nlmsgType = OVS_WIN_NL_DATAPATH_FAMILY_ID; msgOutTmp.nlMsg.nlmsgFlags = 0; /* XXX: ? */ msgOutTmp.nlMsg.nlmsgSeq = msgIn->nlMsg.nlmsgSeq; msgOutTmp.nlMsg.nlmsgPid = msgIn->nlMsg.nlmsgPid; msgOutTmp.genlMsg.cmd = OVS_DP_CMD_GET; msgOutTmp.genlMsg.version = nlDatapathFamilyOps.version; msgOutTmp.genlMsg.reserved = 0; msgOutTmp.ovsHdr.dp_ifindex = ovsSwitchContext->dpNo; writeOk = NlMsgPutHead(nlBuf, (PCHAR)&msgOutTmp, sizeof msgOutTmp); if (writeOk) { writeOk = NlMsgPutTailString(nlBuf, OVS_DP_ATTR_NAME, OVS_SYSTEM_DP_NAME); } if (writeOk) { OVS_DP_STATS dpStats; dpStats.n_hit = datapath->hits; dpStats.n_missed = datapath->misses; dpStats.n_lost = datapath->lost; dpStats.n_flows = datapath->nFlows; writeOk = NlMsgPutTailUnspec(nlBuf, OVS_DP_ATTR_STATS, (PCHAR)&dpStats, sizeof dpStats); } nlMsg = (PNL_MSG_HDR)NlBufAt(nlBuf, 0, 0); nlMsg->nlmsgLen = NlBufSize(nlBuf); return writeOk ? STATUS_SUCCESS : STATUS_INVALID_BUFFER_SIZE; } /* * -------------------------------------------------------------------------- * Handler for queueing an IRP used for event notification. The IRP is * completed when a port state changes. STATUS_PENDING is returned on * success. User mode keep a pending IRP at all times. * -------------------------------------------------------------------------- */ static NTSTATUS OvsPendEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NDIS_STATUS status; UNREFERENCED_PARAMETER(replyLen); POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; OVS_EVENT_POLL poll; poll.dpNo = msgIn->ovsHdr.dp_ifindex; status = OvsWaitEventIoctl(usrParamsCtx->irp, instance->fileObject, &poll, sizeof poll); return status; } /* * -------------------------------------------------------------------------- * Handler for the subscription for the event queue * -------------------------------------------------------------------------- */ static NTSTATUS OvsSubscribeEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NDIS_STATUS status; OVS_EVENT_SUBSCRIBE request; BOOLEAN rc; UINT8 join; PNL_ATTR attrs[2]; const NL_POLICY policy[] = { [OVS_NL_ATTR_MCAST_GRP] = {.type = NL_A_U32 }, [OVS_NL_ATTR_MCAST_JOIN] = {.type = NL_A_U8 }, }; UNREFERENCED_PARAMETER(replyLen); POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; rc = NlAttrParse(&msgIn->nlMsg, sizeof (*msgIn), NlMsgAttrsLen((PNL_MSG_HDR)msgIn), policy, ARRAY_SIZE(policy), attrs, ARRAY_SIZE(attrs)); if (!rc) { status = STATUS_INVALID_PARAMETER; goto done; } /* XXX Ignore the MC group for now */ join = NlAttrGetU8(attrs[OVS_NL_ATTR_MCAST_JOIN]); request.dpNo = msgIn->ovsHdr.dp_ifindex; request.subscribe = join; request.mask = OVS_EVENT_MASK_ALL; status = OvsSubscribeEventIoctl(instance->fileObject, &request, sizeof request); done: return status; } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_DP_CMD_NEW'. * -------------------------------------------------------------------------- */ static NTSTATUS OvsNewDpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { return HandleDpTransactionCommon(usrParamsCtx, replyLen); } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_DP_CMD_GET'. * * The function handles both the dump based as well as the transaction based * 'OVS_DP_CMD_GET' command. In the dump command, it handles the initial * call to setup dump state, as well as subsequent calls to continue dumping * data. * -------------------------------------------------------------------------- */ static NTSTATUS OvsGetDpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) { return HandleDpTransactionCommon(usrParamsCtx, replyLen); } else { return HandleGetDpDump(usrParamsCtx, replyLen); } } /* * -------------------------------------------------------------------------- * Function for handling the transaction based 'OVS_DP_CMD_GET' command. * -------------------------------------------------------------------------- */ static NTSTATUS HandleGetDpTransaction(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { return HandleDpTransactionCommon(usrParamsCtx, replyLen); } /* * -------------------------------------------------------------------------- * Function for handling the dump-based 'OVS_DP_CMD_GET' command. * -------------------------------------------------------------------------- */ static NTSTATUS HandleGetDpDump(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) { *replyLen = 0; OvsSetupDumpStart(usrParamsCtx); } else { NL_BUFFER nlBuf; NTSTATUS status; POVS_MESSAGE msgIn = instance->dumpState.ovsMsg; ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP); if (instance->dumpState.ovsMsg == NULL) { ASSERT(FALSE); return STATUS_INVALID_DEVICE_STATE; } /* Dump state must have been deleted after previous dump operation. */ ASSERT(instance->dumpState.index[0] == 0); /* Output buffer has been validated while validating read dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); status = OvsDpFillInfo(gOvsSwitchContext, msgIn, &nlBuf); if (status != STATUS_SUCCESS) { *replyLen = 0; FreeUserDumpState(instance); return status; } /* Increment the dump index. */ instance->dumpState.index[0] = 1; *replyLen = msgOut->nlMsg.nlmsgLen; /* Free up the dump state, since there's no more data to continue. */ FreeUserDumpState(instance); } return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Command Handler for 'OVS_DP_CMD_SET'. * -------------------------------------------------------------------------- */ static NTSTATUS OvsSetDpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { return HandleDpTransactionCommon(usrParamsCtx, replyLen); } /* * -------------------------------------------------------------------------- * Function for handling transaction based 'OVS_DP_CMD_NEW', 'OVS_DP_CMD_GET' * and 'OVS_DP_CMD_SET' commands. * * 'OVS_DP_CMD_NEW' is implemented to keep userspace code happy. Creation of a * new datapath is not supported currently. * -------------------------------------------------------------------------- */ static NTSTATUS HandleDpTransactionCommon(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; NTSTATUS status = STATUS_SUCCESS; NL_BUFFER nlBuf; NL_ERROR nlError = NL_ERROR_SUCCESS; static const NL_POLICY ovsDatapathSetPolicy[] = { [OVS_DP_ATTR_NAME] = { .type = NL_A_STRING, .maxLen = IFNAMSIZ }, [OVS_DP_ATTR_UPCALL_PID] = { .type = NL_A_U32, .optional = TRUE }, [OVS_DP_ATTR_USER_FEATURES] = { .type = NL_A_U32, .optional = TRUE }, }; PNL_ATTR dpAttrs[ARRAY_SIZE(ovsDatapathSetPolicy)]; UNREFERENCED_PARAMETER(msgOut); /* input buffer has been validated while validating write dev op. */ ASSERT(msgIn != NULL && usrParamsCtx->inputLength >= sizeof *msgIn); /* Parse any attributes in the request. */ if (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_SET || usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_NEW) { if (!NlAttrParse((PNL_MSG_HDR)msgIn, NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN, NlMsgAttrsLen((PNL_MSG_HDR)msgIn), ovsDatapathSetPolicy, ARRAY_SIZE(ovsDatapathSetPolicy), dpAttrs, ARRAY_SIZE(dpAttrs))) { return STATUS_INVALID_PARAMETER; } /* * XXX: Not clear at this stage if there's any role for the * OVS_DP_ATTR_UPCALL_PID and OVS_DP_ATTR_USER_FEATURES attributes passed * from userspace. */ } else { RtlZeroMemory(dpAttrs, sizeof dpAttrs); } /* Output buffer has been validated while validating transact dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); if (dpAttrs[OVS_DP_ATTR_NAME] != NULL) { if (!OvsCompareString(NlAttrGet(dpAttrs[OVS_DP_ATTR_NAME]), OVS_SYSTEM_DP_NAME)) { /* Creation of new datapaths is not supported. */ if (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_SET) { nlError = NL_ERROR_NOTSUPP; goto cleanup; } nlError = NL_ERROR_NODEV; goto cleanup; } } else if ((UINT32)msgIn->ovsHdr.dp_ifindex != gOvsSwitchContext->dpNo) { nlError = NL_ERROR_NODEV; goto cleanup; } if (usrParamsCtx->ovsMsg->genlMsg.cmd == OVS_DP_CMD_NEW) { nlError = NL_ERROR_EXIST; goto cleanup; } status = OvsDpFillInfo(gOvsSwitchContext, msgIn, &nlBuf); *replyLen = NlBufSize(&nlBuf); cleanup: if (nlError != NL_ERROR_SUCCESS) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; } return STATUS_SUCCESS; } NTSTATUS OvsSetupDumpStart(POVS_USER_PARAMS_CONTEXT usrParamsCtx) { POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; /* input buffer has been validated while validating write dev op. */ ASSERT(msgIn != NULL && usrParamsCtx->inputLength >= sizeof *msgIn); /* A write operation that does not indicate dump start is invalid. */ if ((msgIn->nlMsg.nlmsgFlags & NLM_F_DUMP) != NLM_F_DUMP) { return STATUS_INVALID_PARAMETER; } /* XXX: Handle other NLM_F_* flags in the future. */ /* * This operation should be setting up the dump state. If there's any * previous state, clear it up so as to set it up afresh. */ FreeUserDumpState(instance); return InitUserDumpState(instance, msgIn); } /* * -------------------------------------------------------------------------- * Utility function to map the output buffer in an IRP. The buffer is assumed * to have been passed down using METHOD_OUT_DIRECT (Direct I/O). * -------------------------------------------------------------------------- */ static NTSTATUS MapIrpOutputBuffer(PIRP irp, UINT32 bufferLength, UINT32 requiredLength, PVOID *buffer) { ASSERT(irp); ASSERT(buffer); ASSERT(bufferLength); ASSERT(requiredLength); if (!buffer || !irp || bufferLength == 0 || requiredLength == 0) { return STATUS_INVALID_PARAMETER; } if (bufferLength < requiredLength) { return STATUS_NDIS_INVALID_LENGTH; } if (irp->MdlAddress == NULL) { return STATUS_INVALID_PARAMETER; } *buffer = MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); if (*buffer == NULL) { return STATUS_INSUFFICIENT_RESOURCES; } return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * Utility function to fill up information about the state of a port in a reply * to* userspace. * -------------------------------------------------------------------------- */ static NTSTATUS OvsPortFillInfo(POVS_USER_PARAMS_CONTEXT usrParamsCtx, POVS_EVENT_ENTRY eventEntry, PNL_BUFFER nlBuf) { NTSTATUS status; BOOLEAN ok; OVS_MESSAGE msgOutTmp; PNL_MSG_HDR nlMsg; ASSERT(NlBufAt(nlBuf, 0, 0) != 0 && nlBuf->bufRemLen >= sizeof msgOutTmp); msgOutTmp.nlMsg.nlmsgType = OVS_WIN_NL_VPORT_FAMILY_ID; msgOutTmp.nlMsg.nlmsgFlags = 0; /* XXX: ? */ /* driver intiated messages should have zerp seq number*/ msgOutTmp.nlMsg.nlmsgSeq = 0; msgOutTmp.nlMsg.nlmsgPid = usrParamsCtx->ovsInstance->pid; msgOutTmp.genlMsg.version = nlVportFamilyOps.version; msgOutTmp.genlMsg.reserved = 0; /* we don't have netdev yet, treat link up/down a adding/removing a port*/ if (eventEntry->type & (OVS_EVENT_LINK_UP | OVS_EVENT_CONNECT)) { msgOutTmp.genlMsg.cmd = OVS_VPORT_CMD_NEW; } else if (eventEntry->type & (OVS_EVENT_LINK_DOWN | OVS_EVENT_DISCONNECT)) { msgOutTmp.genlMsg.cmd = OVS_VPORT_CMD_DEL; } else { ASSERT(FALSE); return STATUS_UNSUCCESSFUL; } msgOutTmp.ovsHdr.dp_ifindex = gOvsSwitchContext->dpNo; ok = NlMsgPutHead(nlBuf, (PCHAR)&msgOutTmp, sizeof msgOutTmp); if (!ok) { status = STATUS_INVALID_BUFFER_SIZE; goto cleanup; } ok = NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_PORT_NO, eventEntry->portNo) && NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_TYPE, eventEntry->ovsType) && NlMsgPutTailU32(nlBuf, OVS_VPORT_ATTR_UPCALL_PID, eventEntry->upcallPid) && NlMsgPutTailString(nlBuf, OVS_VPORT_ATTR_NAME, eventEntry->ovsName); if (!ok) { status = STATUS_INVALID_BUFFER_SIZE; goto cleanup; } /* XXXX Should we add the port stats attributes?*/ nlMsg = (PNL_MSG_HDR)NlBufAt(nlBuf, 0, 0); nlMsg->nlmsgLen = NlBufSize(nlBuf); status = STATUS_SUCCESS; cleanup: return status; } /* * -------------------------------------------------------------------------- * Handler for reading events from the driver event queue. This handler is * executed when user modes issues a socket receive on a socket assocaited * with the MC group for events. * XXX user mode should read multiple events in one system call * -------------------------------------------------------------------------- */ static NTSTATUS OvsReadEventCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { #ifdef DBG POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE)usrParamsCtx->ovsInstance; #endif NL_BUFFER nlBuf; NTSTATUS status; OVS_EVENT_ENTRY eventEntry; ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP); /* Should never read events with a dump socket */ ASSERT(instance->dumpState.ovsMsg == NULL); /* Must have an event queue */ ASSERT(instance->eventQueue != NULL); /* Output buffer has been validated while validating read dev op. */ ASSERT(msgOut != NULL && usrParamsCtx->outputLength >= sizeof *msgOut); NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); /* remove an event entry from the event queue */ status = OvsRemoveEventEntry(usrParamsCtx->ovsInstance, &eventEntry); if (status != STATUS_SUCCESS) { /* If there were not elements, read should return no data. */ status = STATUS_SUCCESS; *replyLen = 0; goto cleanup; } status = OvsPortFillInfo(usrParamsCtx, &eventEntry, &nlBuf); if (status == NDIS_STATUS_SUCCESS) { *replyLen = NlBufSize(&nlBuf); } cleanup: return status; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Stt.h0000644000000000000000000000013212664352753021377 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594660.213289661 openvswitch-2.5.0/datapath-windows/ovsext/Stt.h0000664000175000017500000000637112664352753023076 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2015 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __OVS_STT_H_ #define __OVS_STT_H_ 1 #define STT_TCP_PORT 7471 #define STT_TCP_PORT_NBO 0x2f1d #define MAX_IP_TOTAL_LEN 65535 // STT defines. #define STT_SEQ_LEN_SHIFT 16 #define STT_SEQ_OFFSET_MASK ((1 << STT_SEQ_LEN_SHIFT) - 1) #define STT_FRAME_LEN(seq) ((seq) >> STT_SEQ_LEN_SHIFT) #define STT_SEGMENT_OFF(seq) ((seq) & STT_SEQ_OFFSET_MASK) #define STT_CSUM_VERIFIED (1 << 0) #define STT_CSUM_PARTIAL (1 << 1) #define STT_PROTO_IPV4 (1 << 2) #define STT_PROTO_TCP (1 << 3) #define STT_PROTO_TYPES (STT_PROTO_IPV4 | STT_PROTO_TCP) #define STT_HASH_TABLE_SIZE ((UINT32)1 << 10) #define STT_HASH_TABLE_MASK (STT_HASH_TABLE_SIZE - 1) #define STT_ENTRY_TIMEOUT 300000000 // 30s #define STT_CLEANUP_INTERVAL 300000000 // 30s #define STT_ETH_PAD 2 typedef struct SttHdr { UINT8 version; UINT8 flags; UINT8 l4Offset; UINT8 reserved; UINT16 mss; UINT16 vlanTCI; UINT64 key; } SttHdr, *PSttHdr; #define STT_HDR_LEN (sizeof(SttHdr) + STT_ETH_PAD) typedef struct _OVS_STT_VPORT { UINT16 dstPort; UINT64 ackNo; UINT64 ipId; UINT64 inPkts; UINT64 outPkts; UINT64 slowInPkts; UINT64 slowOutPkts; } OVS_STT_VPORT, *POVS_STT_VPORT; typedef struct _OVS_STT_PKT_KEY { UINT32 sAddr; UINT32 dAddr; UINT32 ackSeq; } OVS_STT_PKT_KEY, *POVS_STT_PKT_KEY; typedef struct _OVS_STT_PKT_ENTRY { OVS_STT_PKT_KEY ovsPktKey; UINT64 timeout; UINT32 recvdLen; SttHdr sttHdr; PCHAR packetBuf; LIST_ENTRY link; } OVS_STT_PKT_ENTRY, *POVS_STT_PKT_ENTRY; typedef struct _OVS_STT_THREAD_CTX { KEVENT event; PVOID threadObject; UINT32 exit; } OVS_STT_THREAD_CTX, *POVS_STT_THREAD_CTX; NTSTATUS OvsInitSttTunnel(POVS_VPORT_ENTRY vport, UINT16 udpDestPort); VOID OvsCleanupSttTunnel(POVS_VPORT_ENTRY vport); NDIS_STATUS OvsEncapStt(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, PNET_BUFFER_LIST *newNbl); NDIS_STATUS OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, PNET_BUFFER_LIST *newNbl); NTSTATUS OvsInitSttDefragmentation(); VOID OvsCleanupSttDefragmentation(VOID); static __inline UINT32 OvsGetSttTunHdrSize(VOID) { return sizeof (EthHdr) + sizeof(IPHdr) + sizeof(TCPHdr) + STT_HDR_LEN; } #endif /*__OVS_STT_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/ovsext.vcxproj0000644000000000000000000000013212664352753023421 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594660.233290502 openvswitch-2.5.0/datapath-windows/ovsext/ovsext.vcxproj0000664000175000017500000002427212664352753025120 0ustar00jpettitjpettit00000000000000 Win8.1 Debug x64 Win8 Debug x64 Win8.1 Release x64 Win8 Release x64 WDM Driver $(VCTargetsPath11) Win8 Debug Win32 {0D37F250-E766-44C7-90B4-D7E07E77D1AA} {63FE215D-98BE-4440-8081-C6160EFB80FA} $(MSBuildProjectName) WindowsV6.3 True WindowsKernelModeDriver8.1 Win8 True WindowsKernelModeDriver8.1 WindowsV6.3 False WindowsKernelModeDriver8.1 Win8 False WindowsKernelModeDriver8.1 $(IntDir) OVSExt %(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS630=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1 %(PreprocessorDefinitions);NDIS_WDM=1;NDIS640=1 %(AdditionalDependencies);$(DDK_LIB_PATH)\ndis.lib;$(DDK_LIB_PATH)\fwpkclnt.lib;$(SDK_LIB_PATH)\uuid.lib;$(DDK_LIB_PATH)\netio.lib true Level4 $(IntDir);%(AdditionalIncludeDirectories);..\.. $(IntDir);%(AdditionalIncludeDirectories);..\.. $(IntDir);%(AdditionalIncludeDirectories);..\.. $(IntDir);%(AdditionalIncludeDirectories);..\.. ;%(AdditionalIncludeDirectories) precomp.h Create $(IntDir)\precomp.h.pch openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Checksum.c0000644000000000000000000000013212664352753022362 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.169287811 openvswitch-2.5.0/datapath-windows/ovsext/Checksum.c0000664000175000017500000004273712664352753024067 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Checksum.h" #include "Flow.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_CHECKSUM #include "Debug.h" #include "PacketParser.h" #ifndef htons #define htons(_x) (((UINT16)(_x) >> 8) + (((UINT16)(_x) << 8) & 0xff00)) #endif #ifndef swap64 #define swap64(_x) ((((UINT64)(_x) >> 8) & 0x00ff00ff00ff00ff) + \ (((UINT64)(_x) << 8) & 0xff00ff00ff00ff00)) #endif #define fold64(_x) \ _x = ((_x) >> 32) + ((_x) & 0xffffffff); \ _x = (UINT32)(((_x) >> 32) + (_x)); \ _x = ((_x) >> 16) + ((_x) & 0xffff); \ _x = (UINT16)(((_x) >> 16) + (_x)) #define fold32(_x) \ _x = ((_x) >> 16) + ((_x) & 0xffff); \ _x = (UINT16)(((_x) >> 16) + (_x)) /* *---------------------------------------------------------------------------- * CalculateOnesComplement -- * * Given the start address and buffer length, calculate the 1's complement * This routine can be used when multiple buffers are used for a packets. * * PLEASE NOTE, even though the last parameter is UINT64, but the assumption * is it will not overflowed after adding the extra data. * ------------------------------------------------ * * Result: * As name indicate, the final data is not 1's complemnent *---------------------------------------------------------------------------- */ UINT64 CalculateOnesComplement(UINT8 *start, UINT16 totalLength, UINT64 initial, BOOLEAN isEvenStart) { UINT64 sum = 0, val; UINT64 *src = (UINT64 *)start; while (totalLength > 7) { val = *src; sum += val; if (sum < val) sum++; src++; totalLength -= 8; } start = (UINT8 *)src; if (totalLength > 3) { UINT32 val = *(UINT32 *)start; sum += val; if (sum < val) sum++; start += 4; totalLength -= 4; } if (totalLength > 1) { UINT16 val = *(UINT16 *)start; sum += val; if (sum < val) sum++; start += 2; totalLength -= 2; } if (totalLength > 0) { UINT8 val = *start; sum += val; if (sum < val) sum++; start += 1; totalLength -= 1; } ASSERT(totalLength == 0); if (!isEvenStart) { sum = _byteswap_uint64(sum); } sum += initial; if (sum < initial) sum++; return sum; } /* *---------------------------------------------------------------------------- * CalculateChecksum -- * * Given the start point, and length, calculate the checksum * as 1's complement of 1's comlement. * * This assume the checksum field is initailized properly. * * Input Parameter: * ptr: point to the data to be checksumed * totalLength: total length of the data * initial: inital value to remit the checksum. Please note this * value should be network byte order value. * * The last parameter may be useful where you don't want to set * checksum field to zero, in that case you can pass ~checksum, * this is equivalent of set checksum field to zero. * * Result: * The result can be assigned to checksum field directly. *---------------------------------------------------------------------------- */ UINT16 CalculateChecksum(UINT8 *ptr, UINT16 totalLength, UINT16 initial) { UINT64 sum = CalculateOnesComplement(ptr, totalLength, initial, TRUE); fold64(sum); return (UINT16)~sum; } /* *---------------------------------------------------------------------------- * CopyAndCalculateOnesComplement -- * * Given the start address and buffer length, calculate the 1's complement * at same time, copt the data from src to dst. * * This routine can be used when multiple buffers are used for a packets. * * PLEASE NOTE, even though the last parameter is UINT64, but the assumption * is it will not overflowed after adding the extra data. * ------------------------------------------------ * * Result: * As name indicate, the final data is not 1's complemnent *---------------------------------------------------------------------------- */ UINT64 CopyAndCalculateOnesComplement(UINT8 *dst, UINT8 *src, UINT16 length, UINT64 initial, BOOLEAN isEvenStart) { UINT64 sum =0, val; UINT64 *src64, *dst64; union { UINT32 val; UINT8 b8[4]; } tmp; src64 = (UINT64 *)src; dst64 = (UINT64 *)dst; while (length > 7) { val = *src64; *dst64 = val; sum += (val >> 32) + (val & 0xffffffff); src64++; dst64++; length -= 8; } if (length > 3) { val = *(UINT32 *)src64; *(UINT32 *)dst64 = (UINT32)val; sum += (UINT32)val; dst64 = (UINT64 *)((UINT8 *)dst64 + 4); src64 = (UINT64 *)((UINT8 *)src64 + 4); length -= 4; } src = (UINT8 *)src64; dst = (UINT8 *)dst64; tmp.val = 0; switch (length) { case 3: dst[2] = src[2]; tmp.b8[2] = src[2]; case 2: dst[1] = src[1]; tmp.b8[1] = src[1]; case 1: dst[0] = src[0]; tmp.b8[0] = src[0]; sum += tmp.val; } sum = (isEvenStart ? sum : swap64(sum)) + initial; return sum; } /* *---------------------------------------------------------------------------- * CopyAndCalculateChecksum -- * * This is similar to CalculateChecksum, except it will also copy data to * destination address. *---------------------------------------------------------------------------- */ UINT16 CopyAndCalculateChecksum(UINT8 *dst, UINT8 *src, UINT16 length, UINT16 initial) { UINT64 sum = CopyAndCalculateOnesComplement(dst, src, length, initial, TRUE); fold64(sum); return (UINT16)~sum; } /* *---------------------------------------------------------------------------- * IPChecksum -- * * Give IP header, calculate the IP checksum. * We assume IP checksum field is initialized properly * * Input Pramater: * ipHdr: IP header start point * length: IP header length (potentially include IP options) * initial: same as CalculateChecksum * * Result: * The result is already 1's complement, so can be assigned * to checksum field directly *---------------------------------------------------------------------------- */ UINT16 IPChecksum(UINT8 *ipHdr, UINT16 length, UINT16 initial) { UINT32 sum = initial; UINT16 *ptr = (UINT16 *)ipHdr; ASSERT((length & 0x3) == 0); while (length > 1) { sum += ptr[0]; ptr++; length -= 2; } fold32(sum); return (UINT16)~sum; } /* *---------------------------------------------------------------------------- * IPPseudoChecksum -- * * Give src and dst IP address, protocol value and total * upper layer length(not include IP header, but include * upller layer protocol header, for example it include * TCP header for TCP checksum), calculate the pseudo * checksum, please note this checksum is just 1's complement * addition. * * Input Parameter: * src: please note it is in network byte order * dst: same as src * protocol: protocol value in IP header * totalLength: total length of upper layer data including * header. * * Result: * * This value should be put in TCP checksum field before * calculating TCP checksum using CalculateChecksum with * initial value of 0. *---------------------------------------------------------------------------- */ UINT16 IPPseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, UINT16 totalLength) { UINT32 sum = (UINT32)htons(totalLength) + htons(protocol); sum += (*src >> 16) + (*src & 0xffff); sum += (*dst >> 16) + (*dst & 0xffff); fold32(sum); return (UINT16)sum; } /* *---------------------------------------------------------------------------- * IPv6PseudoChecksum -- * * Given IPv6 src and dst address, upper layer protocol and total * upper layer protocol data length including upper layer header * part, calculate the pseudo checksum for upper layer protocol * checksum. * * please note this checksum is just 1's complement addition. * * Input Parameter: * src: src IPv6 address in network byte order * dst: dst IPv6 address. * protocol: upper layer protocol * totalLength: total length of upper layer data. Please note this is * in host byte order. * * Result: * * Place in upper layer checksum field before calculate upper layer * checksum. *---------------------------------------------------------------------------- */ UINT16 IPv6PseudoChecksum(UINT32 *src, UINT32 *dst, UINT8 protocol, UINT16 totalLength) { UINT64 sum = (UINT32)htons(totalLength) + htons(protocol); sum += (UINT64)src[0] + src[1] + src[2] + src[3]; sum += (UINT64)dst[0] + dst[1] + dst[2] + dst[3]; fold64(sum); return (UINT16)sum; } /* *---------------------------------------------------------------------------- * ChecksumUpdate32 -- * * Given old checksum value (as it is in checksum field), * prev value of the relevant field in network byte order * new value of the relevant field in the network byte order * calculate the new checksum. * Please check relevant RFC for reference. * * Input Pramater: * oldSum: old checksum value in checksum field * prev: previous value of relevant 32 bit feld in network * byte order. * new: new value of the relevant 32 bit field in network * byte order. * * Result: * new checksum value to be placed in the checksum field. *---------------------------------------------------------------------------- */ UINT16 ChecksumUpdate32(UINT16 oldSum, UINT32 prev, UINT32 newValue) { UINT32 sum = ~prev; sum = (sum >> 16) + (sum & 0xffff); sum += (newValue >> 16) + (newValue & 0xffff); sum += (UINT16)~oldSum; fold32(sum); return (UINT16)~sum; } /* *---------------------------------------------------------------------------- * ChecksumUpdate16 -- * * Given old checksum value (as it is in checksum field), * prev value of the relevant field in network byte order * new value of the relevant field in the network byte order * calculate the new checksum. * Please check relevant RFC for reference. * * Input Pramater: * oldSum: old checksum value in checksum field * prev: previous value of relevant 32 bit feld in network * byte order. * new: new value of the relevant 32 bit field in network * byte order. * * Result: * new checksum value to be placed in the checksum field. *---------------------------------------------------------------------------- */ UINT16 ChecksumUpdate16(UINT16 oldSum, UINT16 prev, UINT16 newValue) { UINT32 sum = (UINT16)~oldSum; sum += (UINT32)((UINT16)~prev) + newValue; fold32(sum); return (UINT16)~sum; } /* *---------------------------------------------------------------------------- * CalculateChecksumNB -- * * Calculates checksum over a length of bytes contained in an NB. * * nb : NB which contains the packet bytes. * csumDataLen : Length of bytes to be checksummed. * offset : offset to the first bytes of the data stream to be * checksumed. * * Result: * return 0, if there is a failure. *---------------------------------------------------------------------------- */ UINT16 CalculateChecksumNB(const PNET_BUFFER nb, UINT16 csumDataLen, UINT32 offset) { ULONG mdlLen; UINT16 csLen; PUCHAR src; UINT64 csum = 0; PMDL currentMdl; ULONG firstMdlLen; /* Running count of bytes in remainder of the MDLs including current. */ ULONG packetLen; BOOLEAN swapEnd = 1 & csumDataLen; if ((nb == NULL) || (csumDataLen == 0) || (offset >= NET_BUFFER_DATA_LENGTH(nb)) || (offset + csumDataLen > NET_BUFFER_DATA_LENGTH(nb))) { OVS_LOG_ERROR("Invalid parameters - csum length %u, offset %u," "pkt%s len %u", csumDataLen, offset, nb? "":"(null)", nb? NET_BUFFER_DATA_LENGTH(nb) : 0); return 0; } currentMdl = NET_BUFFER_CURRENT_MDL(nb); packetLen = NET_BUFFER_DATA_LENGTH(nb); firstMdlLen = MmGetMdlByteCount(currentMdl) - NET_BUFFER_CURRENT_MDL_OFFSET(nb); firstMdlLen = MIN(firstMdlLen, packetLen); if (offset < firstMdlLen) { src = (PUCHAR) MmGetSystemAddressForMdlSafe(currentMdl, LowPagePriority); if (!src) { return 0; } src += (NET_BUFFER_CURRENT_MDL_OFFSET(nb) + offset); mdlLen = firstMdlLen - offset; packetLen -= firstMdlLen; ASSERT((INT)packetLen >= 0); } else { offset -= firstMdlLen; packetLen -= firstMdlLen; ASSERT((INT)packetLen >= 0); currentMdl = NDIS_MDL_LINKAGE(currentMdl); mdlLen = MmGetMdlByteCount(currentMdl); mdlLen = MIN(mdlLen, packetLen); while (offset >= mdlLen) { offset -= mdlLen; packetLen -= mdlLen; ASSERT((INT)packetLen >= 0); currentMdl = NDIS_MDL_LINKAGE(currentMdl); mdlLen = MmGetMdlByteCount(currentMdl); mdlLen = MIN(mdlLen, packetLen); } src = (PUCHAR)MmGetSystemAddressForMdlSafe(currentMdl, LowPagePriority); if (!src) { return 0; } src += offset; mdlLen -= offset; } while (csumDataLen && (currentMdl != NULL)) { ASSERT(mdlLen < 65536); csLen = MIN((UINT16) mdlLen, csumDataLen); csum = CalculateOnesComplement(src, csLen, csum, !(1 & csumDataLen)); fold64(csum); csumDataLen -= csLen; currentMdl = NDIS_MDL_LINKAGE(currentMdl); if (csumDataLen && currentMdl) { src = MmGetSystemAddressForMdlSafe(currentMdl, LowPagePriority); if (!src) { return 0; } mdlLen = MmGetMdlByteCount(currentMdl); mdlLen = MIN(mdlLen, packetLen); /* packetLen does not include the current MDL from here on. */ packetLen -= mdlLen; ASSERT((INT)packetLen >= 0); } } fold64(csum); ASSERT(csumDataLen == 0); ASSERT((csum & ~0xffff) == 0); csum = (UINT16)~csum; if (swapEnd) { return _byteswap_ushort((UINT16)csum); } return (UINT16)csum; } /* * -------------------------------------------------------------------------- * OvsValidateIPChecksum * -------------------------------------------------------------------------- */ NDIS_STATUS OvsValidateIPChecksum(PNET_BUFFER_LIST curNbl, POVS_PACKET_HDR_INFO hdrInfo) { NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; uint16_t checksum, hdrChecksum; struct IPHdr ip_storage; const IPHdr *ipHdr; if (!hdrInfo->isIPv4) { return NDIS_STATUS_SUCCESS; } /* First check if NIC has indicated checksum failure. */ csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); if (csumInfo.Receive.IpChecksumFailed) { return NDIS_STATUS_FAILURE; } /* Next, check if the NIC did not validate the RX checksum. */ if (!csumInfo.Receive.IpChecksumSucceeded) { ipHdr = OvsGetIp(curNbl, hdrInfo->l3Offset, &ip_storage); if (ipHdr) { ip_storage = *ipHdr; hdrChecksum = ipHdr->check; ip_storage.check = 0; checksum = IPChecksum((uint8 *)&ip_storage, ipHdr->ihl * 4, 0); if (checksum != hdrChecksum) { return NDIS_STATUS_FAILURE; } } } return NDIS_STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsValidateUDPChecksum *---------------------------------------------------------------------------- */ NDIS_STATUS OvsValidateUDPChecksum(PNET_BUFFER_LIST curNbl, BOOLEAN udpCsumZero) { NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); if (udpCsumZero) { /* Zero is valid checksum. */ csumInfo.Receive.UdpChecksumFailed = 0; NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = csumInfo.Value; return NDIS_STATUS_SUCCESS; } /* First check if NIC has indicated UDP checksum failure. */ if (csumInfo.Receive.UdpChecksumFailed) { return NDIS_STATUS_INVALID_PACKET; } return NDIS_STATUS_SUCCESS; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Event.h0000644000000000000000000000013112652645507021704 xustar0030 mtime=1454066503.402754588 29 atime=1456592667.30709024 30 ctime=1456594660.189288653 openvswitch-2.5.0/datapath-windows/ovsext/Event.h0000664000175000017500000000333712652645507023403 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __EVENT_H_ #define __EVENT_H_ 1 typedef struct _OVS_EVENT_QUEUE_ELEM { LIST_ENTRY link; OVS_EVENT_ENTRY event; } OVS_EVENT_QUEUE_ELEM, *POVS_EVENT_QUEUE_ELEM; typedef struct _OVS_EVENT_QUEUE { LIST_ENTRY queueLink; LIST_ENTRY elemList; UINT32 mask; UINT16 numElems; BOOLEAN pollAll; PIRP pendingIrp; PVOID instance; } OVS_EVENT_QUEUE, *POVS_EVENT_QUEUE; NTSTATUS OvsInitEventQueue(VOID); VOID OvsCleanupEventQueue(VOID); struct _OVS_OPEN_INSTANCE; VOID OvsCleanupEvent(struct _OVS_OPEN_INSTANCE *instance); VOID OvsPostEvent(POVS_EVENT_ENTRY event); NTSTATUS OvsSubscribeEventIoctl(PFILE_OBJECT fileObject, PVOID inputBuffer, UINT32 inputLength); NTSTATUS OvsPollEventIoctl(PFILE_OBJECT fileObject, PVOID inputBuffer, UINT32 inputLength, PVOID outputBuffer, UINT32 outputLength, UINT32 *replyLen); NTSTATUS OvsWaitEventIoctl(PIRP irp, PFILE_OBJECT fileObject, PVOID inputBuffer, UINT32 inputLength); NTSTATUS OvsRemoveEventEntry(PVOID instance, POVS_EVENT_ENTRY entry); #endif /* __EVENT_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Util.c0000644000000000000000000000013212631676262021533 xustar0030 mtime=1449622706.986439891 30 atime=1456592667.315090569 30 ctime=1456594660.225290164 openvswitch-2.5.0/datapath-windows/ovsext/Util.c0000664000175000017500000000553412631676262023232 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_OTHERS #include "Debug.h" extern NDIS_HANDLE gOvsExtDriverHandle; VOID* OvsAllocateMemoryWithTag(size_t size, ULONG tag) { OVS_VERIFY_IRQL_LE(DISPATCH_LEVEL); return NdisAllocateMemoryWithTagPriority(gOvsExtDriverHandle, (UINT32)size, tag, NormalPoolPriority); } VOID OvsFreeMemoryWithTag(VOID *ptr, ULONG tag) { ASSERT(ptr); NdisFreeMemoryWithTagPriority(gOvsExtDriverHandle, ptr, tag); } VOID * OvsAllocateMemory(size_t size) { OVS_VERIFY_IRQL_LE(DISPATCH_LEVEL); return NdisAllocateMemoryWithTagPriority(gOvsExtDriverHandle, (UINT32)size, OVS_MEMORY_TAG, NormalPoolPriority); } VOID * OvsAllocateAlignedMemory(size_t size, UINT16 align) { OVS_VERIFY_IRQL_LE(DISPATCH_LEVEL); ASSERT((align == 8) || (align == 16)); if ((align == 8) || (align == 16)) { /* * XXX: NdisAllocateMemory*() functions don't talk anything about * alignment. Hence using ExAllocatePool*(); */ return (VOID *)ExAllocatePoolWithTagPriority(NonPagedPool, size, OVS_MEMORY_TAG, NormalPoolPriority); } /* Invalid user input. */ return NULL; } VOID OvsFreeMemory(VOID *ptr) { ASSERT(ptr); NdisFreeMemoryWithTagPriority(gOvsExtDriverHandle, ptr, OVS_MEMORY_TAG); } VOID OvsFreeAlignedMemory(VOID *ptr) { ASSERT(ptr); ExFreePoolWithTag(ptr, OVS_MEMORY_TAG); } VOID OvsAppendList(PLIST_ENTRY dst, PLIST_ENTRY src) { PLIST_ENTRY srcFirst, srcLast, dstLast; if (IsListEmpty(src)) { return; } srcFirst = src->Flink; srcLast = src->Blink; dstLast = dst->Blink; dstLast->Flink = srcFirst; srcFirst->Blink = dstLast; srcLast->Flink = dst; dst->Blink = srcLast; src->Flink = src; src->Blink = src; } BOOLEAN OvsCompareString(PVOID string1, PVOID string2) { /* * Not a super-efficient string compare since we walk over the strings * twice: to initialize, and then to do the comparison. */ STRING str1, str2; RtlInitString(&str1, string1); RtlInitString(&str2, string2); return RtlEqualString(&str1, &str2, FALSE); } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Vxlan.h0000644000000000000000000000013212664352753021715 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594660.229290333 openvswitch-2.5.0/datapath-windows/ovsext/Vxlan.h0000664000175000017500000000535512664352753023415 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __VXLAN_H_ #define __VXLAN_H_ 1 #include "NetProto.h" typedef struct _OVS_VXLAN_VPORT { UINT16 dstPort; UINT64 inPkts; UINT64 outPkts; UINT64 slowInPkts; UINT64 slowOutPkts; UINT64 filterID; UINT64 ipId; /* * To be filled */ } OVS_VXLAN_VPORT, *POVS_VXLAN_VPORT; /* VXLAN header. */ typedef struct VXLANHdr { /* Flags. */ UINT32 flags1:2; /* Packet needs replication to multicast group (used for multicast proxy). */ UINT32 locallyReplicate:1; /* Instance ID flag, must be set to 1. */ UINT32 instanceID:1; /* Flags. */ UINT32 flags2:4; /* Reserved. */ UINT32 reserved1:24; /* VXLAN ID. */ UINT32 vxlanID:24; /* Reserved. */ UINT32 reserved2:8; } VXLANHdr; NTSTATUS OvsInitVxlanTunnel(PIRP irp, POVS_VPORT_ENTRY vport, UINT16 udpDestPort, PFNTunnelVportPendingOp callback, PVOID tunnelContext); NTSTATUS OvsCleanupVxlanTunnel(PIRP irp, POVS_VPORT_ENTRY vport, PFNTunnelVportPendingOp callback, PVOID tunnelContext); NDIS_STATUS OvsSlowPathDecapVxlan(const PNET_BUFFER_LIST packet, OvsIPv4TunnelKey *tunnelKey); NDIS_STATUS OvsEncapVxlan(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, PNET_BUFFER_LIST *newNbl); NDIS_STATUS OvsDecapVxlan(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, PNET_BUFFER_LIST *newNbl); static __inline UINT32 OvsGetVxlanTunHdrSize(VOID) { /* XXX: Can L2 include VLAN at all? */ return sizeof (EthHdr) + sizeof (IPHdr) + sizeof (UDPHdr) + sizeof (VXLANHdr); } #define VXLAN_UDP_PORT 4789 #define VXLAN_UDP_PORT_NBO 0xB512 #endif /* __VXLAN_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Ethernet.h0000644000000000000000000000013212664352753022403 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.185288484 openvswitch-2.5.0/datapath-windows/ovsext/Ethernet.h0000664000175000017500000003643012664352753024101 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef __ETHERNET_H_ #define __ETHERNET_H_ 1 #define ETH_LADRF_LEN 2 #define ETH_ADDR_LENGTH 6 typedef UINT8 Eth_Address[ETH_ADDR_LENGTH]; #define ETH_ADDR_FMT_STR "%02x:%02x:%02x:%02x:%02x:%02x" #define ETH_ADDR_FMT_ARGS(a) ((UINT8 *)a)[0], ((UINT8 *)a)[1], ((UINT8 *)a)[2], \ ((UINT8 *)a)[3], ((UINT8 *)a)[4], ((UINT8 *)a)[5] #define ETH_MAX_EXACT_MULTICAST_ADDRS 32 typedef enum Eth_RxMode { ETH_FILTER_UNICAST = 0x0001, /* pass unicast (directed) frames */ ETH_FILTER_MULTICAST = 0x0002, /* pass some multicast frames */ ETH_FILTER_ALLMULTI = 0x0004, /* pass *all* multicast frames */ ETH_FILTER_BROADCAST = 0x0008, /* pass broadcast frames */ ETH_FILTER_PROMISC = 0x0010, /* pass all frames (ie no filter) */ ETH_FILTER_USE_LADRF = 0x0020, /* use the LADRF for multicast filtering */ ETH_FILTER_SINK = 0x10000 /* pass not-matched unicast frames */ } Eth_RxMode; /* filter flags printf helpers */ #define ETH_FILTER_FLAG_FMT_STR "%s%s%s%s%s%s%s" #define ETH_FILTER_FLAG_FMT_ARGS(f) (f) & ETH_FILTER_UNICAST ? " UNICAST" : "", \ (f) & ETH_FILTER_MULTICAST ? " MULTICAST" : "", \ (f) & ETH_FILTER_ALLMULTI ? " ALLMULTI" : "", \ (f) & ETH_FILTER_BROADCAST ? " BROADCAST" : "", \ (f) & ETH_FILTER_PROMISC ? " PROMISC" : "", \ (f) & ETH_FILTER_USE_LADRF ? " USE_LADRF" : "", \ (f) & ETH_FILTER_SINK ? " SINK" : "" /* Ethernet header type */ typedef enum { ETH_HEADER_TYPE_DIX, ETH_HEADER_TYPE_802_1PQ, ETH_HEADER_TYPE_802_3, ETH_HEADER_TYPE_802_1PQ_802_3, } Eth_HdrType; /* DIX type fields we care about */ typedef enum { ETH_TYPE_IPV4 = 0x0800, ETH_TYPE_IPV6 = 0x86DD, ETH_TYPE_ARP = 0x0806, ETH_TYPE_RARP = 0x8035, ETH_TYPE_LLDP = 0x88CC, ETH_TYPE_CDP = 0x2000, ETH_TYPE_802_1PQ = 0x8100, // not really a DIX type, but used as such ETH_TYPE_LLC = 0xFFFF, // 0xFFFF is IANA reserved, used to mark LLC } Eth_DixType; typedef enum { ETH_TYPE_IPV4_NBO = 0x0008, ETH_TYPE_IPV6_NBO = 0xDD86, ETH_TYPE_ARP_NBO = 0x0608, ETH_TYPE_RARP_NBO = 0x3580, ETH_TYPE_LLDP_NBO = 0xCC88, ETH_TYPE_CDP_NBO = 0x0020, ETH_TYPE_AKIMBI_NBO = 0xDE88, ETH_TYPE_802_1PQ_NBO = 0x0081, // not really a DIX type, but used as such } Eth_DixTypeNBO; /* low two bits of the LLC control byte */ typedef enum { ETH_LLC_CONTROL_IFRAME = 0x0, // both 0x0 and 0x2, only low bit of 0 needed ETH_LLC_CONTROL_SFRAME = 0x1, ETH_LLC_CONTROL_UFRAME = 0x3, } Eth_LLCControlBits; #define ETH_LLC_CONTROL_UFRAME_MASK (0x3) typedef struct Eth_DIX { UINT16 typeNBO; // indicates the higher level protocol } Eth_DIX; /* * LLC header come in two varieties: 8 bit control and 16 bit control. * when the lower two bits of the first byte's control are '11', this * indicated the 8 bit control field. */ typedef struct Eth_LLC8 { UINT8 dsap; UINT8 ssap; UINT8 control; } Eth_LLC8; typedef struct Eth_LLC16 { UINT8 dsap; UINT8 ssap; UINT16 control; } Eth_LLC16; typedef struct Eth_SNAP { UINT8 snapOrg[3]; Eth_DIX snapType; } Eth_SNAP; typedef struct Eth_802_3 { UINT16 lenNBO; // length of the frame Eth_LLC8 llc; // LLC header Eth_SNAP snap; // SNAP header } Eth_802_3; // 802.1p QOS/priority tags enum { ETH_802_1_P_BEST_EFFORT = 0, ETH_802_1_P_BACKGROUND = 1, ETH_802_1_P_EXCELLENT_EFFORT = 2, ETH_802_1_P_CRITICAL_APPS = 3, ETH_802_1_P_VIDEO = 4, ETH_802_1_P_VOICE = 5, ETH_802_1_P_INTERNETWORK_CONROL = 6, ETH_802_1_P_NETWORK_CONTROL = 7 }; typedef struct Eth_802_1pq_Tag { UINT16 typeNBO; // always ETH_TYPE_802_1PQ UINT16 vidHi:4, // 802.1q vlan ID high nibble canonical:1, // bit order? (should always be 0) priority:3, // 802.1p priority tag vidLo:8; // 802.1q vlan ID low byte } Eth_802_1pq_Tag; typedef struct Eth_802_1pq { Eth_802_1pq_Tag tag; // VLAN/QOS tag union { Eth_DIX dix; // DIX header follows Eth_802_3 e802_3; // or 802.3 header follows }; } Eth_802_1pq; typedef struct Eth_Header { Eth_Address dst; // all types of ethernet frame have dst first Eth_Address src; // and the src next (at least all the ones we'll see) union { Eth_DIX dix; // followed by a DIX header... Eth_802_3 e802_3; // ...or an 802.3 header Eth_802_1pq e802_1pq; // ...or an 802.1[pq] tag and a header }; } Eth_Header; #define ETH_BROADCAST_ADDRESS { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff } static Eth_Address netEthBroadcastAddr = ETH_BROADCAST_ADDRESS; /* * simple predicate for 1536 boundary. * the parameter is a network ordered UINT16, which is compared to 0x06, * testing for "length" values greater than or equal to 0x0600 (1536) */ #define ETH_TYPENOT8023(x) (((x) & 0xff) >= 0x06) /* * header length macros * * first two are typical: ETH_HEADER_LEN_DIX, ETH_HEADER_LEN_802_1PQ * last two are suspicious, due to 802.3 incompleteness */ #define ETH_HEADER_LEN_DIX (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(Eth_DIX)) #define ETH_HEADER_LEN_802_1PQ (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(Eth_802_1pq_Tag) + \ sizeof(Eth_DIX)) #define ETH_HEADER_LEN_802_2_LLC (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(UINT16) + \ sizeof(Eth_LLC8)) #define ETH_HEADER_LEN_802_2_LLC16 (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(UINT16) + \ sizeof(Eth_LLC16)) #define ETH_HEADER_LEN_802_3 (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(Eth_802_3)) #define ETH_HEADER_LEN_802_1PQ_LLC (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(Eth_802_1pq_Tag) + \ sizeof(UINT16) + \ sizeof(Eth_LLC8)) #define ETH_HEADER_LEN_802_1PQ_LLC16 (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(Eth_802_1pq_Tag) + \ sizeof(UINT16) + \ sizeof(Eth_LLC16)) #define ETH_HEADER_LEN_802_1PQ_802_3 (sizeof(Eth_Address) + \ sizeof(Eth_Address) + \ sizeof(Eth_802_1pq_Tag) + \ sizeof(Eth_802_3)) #define ETH_MIN_HEADER_LEN (ETH_HEADER_LEN_DIX) #define ETH_MAX_HEADER_LEN (ETH_HEADER_LEN_802_1PQ_802_3) #define ETH_MIN_FRAME_LEN 60 #define ETH_MAX_STD_MTU 1500 #define ETH_MAX_STD_FRAMELEN (ETH_MAX_STD_MTU + ETH_MAX_HEADER_LEN) #define ETH_MAX_JUMBO_MTU 9000 #define ETH_MAX_JUMBO_FRAMELEN (ETH_MAX_JUMBO_MTU + ETH_MAX_HEADER_LEN) #define ETH_DEFAULT_MTU 1500 #define ETH_FCS_LEN 4 #define ETH_VLAN_LEN sizeof(Eth_802_1pq_Tag) /* *---------------------------------------------------------------------------- * Do the two ethernet addresses match? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsAddrMatch(const Eth_Address addr1, const Eth_Address addr2) { return !memcmp(addr1, addr2, ETH_ADDR_LENGTH); } /* *---------------------------------------------------------------------------- * Is the address the broadcast address? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsBroadcastAddr(const Eth_Address addr) { return Eth_IsAddrMatch(addr, netEthBroadcastAddr); } /* *---------------------------------------------------------------------------- * Is the address a unicast address? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsUnicastAddr(const Eth_Address addr) { // broadcast and multicast frames always have the low bit set in byte 0 return !(((CHAR *)addr)[0] & 0x1); } /* *---------------------------------------------------------------------------- * Is the address the all-zeros address? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsNullAddr(const Eth_Address addr) { return ((addr[0] | addr[1] | addr[2] | addr[3] | addr[4] | addr[5]) == 0); } /* *---------------------------------------------------------------------------- * * Eth_HeaderType -- * return an Eth_HdrType depending on the eth header * contents. will not work in all cases, especially since it * requres ETH_HEADER_LEN_802_1PQ bytes to determine the type * * HeaderType isn't sufficient to determine the length of * the eth header. for 802.3 header, its not clear without * examination, whether a SNAP is included * * returned type: * * ETH_HEADER_TYPE_DIX: typical 14 byte eth header * ETH_HEADER_TYPE_802_1PQ: DIX+vlan tagging * ETH_HEADER_TYPE_802_3: 802.3 eth header * ETH_HEADER_TYPE_802_1PQ_802_3: 802.3 + vlan tag * * the test for DIX was moved from a 1500 boundary to a 1536 * boundary, since the vmxnet2 MTU was updated to 1514. when * W2K8 attempted to send LLC frames, these were interpreted * as DIX frames instead of the correct 802.3 type * * these links may help if they're valid: * * http://standards.ieee.org/regauth/ethertype/type-tut.html * http://standards.ieee.org/regauth/ethertype/type-pub.html * * Results: * Eth_HdrType value * *---------------------------------------------------------------------------- */ static __inline Eth_HdrType Eth_HeaderType(const Eth_Header *eh) { /* * we use 1536 (IEEE 802.3-std mentions 1536, but iana indicates * type of 0-0x5dc are 802.3) instead of some #def symbol to prevent * inadvertant reuse of the same macro for buffer size decls. */ if (ETH_TYPENOT8023(eh->dix.typeNBO)) { if (eh->dix.typeNBO != ETH_TYPE_802_1PQ_NBO) { /* typical case */ return ETH_HEADER_TYPE_DIX; } /* some type of 802.1pq tagged frame */ if (ETH_TYPENOT8023(eh->e802_1pq.dix.typeNBO)) { /* vlan tagging with dix style type */ return ETH_HEADER_TYPE_802_1PQ; } /* vlan tagging with 802.3 header */ return ETH_HEADER_TYPE_802_1PQ_802_3; } /* assume 802.3 */ return ETH_HEADER_TYPE_802_3; } /* *---------------------------------------------------------------------------- * * Eth_EncapsulatedPktType -- * Get the encapsulated (layer 3) frame type. * for LLC frames without SNAP, we don't have * an encapsulated type, and return ETH_TYPE_LLC. * * IANA reserves 0xFFFF, which we reuse to indicate * ETH_TYPE_LLC. * * Results: * NBO frame type. * *---------------------------------------------------------------------------- */ static __inline UINT16 Eth_EncapsulatedPktType(const Eth_Header *eh) { Eth_HdrType type = Eth_HeaderType(eh); switch (type) { case ETH_HEADER_TYPE_DIX: return eh->dix.typeNBO; case ETH_HEADER_TYPE_802_1PQ: return eh->e802_1pq.dix.typeNBO; case ETH_HEADER_TYPE_802_3: /* * Documentation describes SNAP headers as having ONLY * 0x03 as the control fields, not just the lower two bits * This prevents the use of Eth_IsLLCControlUFormat. */ if ((eh->e802_3.llc.dsap == 0xaa) && (eh->e802_3.llc.ssap == 0xaa) && (eh->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME)) { return eh->e802_3.snap.snapType.typeNBO; } else { // LLC, no snap header, then no type return ETH_TYPE_LLC; } case ETH_HEADER_TYPE_802_1PQ_802_3: if ((eh->e802_1pq.e802_3.llc.dsap == 0xaa) && (eh->e802_1pq.e802_3.llc.ssap == 0xaa) && (eh->e802_1pq.e802_3.llc.control == ETH_LLC_CONTROL_UFRAME)) { return eh->e802_1pq.e802_3.snap.snapType.typeNBO; } else { // tagged LLC, no snap header, then no type return ETH_TYPE_LLC; } } ASSERT(FALSE); return 0; } /* *---------------------------------------------------------------------------- * Is the frame of the requested protocol type or is it an 802.1[pq] * encapsulation of such a frame? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsDixType(const Eth_Header *eh, const Eth_DixTypeNBO type) { return Eth_EncapsulatedPktType(eh) == type; } /* *---------------------------------------------------------------------------- * Is the frame an IPV4 frame? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsIPV4(const Eth_Header *eh) { return Eth_IsDixType(eh, ETH_TYPE_IPV4_NBO); } /* *---------------------------------------------------------------------------- * Is the frame an IPV6 frame? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsIPV6(const Eth_Header *eh) { return Eth_IsDixType(eh, ETH_TYPE_IPV6_NBO); } /* *---------------------------------------------------------------------------- * Is the frame an ARP frame? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsARP(const Eth_Header *eh) { return Eth_IsDixType(eh, ETH_TYPE_ARP_NBO); } /* *---------------------------------------------------------------------------- * Does the frame contain an 802.1[pq] tag? *---------------------------------------------------------------------------- */ static __inline BOOLEAN Eth_IsFrameTagged(const Eth_Header *eh) { return (eh->dix.typeNBO == ETH_TYPE_802_1PQ_NBO); } #endif /* __ETHERNET_H_ */ openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Stt.c0000644000000000000000000000013212664352753021372 xustar0030 mtime=1456592363.434620672 30 atime=1456592368.174815358 30 ctime=1456594660.213289661 openvswitch-2.5.0/datapath-windows/ovsext/Stt.c0000664000175000017500000006726612664352753023103 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2015 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "Atomic.h" #include "Checksum.h" #include "Flow.h" #include "IpHelper.h" #include "NetProto.h" #include "PacketIO.h" #include "PacketParser.h" #include "Stt.h" #include "Switch.h" #include "User.h" #include "Util.h" #include "Vport.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_STT #include "Debug.h" #include "Jhash.h" KSTART_ROUTINE OvsSttDefragCleaner; static PLIST_ENTRY OvsSttPktFragHash; static NDIS_SPIN_LOCK OvsSttSpinLock; static OVS_STT_THREAD_CTX sttDefragThreadCtx; static NDIS_STATUS OvsDoEncapStt(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, const OvsIPv4TunnelKey *tunKey, const POVS_FWD_INFO fwdInfo, POVS_PACKET_HDR_INFO layers, POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST *newNbl); /* * -------------------------------------------------------------------------- * OvsInitSttTunnel -- * Initialize STT tunnel module. * -------------------------------------------------------------------------- */ NTSTATUS OvsInitSttTunnel(POVS_VPORT_ENTRY vport, UINT16 tcpDestPort) { POVS_STT_VPORT sttPort; sttPort = (POVS_STT_VPORT) OvsAllocateMemoryWithTag(sizeof(*sttPort), OVS_STT_POOL_TAG); if (!sttPort) { OVS_LOG_ERROR("Insufficient memory, can't allocate STT_VPORT"); return STATUS_INSUFFICIENT_RESOURCES; } RtlZeroMemory(sttPort, sizeof(*sttPort)); sttPort->dstPort = tcpDestPort; vport->priv = (PVOID) sttPort; return STATUS_SUCCESS; } /* * -------------------------------------------------------------------------- * OvsCleanupSttTunnel -- * Cleanup STT Tunnel module. * -------------------------------------------------------------------------- */ void OvsCleanupSttTunnel(POVS_VPORT_ENTRY vport) { if (vport->ovsType != OVS_VPORT_TYPE_STT || vport->priv == NULL) { return; } OvsFreeMemoryWithTag(vport->priv, OVS_STT_POOL_TAG); vport->priv = NULL; } /* * -------------------------------------------------------------------------- * OvsEncapStt -- * Encapsulates a packet with an STT header. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsEncapStt(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, POVS_SWITCH_CONTEXT switchContext, POVS_PACKET_HDR_INFO layers, PNET_BUFFER_LIST *newNbl) { OVS_FWD_INFO fwdInfo; NDIS_STATUS status; UNREFERENCED_PARAMETER(switchContext); status = OvsLookupIPFwdInfo(tunKey->dst, &fwdInfo); if (status != STATUS_SUCCESS) { OvsFwdIPHelperRequest(NULL, 0, tunKey, NULL, NULL, NULL); /* * XXX This case where the ARP table is not populated is * currently not handled */ return NDIS_STATUS_FAILURE; } status = OvsDoEncapStt(vport, curNbl, tunKey, &fwdInfo, layers, switchContext, newNbl); return status; } /* * -------------------------------------------------------------------------- * OvsDoEncapStt -- * Internal utility function which actually does the STT encap. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsDoEncapStt(POVS_VPORT_ENTRY vport, PNET_BUFFER_LIST curNbl, const OvsIPv4TunnelKey *tunKey, const POVS_FWD_INFO fwdInfo, POVS_PACKET_HDR_INFO layers, POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST *newNbl) { NDIS_STATUS status = NDIS_STATUS_SUCCESS; PMDL curMdl = NULL; PNET_BUFFER curNb; PUINT8 buf = NULL; EthHdr *outerEthHdr; IPHdr *outerIpHdr; TCPHdr *outerTcpHdr; SttHdr *sttHdr; UINT32 innerFrameLen, ipTotalLen; POVS_STT_VPORT vportStt; UINT32 headRoom = OvsGetSttTunHdrSize(); UINT32 tcpChksumLen; PUINT8 bufferStart; ULONG mss = 0; NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO lsoInfo; curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); /* Verify if inner checksum is verified */ BOOLEAN innerChecksumVerified = FALSE; BOOLEAN innerPartialChecksum = FALSE; if (layers->isTcp) { lsoInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpLargeSendNetBufferListInfo); switch (lsoInfo.Transmit.Type) { case NDIS_TCP_LARGE_SEND_OFFLOAD_V1_TYPE: mss = lsoInfo.LsoV1Transmit.MSS; break; case NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE: mss = lsoInfo.LsoV2Transmit.MSS; break; default: OVS_LOG_ERROR("Unknown LSO transmit type:%d", lsoInfo.Transmit.Type); } } vportStt = (POVS_STT_VPORT) GetOvsVportPriv(vport); ASSERT(vportStt); NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, headRoom, FALSE /*copy NblInfo*/); if (*newNbl == NULL) { OVS_LOG_ERROR("Unable to copy NBL"); return NDIS_STATUS_FAILURE; } curNbl = *newNbl; curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); curMdl = NET_BUFFER_CURRENT_MDL(curNb); /* NB Chain should be split before */ ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL); innerFrameLen = NET_BUFFER_DATA_LENGTH(curNb); bufferStart = (PUINT8)MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); bufferStart += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); if (layers->isIPv4) { IPHdr *ip = (IPHdr *)(bufferStart + layers->l3Offset); if (!ip->tot_len) { ip->tot_len = htons(innerFrameLen - sizeof(EthHdr)); } if (!ip->check) { ip->check = IPChecksum((UINT8 *)ip, ip->ihl * 4, 0); } } if (layers->isTcp) { if (mss) { innerPartialChecksum = TRUE; } else { if (!csumInfo.Transmit.TcpChecksum) { innerChecksumVerified = TRUE; } else { innerPartialChecksum = TRUE; } } } else if (layers->isUdp) { if(!csumInfo.Transmit.UdpChecksum) { innerChecksumVerified = TRUE; } else { innerPartialChecksum = TRUE; } } status = NdisRetreatNetBufferDataStart(curNb, headRoom, 0, NULL); if (status != NDIS_STATUS_SUCCESS) { ASSERT(!"Unable to NdisRetreatNetBufferDataStart(headroom)"); OVS_LOG_ERROR("Unable to NdisRetreatNetBufferDataStart(headroom)"); goto ret_error; } /* * Make sure that the headroom for the tunnel header is continguous in * memory. */ curMdl = NET_BUFFER_CURRENT_MDL(curNb); ASSERT((int) (MmGetMdlByteCount(curMdl) - NET_BUFFER_CURRENT_MDL_OFFSET(curNb)) >= (int) headRoom); buf = (PUINT8) MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); if (!buf) { ASSERT(!"MmGetSystemAddressForMdlSafe failed"); OVS_LOG_ERROR("MmGetSystemAddressForMdlSafe failed"); status = NDIS_STATUS_RESOURCES; goto ret_error; } buf += NET_BUFFER_CURRENT_MDL_OFFSET(curNb); outerEthHdr = (EthHdr *)buf; outerIpHdr = (IPHdr *) (outerEthHdr + 1); outerTcpHdr = (TCPHdr *) (outerIpHdr + 1); sttHdr = (SttHdr *) (outerTcpHdr + 1); /* L2 header */ ASSERT(((PCHAR)&fwdInfo->dstMacAddr + sizeof fwdInfo->dstMacAddr) == (PCHAR)&fwdInfo->srcMacAddr); NdisMoveMemory(outerEthHdr->Destination, fwdInfo->dstMacAddr, sizeof outerEthHdr->Destination + sizeof outerEthHdr->Source); outerEthHdr->Type = htons(ETH_TYPE_IPV4); /* L3 header */ outerIpHdr->ihl = sizeof(IPHdr) >> 2; outerIpHdr->version = IPPROTO_IPV4; outerIpHdr->tos = tunKey->tos; ipTotalLen = sizeof(IPHdr) + sizeof(TCPHdr) + STT_HDR_LEN + innerFrameLen; outerIpHdr->tot_len = htons(ipTotalLen); ASSERT(ipTotalLen < 65536); outerIpHdr->id = (uint16) atomic_add64(&vportStt->ipId, innerFrameLen); outerIpHdr->frag_off = (tunKey->flags & OVS_TNL_F_DONT_FRAGMENT) ? IP_DF_NBO : 0; outerIpHdr->ttl = tunKey->ttl? tunKey->ttl : 64; outerIpHdr->protocol = IPPROTO_TCP; outerIpHdr->check = 0; outerIpHdr->saddr = fwdInfo->srcIpAddr; outerIpHdr->daddr = tunKey->dst; /* L4 header */ RtlZeroMemory(outerTcpHdr, sizeof *outerTcpHdr); outerTcpHdr->source = htons(tunKey->flow_hash | 32768); outerTcpHdr->dest = htons(vportStt->dstPort); outerTcpHdr->seq = htonl((STT_HDR_LEN + innerFrameLen) << STT_SEQ_LEN_SHIFT); outerTcpHdr->ack_seq = htonl(atomic_inc64(&vportStt->ackNo)); outerTcpHdr->doff = sizeof(TCPHdr) >> 2; outerTcpHdr->psh = 1; outerTcpHdr->ack = 1; outerTcpHdr->window = (uint16) ~0; /* Calculate pseudo header chksum */ tcpChksumLen = sizeof(TCPHdr) + STT_HDR_LEN + innerFrameLen; ASSERT(tcpChksumLen < 65535); outerTcpHdr->check = IPPseudoChecksum(&fwdInfo->srcIpAddr,(uint32 *) &tunKey->dst, IPPROTO_TCP, (uint16) tcpChksumLen); sttHdr->version = 0; /* Set STT Header */ sttHdr->flags = 0; if (innerPartialChecksum) { sttHdr->flags |= STT_CSUM_PARTIAL; if (layers->isIPv4) { sttHdr->flags |= STT_PROTO_IPV4; } if (layers->isTcp) { sttHdr->flags |= STT_PROTO_TCP; } sttHdr->l4Offset = (UINT8) layers->l4Offset; sttHdr->mss = (UINT16) htons(mss); } else if (innerChecksumVerified) { sttHdr->flags = STT_CSUM_VERIFIED; sttHdr->l4Offset = 0; sttHdr->mss = 0; } sttHdr->reserved = 0; sttHdr->vlanTCI = 0; sttHdr->key = tunKey->tunnelId; /* Zero out stt padding */ *(uint16 *)(sttHdr + 1) = 0; /* Offload IP and TCP checksum */ ULONG tcpHeaderOffset = sizeof *outerEthHdr + outerIpHdr->ihl * 4; csumInfo.Value = 0; csumInfo.Transmit.IpHeaderChecksum = 1; csumInfo.Transmit.TcpChecksum = 1; csumInfo.Transmit.IsIPv4 = 1; csumInfo.Transmit.TcpHeaderOffset = tcpHeaderOffset; NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = csumInfo.Value; UINT32 encapMss = OvsGetExternalMtu(switchContext) - sizeof(IPHdr) - sizeof(TCPHdr); if (ipTotalLen > encapMss) { lsoInfo.Value = 0; lsoInfo.LsoV2Transmit.TcpHeaderOffset = tcpHeaderOffset; lsoInfo.LsoV2Transmit.MSS = encapMss; lsoInfo.LsoV2Transmit.Type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; lsoInfo.LsoV2Transmit.IPVersion = NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4; NET_BUFFER_LIST_INFO(curNbl, TcpLargeSendNetBufferListInfo) = lsoInfo.Value; } return STATUS_SUCCESS; ret_error: OvsCompleteNBL(switchContext, *newNbl, TRUE); *newNbl = NULL; return status; } /* *---------------------------------------------------------------------------- * OvsValidateTCPChecksum * Validate TCP checksum *---------------------------------------------------------------------------- */ static __inline NDIS_STATUS OvsValidateTCPChecksum(PNET_BUFFER_LIST curNbl, PNET_BUFFER curNb) { NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo); /* Check if NIC has indicated TCP checksum failure */ if (csumInfo.Receive.TcpChecksumFailed) { return NDIS_STATUS_INVALID_PACKET; } UINT16 checkSum; /* Check if TCP Checksum has been calculated by NIC */ if (csumInfo.Receive.TcpChecksumSucceeded) { return NDIS_STATUS_SUCCESS; } EthHdr *eth = (EthHdr *)NdisGetDataBuffer(curNb, sizeof(EthHdr), NULL, 1, 0); if (eth->Type == ntohs(NDIS_ETH_TYPE_IPV4)) { IPHdr *ip = (IPHdr *)((PCHAR)eth + sizeof *eth); UINT32 l4Payload = ntohs(ip->tot_len) - ip->ihl * 4; TCPHdr *tcp = (TCPHdr *)((PCHAR)ip + ip->ihl * 4); checkSum = tcp->check; tcp->check = 0; tcp->check = IPPseudoChecksum(&ip->saddr, &ip->daddr, IPPROTO_TCP, (UINT16)l4Payload); tcp->check = CalculateChecksumNB(curNb, (UINT16)(l4Payload), sizeof(EthHdr) + ip->ihl * 4); if (checkSum != tcp->check) { return NDIS_STATUS_INVALID_PACKET; } } else { OVS_LOG_ERROR("IPv6 on STT is not supported"); return NDIS_STATUS_INVALID_PACKET; } csumInfo.Receive.TcpChecksumSucceeded = 1; NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = csumInfo.Value; return NDIS_STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsInitSttDefragmentation * Initialize the components used by the stt lso defragmentation *---------------------------------------------------------------------------- */ NTSTATUS OvsInitSttDefragmentation() { NTSTATUS status; HANDLE threadHandle = NULL; /* Init the sync-lock */ NdisAllocateSpinLock(&OvsSttSpinLock); /* Init the Hash Buffer */ OvsSttPktFragHash = OvsAllocateMemoryWithTag(sizeof(LIST_ENTRY) * STT_HASH_TABLE_SIZE, OVS_STT_POOL_TAG); if (OvsSttPktFragHash == NULL) { NdisFreeSpinLock(&OvsSttSpinLock); return STATUS_INSUFFICIENT_RESOURCES; } for (int i = 0; i < STT_HASH_TABLE_SIZE; i++) { InitializeListHead(&OvsSttPktFragHash[i]); } /* Init Defrag Cleanup Thread */ KeInitializeEvent(&sttDefragThreadCtx.event, NotificationEvent, FALSE); status = PsCreateSystemThread(&threadHandle, SYNCHRONIZE, NULL, NULL, NULL, OvsSttDefragCleaner, &sttDefragThreadCtx); if (status != STATUS_SUCCESS) { OvsCleanupSttDefragmentation(); return status; } ObReferenceObjectByHandle(threadHandle, SYNCHRONIZE, NULL, KernelMode, &sttDefragThreadCtx.threadObject, NULL); ZwClose(threadHandle); threadHandle = NULL; return STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsCleanupSttDefragmentation * Cleanup memory and thread that were spawned for STT LSO defragmentation *---------------------------------------------------------------------------- */ VOID OvsCleanupSttDefragmentation(VOID) { NdisAcquireSpinLock(&OvsSttSpinLock); sttDefragThreadCtx.exit = 1; KeSetEvent(&sttDefragThreadCtx.event, 0, FALSE); NdisReleaseSpinLock(&OvsSttSpinLock); KeWaitForSingleObject(sttDefragThreadCtx.threadObject, Executive, KernelMode, FALSE, NULL); ObDereferenceObject(sttDefragThreadCtx.threadObject); if (OvsSttPktFragHash) { OvsFreeMemoryWithTag(OvsSttPktFragHash, OVS_STT_POOL_TAG); OvsSttPktFragHash = NULL; } NdisFreeSpinLock(&OvsSttSpinLock); } /* *---------------------------------------------------------------------------- * OvsSttDefragCleaner * Runs periodically and cleans up the buffer to remove expired segments *---------------------------------------------------------------------------- */ VOID OvsSttDefragCleaner(PVOID data) { POVS_STT_THREAD_CTX context = (POVS_STT_THREAD_CTX)data; PLIST_ENTRY link, next; POVS_STT_PKT_ENTRY entry; BOOLEAN success = TRUE; while (success) { NdisAcquireSpinLock(&OvsSttSpinLock); if (context->exit) { NdisReleaseSpinLock(&OvsSttSpinLock); break; } /* Set the timeout for the thread and cleanup */ UINT64 currentTime, threadSleepTimeout; NdisGetCurrentSystemTime((LARGE_INTEGER *)¤tTime); threadSleepTimeout = currentTime + STT_CLEANUP_INTERVAL; for (int i = 0; i < STT_HASH_TABLE_SIZE; i++) { LIST_FORALL_SAFE(&OvsSttPktFragHash[i], link, next) { entry = CONTAINING_RECORD(link, OVS_STT_PKT_ENTRY, link); if (entry->timeout < currentTime) { RemoveEntryList(&entry->link); OvsFreeMemoryWithTag(entry->packetBuf, OVS_STT_POOL_TAG); OvsFreeMemoryWithTag(entry, OVS_STT_POOL_TAG); } } } NdisReleaseSpinLock(&OvsSttSpinLock); KeWaitForSingleObject(&context->event, Executive, KernelMode, FALSE, (LARGE_INTEGER *)&threadSleepTimeout); } PsTerminateSystemThread(STATUS_SUCCESS); } static OVS_STT_PKT_KEY OvsGeneratePacketKey(IPHdr *ipHdr, TCPHdr *tcpHdr) { OVS_STT_PKT_KEY key; key.sAddr = ipHdr->saddr; key.dAddr = ipHdr->daddr; key.ackSeq = ntohl(tcpHdr->ack_seq); return key; } static UINT32 OvsSttGetPktHash(OVS_STT_PKT_KEY *pktKey) { UINT32 arr[3]; arr[0] = pktKey->ackSeq; arr[1] = pktKey->dAddr; arr[2] = pktKey->sAddr; return OvsJhashWords(arr, 3, OVS_HASH_BASIS); } static VOID * OvsLookupPktFrag(OVS_STT_PKT_KEY *pktKey, UINT32 hash) { PLIST_ENTRY link; POVS_STT_PKT_ENTRY entry; LIST_FORALL(&OvsSttPktFragHash[hash & STT_HASH_TABLE_MASK], link) { entry = CONTAINING_RECORD(link, OVS_STT_PKT_ENTRY, link); if (entry->ovsPktKey.ackSeq == pktKey->ackSeq && entry->ovsPktKey.dAddr == pktKey->dAddr && entry->ovsPktKey.sAddr == pktKey->sAddr) { return entry; } } return NULL; } /* * -------------------------------------------------------------------------- * OvsSttReassemble -- * Reassemble an LSO packet from multiple STT-Fragments. * -------------------------------------------------------------------------- */ PNET_BUFFER_LIST OvsSttReassemble(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, IPHdr *ipHdr, TCPHdr *tcp, SttHdr *newSttHdr, UINT16 payloadLen) { UINT32 seq = ntohl(tcp->seq); UINT32 innerPacketLen = (seq >> STT_SEQ_LEN_SHIFT) - STT_HDR_LEN; UINT32 segOffset = STT_SEGMENT_OFF(seq); UINT32 offset = segOffset == 0 ? 0 : segOffset - STT_HDR_LEN; UINT32 startOffset = 0; OVS_STT_PKT_ENTRY *pktFragEntry; PNET_BUFFER_LIST targetPNbl = NULL; BOOLEAN lastPacket = FALSE; PNET_BUFFER sourceNb; UINT32 fragmentLength = payloadLen; SttHdr stt; SttHdr *sttHdr = NULL; sourceNb = NET_BUFFER_LIST_FIRST_NB(curNbl); /* XXX optimize this lock */ NdisAcquireSpinLock(&OvsSttSpinLock); /* If this is the first fragment, copy the STT header */ if (segOffset == 0) { sttHdr = NdisGetDataBuffer(sourceNb, sizeof(SttHdr), &stt, 1, 0); if (sttHdr == NULL) { OVS_LOG_ERROR("Unable to retrieve STT header"); return NULL; } fragmentLength = fragmentLength - STT_HDR_LEN; startOffset = startOffset + STT_HDR_LEN; } /* Lookup fragment */ OVS_STT_PKT_KEY pktKey = OvsGeneratePacketKey(ipHdr, tcp); UINT32 hash = OvsSttGetPktHash(&pktKey); pktFragEntry = OvsLookupPktFrag(&pktKey, hash); if (pktFragEntry == NULL) { /* Create a new Packet Entry */ POVS_STT_PKT_ENTRY entry; entry = OvsAllocateMemoryWithTag(sizeof(OVS_STT_PKT_ENTRY), OVS_STT_POOL_TAG); RtlZeroMemory(entry, sizeof (OVS_STT_PKT_ENTRY)); /* Update Key, timestamp and recvdLen */ NdisMoveMemory(&entry->ovsPktKey, &pktKey, sizeof (OVS_STT_PKT_KEY)); entry->recvdLen = fragmentLength; UINT64 currentTime; NdisGetCurrentSystemTime((LARGE_INTEGER *) ¤tTime); entry->timeout = currentTime + STT_ENTRY_TIMEOUT; if (segOffset == 0) { entry->sttHdr = *sttHdr; } /* Copy the data from Source to new buffer */ entry->packetBuf = OvsAllocateMemoryWithTag(innerPacketLen, OVS_STT_POOL_TAG); if (OvsGetPacketBytes(curNbl, fragmentLength, startOffset, entry->packetBuf + offset) == NULL) { OVS_LOG_ERROR("Error when obtaining bytes from Packet"); goto handle_error; } /* Insert the entry in the Static Buffer */ InsertHeadList(&OvsSttPktFragHash[hash & STT_HASH_TABLE_MASK], &entry->link); } else { /* Add to recieved length to identify if this is the last fragment */ pktFragEntry->recvdLen += fragmentLength; lastPacket = (pktFragEntry->recvdLen == innerPacketLen); if (segOffset == 0) { pktFragEntry->sttHdr = *sttHdr; } /* Copy the fragment data from Source to existing buffer */ if (OvsGetPacketBytes(curNbl, fragmentLength, startOffset, pktFragEntry->packetBuf + offset) == NULL) { OVS_LOG_ERROR("Error when obtaining bytes from Packet"); goto handle_error; } } handle_error: if (lastPacket) { /* Retrieve the original STT header */ NdisMoveMemory(newSttHdr, &pktFragEntry->sttHdr, sizeof (SttHdr)); targetPNbl = OvsAllocateNBLFromBuffer(switchContext, pktFragEntry->packetBuf, innerPacketLen); /* Delete this entry and free up the memory/ */ RemoveEntryList(&pktFragEntry->link); OvsFreeMemoryWithTag(pktFragEntry->packetBuf, OVS_STT_POOL_TAG); OvsFreeMemoryWithTag(pktFragEntry, OVS_STT_POOL_TAG); } NdisReleaseSpinLock(&OvsSttSpinLock); return lastPacket ? targetPNbl : NULL; } VOID OvsDecapSetOffloads(PNET_BUFFER_LIST curNbl, SttHdr *sttHdr) { if ((sttHdr->flags & STT_CSUM_VERIFIED) || !(sttHdr->flags & STT_CSUM_PARTIAL)) { return; } UINT8 protoType; NDIS_TCP_IP_CHECKSUM_NET_BUFFER_LIST_INFO csumInfo; csumInfo.Value = 0; csumInfo.Transmit.IpHeaderChecksum = 0; csumInfo.Transmit.TcpHeaderOffset = sttHdr->l4Offset; protoType = sttHdr->flags & STT_PROTO_TYPES; switch (protoType) { case (STT_PROTO_IPV4 | STT_PROTO_TCP): /* TCP/IPv4 */ csumInfo.Transmit.IsIPv4 = 1; csumInfo.Transmit.TcpChecksum = 1; break; case STT_PROTO_TCP: /* TCP/IPv6 */ csumInfo.Transmit.IsIPv6 = 1; csumInfo.Transmit.TcpChecksum = 1; break; case STT_PROTO_IPV4: /* UDP/IPv4 */ csumInfo.Transmit.IsIPv4 = 1; csumInfo.Transmit.UdpChecksum = 1; break; default: /* UDP/IPv6 */ csumInfo.Transmit.IsIPv6 = 1; csumInfo.Transmit.UdpChecksum = 1; } NET_BUFFER_LIST_INFO(curNbl, TcpIpChecksumNetBufferListInfo) = csumInfo.Value; if (sttHdr->mss) { NDIS_TCP_LARGE_SEND_OFFLOAD_NET_BUFFER_LIST_INFO lsoInfo; lsoInfo.Value = 0; lsoInfo.LsoV2Transmit.TcpHeaderOffset = sttHdr->l4Offset; lsoInfo.LsoV2Transmit.MSS = ETH_DEFAULT_MTU - sizeof(IPHdr) - sizeof(TCPHdr); lsoInfo.LsoV2Transmit.Type = NDIS_TCP_LARGE_SEND_OFFLOAD_V2_TYPE; if (sttHdr->flags & STT_PROTO_IPV4) { lsoInfo.LsoV2Transmit.IPVersion = NDIS_TCP_LARGE_SEND_OFFLOAD_IPv4; } else { lsoInfo.LsoV2Transmit.IPVersion = NDIS_TCP_LARGE_SEND_OFFLOAD_IPv6; } NET_BUFFER_LIST_INFO(curNbl, TcpLargeSendNetBufferListInfo) = lsoInfo.Value; } } /* * -------------------------------------------------------------------------- * OvsDecapStt -- * Decapsulates an STT packet. * -------------------------------------------------------------------------- */ NDIS_STATUS OvsDecapStt(POVS_SWITCH_CONTEXT switchContext, PNET_BUFFER_LIST curNbl, OvsIPv4TunnelKey *tunKey, PNET_BUFFER_LIST *newNbl) { NDIS_STATUS status = NDIS_STATUS_FAILURE; PNET_BUFFER curNb, newNb; IPHdr *ipHdr; char *ipBuf[sizeof(IPHdr)]; SttHdr stt; SttHdr *sttHdr; char *sttBuf[STT_HDR_LEN]; UINT32 advanceCnt, hdrLen; BOOLEAN isLsoPacket = FALSE; curNb = NET_BUFFER_LIST_FIRST_NB(curNbl); ASSERT(NET_BUFFER_NEXT_NB(curNb) == NULL); /* Validate the TCP Checksum */ status = OvsValidateTCPChecksum(curNbl, curNb); if (status != NDIS_STATUS_SUCCESS) { return status; } /* Skip Eth header */ hdrLen = sizeof(EthHdr); NdisAdvanceNetBufferDataStart(curNb, hdrLen, FALSE, NULL); advanceCnt = hdrLen; ipHdr = NdisGetDataBuffer(curNb, sizeof *ipHdr, (PVOID) &ipBuf, 1 /*no align*/, 0); ASSERT(ipHdr); TCPHdr *tcp = (TCPHdr *)((PCHAR)ipHdr + ipHdr->ihl * 4); /* Skip IP & TCP headers */ hdrLen = sizeof(IPHdr) + sizeof(TCPHdr), NdisAdvanceNetBufferDataStart(curNb, hdrLen, FALSE, NULL); advanceCnt += hdrLen; UINT32 seq = ntohl(tcp->seq); UINT32 totalLen = (seq >> STT_SEQ_LEN_SHIFT); UINT16 payloadLen = (UINT16)ntohs(ipHdr->tot_len) - (ipHdr->ihl * 4) - (sizeof * tcp); /* Check if incoming packet requires reassembly */ if (totalLen != payloadLen) { sttHdr = &stt; PNET_BUFFER_LIST pNbl = OvsSttReassemble(switchContext, curNbl, ipHdr, tcp, sttHdr, payloadLen); if (pNbl == NULL) { return NDIS_STATUS_SUCCESS; } *newNbl = pNbl; isLsoPacket = TRUE; } else { /* STT Header */ sttHdr = NdisGetDataBuffer(curNb, sizeof *sttHdr, (PVOID) &sttBuf, 1 /*no align*/, 0); /* Skip stt header, DataOffset points to inner pkt now. */ hdrLen = STT_HDR_LEN; NdisAdvanceNetBufferDataStart(curNb, hdrLen, FALSE, NULL); advanceCnt += hdrLen; *newNbl = OvsPartialCopyNBL(switchContext, curNbl, 0, 0, FALSE /*copy NBL info*/); } if (*newNbl == NULL) { OVS_LOG_ERROR("Unable to allocate a new cloned NBL"); return NDIS_STATUS_RESOURCES; } status = NdisRetreatNetBufferDataStart(curNb, advanceCnt, 0, NULL); if (status != NDIS_STATUS_SUCCESS) { OvsCompleteNBL(switchContext, *newNbl, TRUE); return NDIS_STATUS_FAILURE; } newNb = NET_BUFFER_LIST_FIRST_NB(*newNbl); ASSERT(sttHdr); /* Initialize the tunnel key */ tunKey->dst = ipHdr->daddr; tunKey->src = ipHdr->saddr; tunKey->tunnelId = sttHdr->key; tunKey->flags = OVS_TNL_F_KEY; tunKey->tos = ipHdr->tos; tunKey->ttl = ipHdr->ttl; tunKey->pad = 0; /* Set Checksum and LSO offload flags */ OvsDecapSetOffloads(*newNbl, sttHdr); return NDIS_STATUS_SUCCESS; } openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/Flow.c0000644000000000000000000000013212664352753021527 xustar0030 mtime=1456592363.430620507 30 atime=1456592368.174815358 30 ctime=1456594660.189288653 openvswitch-2.5.0/datapath-windows/ovsext/Flow.c0000664000175000017500000024143012664352753023223 0ustar00jpettitjpettit00000000000000/* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "precomp.h" #include "NetProto.h" #include "Util.h" #include "Jhash.h" #include "Flow.h" #include "PacketParser.h" #include "Datapath.h" #ifdef OVS_DBG_MOD #undef OVS_DBG_MOD #endif #define OVS_DBG_MOD OVS_DBG_FLOW #include "Debug.h" #pragma warning( push ) #pragma warning( disable:4127 ) extern POVS_SWITCH_CONTEXT gOvsSwitchContext; extern UINT64 ovsTimeIncrementPerTick; static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags, OvsFlowInfo *info); static NTSTATUS HandleFlowPut(OvsFlowPut *put, OVS_DATAPATH *datapath, struct OvsFlowStats *stats); static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put, UINT64 hash); static VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow); static VOID DeleteAllFlows(OVS_DATAPATH *datapath); static NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow); static VOID FreeFlow(OvsFlow *flow); static VOID __inline *GetStartAddrNBL(const NET_BUFFER_LIST *_pNB); static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr, PNL_ATTR actionAttr, PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow); static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, PNL_ATTR *tunnelAttrs, OvsFlowKey *destKey); static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs, PNL_ATTR *tunnelAttrs, OvsFlowKey *destKey); static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr, PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow); static NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); static NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo); static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats); static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen, PNL_ATTR actions); static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey); static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey, Icmp6Key *ipv6FlowPutIcmpKey); static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey); static NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput, OvsFlowDumpOutput *dumpOutput, UINT32 *replyLen); #define OVS_FLOW_TABLE_SIZE 2048 #define OVS_FLOW_TABLE_MASK (OVS_FLOW_TABLE_SIZE -1) #define HASH_BUCKET(hash) ((hash) & OVS_FLOW_TABLE_MASK) /* Flow family related netlink policies */ /* For Parsing attributes in FLOW_* commands */ const NL_POLICY nlFlowPolicy[] = { [OVS_FLOW_ATTR_KEY] = {.type = NL_A_NESTED, .optional = FALSE}, [OVS_FLOW_ATTR_MASK] = {.type = NL_A_NESTED, .optional = TRUE}, [OVS_FLOW_ATTR_ACTIONS] = {.type = NL_A_NESTED, .optional = TRUE}, [OVS_FLOW_ATTR_STATS] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_flow_stats), .maxLen = sizeof(struct ovs_flow_stats), .optional = TRUE}, [OVS_FLOW_ATTR_TCP_FLAGS] = {NL_A_U8, .optional = TRUE}, [OVS_FLOW_ATTR_USED] = {NL_A_U64, .optional = TRUE}, [OVS_FLOW_ATTR_PROBE] = {.type = NL_A_FLAG, .optional = TRUE} }; /* For Parsing nested OVS_FLOW_ATTR_KEY attributes. * Some of the attributes like OVS_KEY_ATTR_RECIRC_ID * & OVS_KEY_ATTR_MPLS are not supported yet. */ const NL_POLICY nlFlowKeyPolicy[] = { [OVS_KEY_ATTR_ENCAP] = {.type = NL_A_VAR_LEN, .optional = TRUE}, [OVS_KEY_ATTR_PRIORITY] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = TRUE}, [OVS_KEY_ATTR_IN_PORT] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = FALSE}, [OVS_KEY_ATTR_ETHERNET] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_ethernet), .maxLen = sizeof(struct ovs_key_ethernet), .optional = TRUE}, [OVS_KEY_ATTR_VLAN] = {.type = NL_A_UNSPEC, .minLen = 2, .maxLen = 2, .optional = TRUE}, [OVS_KEY_ATTR_ETHERTYPE] = {.type = NL_A_UNSPEC, .minLen = 2, .maxLen = 2, .optional = TRUE}, [OVS_KEY_ATTR_IPV4] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_ipv4), .maxLen = sizeof(struct ovs_key_ipv4), .optional = TRUE}, [OVS_KEY_ATTR_IPV6] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_ipv6), .maxLen = sizeof(struct ovs_key_ipv6), .optional = TRUE}, [OVS_KEY_ATTR_TCP] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_tcp), .maxLen = sizeof(struct ovs_key_tcp), .optional = TRUE}, [OVS_KEY_ATTR_UDP] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_udp), .maxLen = sizeof(struct ovs_key_udp), .optional = TRUE}, [OVS_KEY_ATTR_ICMP] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_icmp), .maxLen = sizeof(struct ovs_key_icmp), .optional = TRUE}, [OVS_KEY_ATTR_ICMPV6] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_icmpv6), .maxLen = sizeof(struct ovs_key_icmpv6), .optional = TRUE}, [OVS_KEY_ATTR_ARP] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_arp), .maxLen = sizeof(struct ovs_key_arp), .optional = TRUE}, [OVS_KEY_ATTR_ND] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_nd), .maxLen = sizeof(struct ovs_key_nd), .optional = TRUE}, [OVS_KEY_ATTR_SKB_MARK] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = TRUE}, [OVS_KEY_ATTR_TUNNEL] = {.type = NL_A_VAR_LEN, .optional = TRUE}, [OVS_KEY_ATTR_SCTP] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_key_sctp), .maxLen = sizeof(struct ovs_key_sctp), .optional = TRUE}, [OVS_KEY_ATTR_TCP_FLAGS] = {.type = NL_A_UNSPEC, .minLen = 2, .maxLen = 2, .optional = TRUE}, [OVS_KEY_ATTR_DP_HASH] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = TRUE}, [OVS_KEY_ATTR_RECIRC_ID] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = TRUE}, [OVS_KEY_ATTR_MPLS] = {.type = NL_A_VAR_LEN, .optional = TRUE} }; const UINT32 nlFlowKeyPolicyLen = ARRAY_SIZE(nlFlowKeyPolicy); /* For Parsing nested OVS_KEY_ATTR_TUNNEL attributes */ const NL_POLICY nlFlowTunnelKeyPolicy[] = { [OVS_TUNNEL_KEY_ATTR_ID] = {.type = NL_A_UNSPEC, .minLen = 8, .maxLen = 8, .optional = TRUE}, [OVS_TUNNEL_KEY_ATTR_IPV4_SRC] = {.type = NL_A_UNSPEC, .minLen = 4, .maxLen = 4, .optional = TRUE}, [OVS_TUNNEL_KEY_ATTR_IPV4_DST] = {.type = NL_A_UNSPEC, .minLen = 4 , .maxLen = 4, .optional = FALSE}, [OVS_TUNNEL_KEY_ATTR_TOS] = {.type = NL_A_UNSPEC, .minLen = 1, .maxLen = 1, .optional = TRUE}, [OVS_TUNNEL_KEY_ATTR_TTL] = {.type = NL_A_UNSPEC, .minLen = 1, .maxLen = 1, .optional = TRUE}, [OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT] = {.type = NL_A_UNSPEC, .minLen = 0, .maxLen = 0, .optional = TRUE}, [OVS_TUNNEL_KEY_ATTR_CSUM] = {.type = NL_A_UNSPEC, .minLen = 0, .maxLen = 0, .optional = TRUE}, [OVS_TUNNEL_KEY_ATTR_OAM] = {.type = NL_A_UNSPEC, .minLen = 0, .maxLen = 0, .optional = TRUE}, [OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS] = {.type = NL_A_VAR_LEN, .optional = TRUE} }; /* For Parsing nested OVS_FLOW_ATTR_ACTIONS attributes */ const NL_POLICY nlFlowActionPolicy[] = { [OVS_ACTION_ATTR_OUTPUT] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32), .maxLen = sizeof(UINT32), .optional = TRUE}, [OVS_ACTION_ATTR_USERSPACE] = {.type = NL_A_VAR_LEN, .optional = TRUE}, [OVS_ACTION_ATTR_PUSH_VLAN] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_action_push_vlan), .maxLen = sizeof(struct ovs_action_push_vlan), .optional = TRUE}, [OVS_ACTION_ATTR_POP_VLAN] = {.type = NL_A_UNSPEC, .optional = TRUE}, [OVS_ACTION_ATTR_PUSH_MPLS] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_action_push_mpls), .maxLen = sizeof(struct ovs_action_push_mpls), .optional = TRUE}, [OVS_ACTION_ATTR_POP_MPLS] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT16), .maxLen = sizeof(UINT16), .optional = TRUE}, [OVS_ACTION_ATTR_RECIRC] = {.type = NL_A_UNSPEC, .minLen = sizeof(UINT32), .maxLen = sizeof(UINT32), .optional = TRUE}, [OVS_ACTION_ATTR_HASH] = {.type = NL_A_UNSPEC, .minLen = sizeof(struct ovs_action_hash), .maxLen = sizeof(struct ovs_action_hash), .optional = TRUE}, [OVS_ACTION_ATTR_SET] = {.type = NL_A_VAR_LEN, .optional = TRUE}, [OVS_ACTION_ATTR_SAMPLE] = {.type = NL_A_VAR_LEN, .optional = TRUE} }; /* *---------------------------------------------------------------------------- * Netlink interface for flow commands. *---------------------------------------------------------------------------- */ /* *---------------------------------------------------------------------------- * OvsFlowNewCmdHandler -- * Handler for OVS_FLOW_CMD_NEW/SET/DEL command. * It also handles FLUSH case (DEL w/o any key in input) *---------------------------------------------------------------------------- */ NTSTATUS OvsFlowNlCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS rc = STATUS_SUCCESS; BOOLEAN ok; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; POVS_MESSAGE msgOut = (POVS_MESSAGE)usrParamsCtx->outputBuffer; PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg); POVS_HDR ovsHdr = &(msgIn->ovsHdr); PNL_ATTR flowAttrs[__OVS_FLOW_ATTR_MAX]; UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN; OvsFlowPut mappedFlow; OvsFlowStats stats; struct ovs_flow_stats replyStats; NL_ERROR nlError = NL_ERROR_SUCCESS; NL_BUFFER nlBuf; RtlZeroMemory(&mappedFlow, sizeof(OvsFlowPut)); RtlZeroMemory(&stats, sizeof(stats)); RtlZeroMemory(&replyStats, sizeof(replyStats)); if (!(usrParamsCtx->outputBuffer)) { /* No output buffer */ rc = STATUS_INVALID_BUFFER_SIZE; goto done; } /* Get all the top level Flow attributes */ if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr), nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy), flowAttrs, ARRAY_SIZE(flowAttrs))) != TRUE) { OVS_LOG_ERROR("Attr Parsing failed for msg: %p", nlMsgHdr); rc = STATUS_INVALID_PARAMETER; goto done; } /* FLOW_DEL command w/o any key input is a flush case. */ if ((genlMsgHdr->cmd == OVS_FLOW_CMD_DEL) && (!(flowAttrs[OVS_FLOW_ATTR_KEY]))) { rc = OvsFlushFlowIoctl(ovsHdr->dp_ifindex); if (rc == STATUS_SUCCESS) { /* XXX: refactor this code. */ /* So far so good. Prepare the reply for userspace */ NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); /* Prepare nl Msg headers */ ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0, nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid, genlMsgHdr->cmd, OVS_FLOW_VERSION, ovsHdr->dp_ifindex); if (ok) { *replyLen = msgOut->nlMsg.nlmsgLen; } else { rc = STATUS_INVALID_BUFFER_SIZE; } } goto done; } if (flowAttrs[OVS_FLOW_ATTR_PROBE]) { OVS_LOG_ERROR("Attribute OVS_FLOW_ATTR_PROBE not supported"); goto done; } if ((rc = _MapNlToFlowPut(msgIn, flowAttrs[OVS_FLOW_ATTR_KEY], flowAttrs[OVS_FLOW_ATTR_ACTIONS], flowAttrs[OVS_FLOW_ATTR_CLEAR], &mappedFlow)) != STATUS_SUCCESS) { OVS_LOG_ERROR("Conversion to OvsFlowPut failed"); goto done; } rc = OvsPutFlowIoctl(&mappedFlow, sizeof (struct OvsFlowPut), &stats); if (rc != STATUS_SUCCESS) { OVS_LOG_ERROR("OvsPutFlowIoctl failed."); /* * Report back to the userspace the flow could not be modified, * created or deleted */ nlError = NL_ERROR_NOENT; goto done; } replyStats.n_packets = stats.packetCount; replyStats.n_bytes = stats.byteCount; /* So far so good. Prepare the reply for userspace */ NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); /* Prepare nl Msg headers */ ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, 0, nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid, genlMsgHdr->cmd, OVS_FLOW_VERSION, ovsHdr->dp_ifindex); if (!ok) { rc = STATUS_INVALID_BUFFER_SIZE; goto done; } else { rc = STATUS_SUCCESS; } /* Append OVS_FLOW_ATTR_KEY attribute. This is need i.e. for flow delete*/ if (!NlMsgPutNested(&nlBuf, OVS_FLOW_ATTR_KEY, NlAttrData(flowAttrs[OVS_FLOW_ATTR_KEY]), NlAttrGetSize(flowAttrs[OVS_FLOW_ATTR_KEY]))) { OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_KEY attribute failed."); rc = STATUS_INVALID_BUFFER_SIZE; goto done; } /* Append OVS_FLOW_ATTR_STATS attribute */ if (!NlMsgPutTailUnspec(&nlBuf, OVS_FLOW_ATTR_STATS, (PCHAR)(&replyStats), sizeof(replyStats))) { OVS_LOG_ERROR("Adding OVS_FLOW_ATTR_STATS attribute failed."); rc = STATUS_INVALID_BUFFER_SIZE; goto done; } msgOut->nlMsg.nlmsgLen = NLMSG_ALIGN(NlBufSize(&nlBuf)); *replyLen = msgOut->nlMsg.nlmsgLen; done: if (nlError != NL_ERROR_SUCCESS) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; rc = STATUS_SUCCESS; } return rc; } /* *---------------------------------------------------------------------------- * OvsFlowNlGetCmdHandler -- * Handler for OVS_FLOW_CMD_GET/DUMP commands. *---------------------------------------------------------------------------- */ NTSTATUS OvsFlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS status = STATUS_SUCCESS; if (usrParamsCtx->devOp == OVS_TRANSACTION_DEV_OP) { status = _FlowNlGetCmdHandler(usrParamsCtx, replyLen); } else { status = _FlowNlDumpCmdHandler(usrParamsCtx, replyLen); } return status; } /* *---------------------------------------------------------------------------- * _FlowNlGetCmdHandler -- * Handler for OVS_FLOW_CMD_GET command. *---------------------------------------------------------------------------- */ NTSTATUS _FlowNlGetCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS rc = STATUS_SUCCESS; POVS_MESSAGE msgIn = (POVS_MESSAGE)usrParamsCtx->inputBuffer; PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); POVS_HDR ovsHdr = &(msgIn->ovsHdr); PNL_MSG_HDR nlMsgOutHdr = NULL; UINT32 attrOffset = NLMSG_HDRLEN + GENL_HDRLEN + OVS_HDRLEN; PNL_ATTR nlAttrs[__OVS_FLOW_ATTR_MAX]; OvsFlowGetInput getInput; OvsFlowGetOutput getOutput; NL_BUFFER nlBuf; PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX]; PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX]; NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); RtlZeroMemory(&getInput, sizeof(OvsFlowGetInput)); RtlZeroMemory(&getOutput, sizeof(OvsFlowGetOutput)); UINT32 keyAttrOffset = 0; UINT32 tunnelKeyAttrOffset = 0; BOOLEAN ok; NL_ERROR nlError = NL_ERROR_SUCCESS; if (usrParamsCtx->inputLength > usrParamsCtx->outputLength) { /* Should not be the case. * We'll be copying the flow keys back from * input buffer to output buffer. */ rc = STATUS_INVALID_PARAMETER; OVS_LOG_ERROR("inputLength: %d GREATER THEN outputLength: %d", usrParamsCtx->inputLength, usrParamsCtx->outputLength); goto done; } /* Get all the top level Flow attributes */ if ((NlAttrParse(nlMsgHdr, attrOffset, NlMsgAttrsLen(nlMsgHdr), nlFlowPolicy, ARRAY_SIZE(nlFlowPolicy), nlAttrs, ARRAY_SIZE(nlAttrs))) != TRUE) { OVS_LOG_ERROR("Attr Parsing failed for msg: %p", nlMsgHdr); rc = STATUS_INVALID_PARAMETER; goto done; } keyAttrOffset = (UINT32)((PCHAR) nlAttrs[OVS_FLOW_ATTR_KEY] - (PCHAR)nlMsgHdr); /* Get flow keys attributes */ if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(nlAttrs[OVS_FLOW_ATTR_KEY]), nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy), keyAttrs, ARRAY_SIZE(keyAttrs))) != TRUE) { OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p", nlMsgHdr); rc = STATUS_INVALID_PARAMETER; goto done; } if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) { tunnelKeyAttrOffset = (UINT32)((PCHAR) (keyAttrs[OVS_KEY_ATTR_TUNNEL]) - (PCHAR)nlMsgHdr); /* Get tunnel keys attributes */ if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset, NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]), nlFlowTunnelKeyPolicy, ARRAY_SIZE(nlFlowTunnelKeyPolicy), tunnelAttrs, ARRAY_SIZE(tunnelAttrs))) != TRUE) { OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p", nlMsgHdr); rc = STATUS_INVALID_PARAMETER; goto done; } } _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs, &(getInput.key)); getInput.dpNo = ovsHdr->dp_ifindex; getInput.getFlags = FLOW_GET_STATS | FLOW_GET_ACTIONS; /* 4th argument is a no op. * We are keeping this argument to be compatible * with our dpif-windows based interface. */ rc = OvsGetFlowIoctl(&getInput, &getOutput); if (rc != STATUS_SUCCESS) { OVS_LOG_ERROR("OvsGetFlowIoctl failed."); /* * Report back to the userspace the flow could not be found */ nlError = NL_ERROR_NOENT; goto done; } /* Lets prepare the reply. */ nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, 0, 0)); /* Input already has all the attributes for the flow key. * Lets copy the values back. */ ok = NlMsgPutTail(&nlBuf, (PCHAR)(usrParamsCtx->inputBuffer), usrParamsCtx->inputLength); if (!ok) { OVS_LOG_ERROR("Could not copy the data to the buffer tail"); goto done; } rc = _MapFlowStatsToNlStats(&nlBuf, &((getOutput.info).stats)); if (rc != STATUS_SUCCESS) { OVS_LOG_ERROR("_OvsFlowMapFlowKeyToNlStats failed."); goto done; } rc = _MapFlowActionToNlAction(&nlBuf, ((getOutput.info).actionsLen), getOutput.info.actions); if (rc != STATUS_SUCCESS) { OVS_LOG_ERROR("_MapFlowActionToNlAction failed."); goto done; } NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf)); NlMsgAlignSize(nlMsgOutHdr); *replyLen += NlMsgSize(nlMsgOutHdr); done: if (nlError != NL_ERROR_SUCCESS) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; rc = STATUS_SUCCESS; } return rc; } /* *---------------------------------------------------------------------------- * _FlowNlDumpCmdHandler -- * Handler for OVS_FLOW_CMD_DUMP command. *---------------------------------------------------------------------------- */ NTSTATUS _FlowNlDumpCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen) { NTSTATUS rc = STATUS_SUCCESS; UINT32 temp = 0; /* To keep compiler happy for calling OvsDoDumpFlows */ NL_ERROR nlError = NL_ERROR_SUCCESS; POVS_OPEN_INSTANCE instance = (POVS_OPEN_INSTANCE) (usrParamsCtx->ovsInstance); POVS_MESSAGE msgIn = instance->dumpState.ovsMsg; if (usrParamsCtx->devOp == OVS_WRITE_DEV_OP) { /* Dump Start */ OvsSetupDumpStart(usrParamsCtx); goto done; } PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg); POVS_HDR ovsHdr = &(msgIn->ovsHdr); PNL_MSG_HDR nlMsgOutHdr = NULL; UINT32 hdrOffset = 0; /* Get Next */ OvsFlowDumpOutput dumpOutput; OvsFlowDumpInput dumpInput; NL_BUFFER nlBuf; NlBufInit(&nlBuf, usrParamsCtx->outputBuffer, usrParamsCtx->outputLength); ASSERT(usrParamsCtx->devOp == OVS_READ_DEV_OP); ASSERT(usrParamsCtx->outputLength); RtlZeroMemory(&dumpInput, sizeof(OvsFlowDumpInput)); RtlZeroMemory(&dumpOutput, sizeof(OvsFlowDumpOutput)); dumpInput.dpNo = ovsHdr->dp_ifindex; dumpInput.getFlags = FLOW_GET_KEY | FLOW_GET_STATS | FLOW_GET_ACTIONS; /* Lets provide as many flows to userspace as possible. */ do { dumpInput.position[0] = instance->dumpState.index[0]; dumpInput.position[1] = instance->dumpState.index[1]; rc = OvsDoDumpFlows(&dumpInput, &dumpOutput, &temp); if (rc != STATUS_SUCCESS) { OVS_LOG_ERROR("OvsDoDumpFlows failed with rc: %d", rc); /* * Report back to the userspace the flows could not be found */ nlError = NL_ERROR_NOENT; break; } /* Done with Dump, send NLMSG_DONE */ if (!(dumpOutput.n)) { BOOLEAN ok; OVS_LOG_INFO("Dump Done"); nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, NlBufSize(&nlBuf), 0)); ok = NlFillNlHdr(&nlBuf, NLMSG_DONE, NLM_F_MULTI, nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid); if (!ok) { rc = STATUS_INVALID_BUFFER_SIZE; OVS_LOG_ERROR("Unable to prepare DUMP_DONE reply."); break; } else { rc = STATUS_SUCCESS; } NlMsgAlignSize(nlMsgOutHdr); *replyLen += NlMsgSize(nlMsgOutHdr); FreeUserDumpState(instance); break; } else { BOOLEAN ok; hdrOffset = NlBufSize(&nlBuf); nlMsgOutHdr = (PNL_MSG_HDR)(NlBufAt(&nlBuf, hdrOffset, 0)); /* Netlink header */ ok = NlFillOvsMsg(&nlBuf, nlMsgHdr->nlmsgType, NLM_F_MULTI, nlMsgHdr->nlmsgSeq, nlMsgHdr->nlmsgPid, genlMsgHdr->cmd, genlMsgHdr->version, ovsHdr->dp_ifindex); if (!ok) { /* Reset rc to success so that we can * send already added messages to user space. */ rc = STATUS_SUCCESS; break; } /* Time to add attributes */ rc = _MapFlowInfoToNl(&nlBuf, &(dumpOutput.flow)); if (rc != STATUS_SUCCESS) { /* Adding the attribute failed, we are out of space in the buffer, remove the appended OVS header */ NlMsgSetSize(nlMsgOutHdr, NlMsgSize(nlMsgOutHdr) - sizeof(struct _OVS_MESSAGE)); /* Reset rc to success so that we can * send already added messages to user space. */ rc = STATUS_SUCCESS; break; } NlMsgSetSize(nlMsgOutHdr, NlBufSize(&nlBuf) - hdrOffset); NlMsgAlignSize(nlMsgOutHdr); *replyLen += NlMsgSize(nlMsgOutHdr); instance->dumpState.index[0] = dumpOutput.position[0]; instance->dumpState.index[1] = dumpOutput.position[1]; } } while(TRUE); done: if (nlError != NL_ERROR_SUCCESS) { POVS_MESSAGE_ERROR msgError = (POVS_MESSAGE_ERROR) usrParamsCtx->outputBuffer; NlBuildErrorMsg(msgIn, msgError, nlError); *replyLen = msgError->nlMsg.nlmsgLen; rc = STATUS_SUCCESS; } return rc; } /* *---------------------------------------------------------------------------- * _MapFlowInfoToNl -- * Maps OvsFlowInfo to Netlink attributes. *---------------------------------------------------------------------------- */ static NTSTATUS _MapFlowInfoToNl(PNL_BUFFER nlBuf, OvsFlowInfo *flowInfo) { NTSTATUS rc = STATUS_SUCCESS; rc = MapFlowKeyToNlKey(nlBuf, &(flowInfo->key), OVS_FLOW_ATTR_KEY, OVS_KEY_ATTR_TUNNEL); if (rc != STATUS_SUCCESS) { goto done; } rc = _MapFlowStatsToNlStats(nlBuf, &(flowInfo->stats)); if (rc != STATUS_SUCCESS) { goto done; } rc = _MapFlowActionToNlAction(nlBuf, flowInfo->actionsLen, flowInfo->actions); if (rc != STATUS_SUCCESS) { goto done; } done: return rc; } /* *---------------------------------------------------------------------------- * _MapFlowStatsToNlStats -- * Maps OvsFlowStats to OVS_FLOW_ATTR_STATS attribute. *---------------------------------------------------------------------------- */ static NTSTATUS _MapFlowStatsToNlStats(PNL_BUFFER nlBuf, OvsFlowStats *flowStats) { NTSTATUS rc = STATUS_SUCCESS; struct ovs_flow_stats replyStats; replyStats.n_packets = flowStats->packetCount; replyStats.n_bytes = flowStats->byteCount; if (!NlMsgPutTailU64(nlBuf, OVS_FLOW_ATTR_USED, flowStats->used)) { rc = STATUS_INVALID_BUFFER_SIZE; goto done; } if (!NlMsgPutTailUnspec(nlBuf, OVS_FLOW_ATTR_STATS, (PCHAR)(&replyStats), sizeof(struct ovs_flow_stats))) { rc = STATUS_INVALID_BUFFER_SIZE; goto done; } if (!NlMsgPutTailU8(nlBuf, OVS_FLOW_ATTR_TCP_FLAGS, flowStats->tcpFlags)) { rc = STATUS_INVALID_BUFFER_SIZE; goto done; } done: return rc; } /* *---------------------------------------------------------------------------- * _MapFlowActionToNlAction -- * Maps flow actions to OVS_FLOW_ATTR_ACTION attribute. *---------------------------------------------------------------------------- */ static NTSTATUS _MapFlowActionToNlAction(PNL_BUFFER nlBuf, uint32_t actionsLen, PNL_ATTR actions) { NTSTATUS rc = STATUS_SUCCESS; UINT32 offset = 0; offset = NlMsgStartNested(nlBuf, OVS_FLOW_ATTR_ACTIONS); if (!offset) { /* Starting the nested attribute failed. */ rc = STATUS_INVALID_BUFFER_SIZE; goto error_nested_start; } if (!NlBufCopyAtTail(nlBuf, (PCHAR)actions, actionsLen)) { /* Adding a nested attribute failed. */ rc = STATUS_INVALID_BUFFER_SIZE; goto done; } done: NlMsgEndNested(nlBuf, offset); error_nested_start: return rc; } /* *---------------------------------------------------------------------------- * MapFlowKeyToNlKey -- * Maps OvsFlowKey to OVS_FLOW_ATTR_KEY attribute. *---------------------------------------------------------------------------- */ NTSTATUS MapFlowKeyToNlKey(PNL_BUFFER nlBuf, OvsFlowKey *flowKey, UINT16 keyType, UINT16 tunKeyType) { NTSTATUS rc = STATUS_SUCCESS; struct ovs_key_ethernet ethKey; UINT32 offset = 0; offset = NlMsgStartNested(nlBuf, keyType); if (!offset) { /* Starting the nested attribute failed. */ rc = STATUS_UNSUCCESSFUL; goto error_nested_start; } /* Ethernet header */ RtlCopyMemory(&(ethKey.eth_src), flowKey->l2.dlSrc, ETH_ADDR_LEN); RtlCopyMemory(&(ethKey.eth_dst), flowKey->l2.dlDst, ETH_ADDR_LEN); if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ETHERNET, (PCHAR)(ðKey), sizeof(struct ovs_key_ethernet))) { rc = STATUS_UNSUCCESSFUL; goto done; } if (!NlMsgPutTailU32(nlBuf, OVS_KEY_ATTR_IN_PORT, flowKey->l2.inPort)) { rc = STATUS_UNSUCCESSFUL; goto done; } if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_ETHERTYPE, flowKey->l2.dlType)) { rc = STATUS_UNSUCCESSFUL; goto done; } if (flowKey->l2.vlanTci) { if (!NlMsgPutTailU16(nlBuf, OVS_KEY_ATTR_VLAN, flowKey->l2.vlanTci)) { rc = STATUS_UNSUCCESSFUL; goto done; } } /* ==== L3 + L4 ==== */ switch (ntohs(flowKey->l2.dlType)) { case ETH_TYPE_IPV4: { IpKey *ipv4FlowPutKey = &(flowKey->ipKey); rc = _MapFlowIpv4KeyToNlKey(nlBuf, ipv4FlowPutKey); break; } case ETH_TYPE_IPV6: { Ipv6Key *ipv6FlowPutKey = &(flowKey->ipv6Key); Icmp6Key *icmpv6FlowPutKey = &(flowKey->icmp6Key); rc = _MapFlowIpv6KeyToNlKey(nlBuf, ipv6FlowPutKey, icmpv6FlowPutKey); break; } case ETH_TYPE_ARP: case ETH_TYPE_RARP: { ArpKey *arpFlowPutKey = &(flowKey->arpKey); rc = _MapFlowArpKeyToNlKey(nlBuf, arpFlowPutKey); break; } default: break; } if (rc != STATUS_SUCCESS) { goto done; } if (flowKey->tunKey.dst) { rc = MapFlowTunKeyToNlKey(nlBuf, &(flowKey->tunKey), tunKeyType); if (rc != STATUS_SUCCESS) { goto done; } } done: NlMsgEndNested(nlBuf, offset); error_nested_start: return rc; } /* *---------------------------------------------------------------------------- * MapFlowTunKeyToNlKey -- * Maps OvsIPv4TunnelKey to OVS_TUNNEL_KEY_ATTR_ID attribute. *---------------------------------------------------------------------------- */ NTSTATUS MapFlowTunKeyToNlKey(PNL_BUFFER nlBuf, OvsIPv4TunnelKey *tunKey, UINT16 tunKeyType) { NTSTATUS rc = STATUS_SUCCESS; UINT32 offset = 0; offset = NlMsgStartNested(nlBuf, tunKeyType); if (!offset) { /* Starting the nested attribute failed. */ rc = STATUS_UNSUCCESSFUL; goto error_nested_start; } if (!NlMsgPutTailU64(nlBuf, OVS_TUNNEL_KEY_ATTR_ID, tunKey->tunnelId)) { rc = STATUS_UNSUCCESSFUL; goto done; } if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_DST, tunKey->dst)) { rc = STATUS_UNSUCCESSFUL; goto done; } if (!NlMsgPutTailU32(nlBuf, OVS_TUNNEL_KEY_ATTR_IPV4_SRC, tunKey->src)) { rc = STATUS_UNSUCCESSFUL; goto done; } if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TOS, tunKey->tos)) { rc = STATUS_UNSUCCESSFUL; goto done; } if (!NlMsgPutTailU8(nlBuf, OVS_TUNNEL_KEY_ATTR_TTL, tunKey->ttl)) { rc = STATUS_UNSUCCESSFUL; goto done; } done: NlMsgEndNested(nlBuf, offset); error_nested_start: return rc; } /* *---------------------------------------------------------------------------- * _MapFlowTunKeyToNlKey -- * Maps OvsIPv4FlowPutKey to OVS_KEY_ATTR_IPV4 attribute. *---------------------------------------------------------------------------- */ static NTSTATUS _MapFlowIpv4KeyToNlKey(PNL_BUFFER nlBuf, IpKey *ipv4FlowPutKey) { NTSTATUS rc = STATUS_SUCCESS; struct ovs_key_ipv4 ipv4Key; ipv4Key.ipv4_src = ipv4FlowPutKey->nwSrc; ipv4Key.ipv4_dst = ipv4FlowPutKey->nwDst; ipv4Key.ipv4_proto = ipv4FlowPutKey->nwProto; ipv4Key.ipv4_tos = ipv4FlowPutKey->nwTos; ipv4Key.ipv4_ttl = ipv4FlowPutKey->nwTtl; ipv4Key.ipv4_frag = ipv4FlowPutKey->nwFrag; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV4, (PCHAR)(&ipv4Key), sizeof(struct ovs_key_ipv4))) { rc = STATUS_UNSUCCESSFUL; goto done; } switch (ipv4Key.ipv4_proto) { case IPPROTO_TCP: { struct ovs_key_tcp tcpKey; tcpKey.tcp_src = ipv4FlowPutKey->l4.tpSrc; tcpKey.tcp_dst = ipv4FlowPutKey->l4.tpDst; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP, (PCHAR)(&tcpKey), sizeof(tcpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } case IPPROTO_UDP: { struct ovs_key_udp udpKey; udpKey.udp_src = ipv4FlowPutKey->l4.tpSrc; udpKey.udp_dst = ipv4FlowPutKey->l4.tpDst; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP, (PCHAR)(&udpKey), sizeof(udpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } case IPPROTO_SCTP: { struct ovs_key_sctp sctpKey; sctpKey.sctp_src = ipv4FlowPutKey->l4.tpSrc; sctpKey.sctp_dst = ipv4FlowPutKey->l4.tpDst; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP, (PCHAR)(&sctpKey), sizeof(sctpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } case IPPROTO_ICMP: { struct ovs_key_icmp icmpKey; /* XXX: revisit to see if htons is needed */ icmpKey.icmp_type = (__u8)(ipv4FlowPutKey->l4.tpSrc); icmpKey.icmp_code = (__u8)(ipv4FlowPutKey->l4.tpDst); if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMP, (PCHAR)(&icmpKey), sizeof(icmpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } default: break; } done: return rc; } /* *---------------------------------------------------------------------------- * _MapFlowIpv6KeyToNlKey -- * Maps _MapFlowIpv6KeyToNlKey to OVS_KEY_ATTR_IPV6 attribute. *---------------------------------------------------------------------------- */ static NTSTATUS _MapFlowIpv6KeyToNlKey(PNL_BUFFER nlBuf, Ipv6Key *ipv6FlowPutKey, Icmp6Key *icmpv6FlowPutKey) { NTSTATUS rc = STATUS_SUCCESS; struct ovs_key_ipv6 ipv6Key; RtlCopyMemory(&(ipv6Key.ipv6_src), &ipv6FlowPutKey->ipv6Src, sizeof ipv6Key.ipv6_src); RtlCopyMemory(&(ipv6Key.ipv6_dst), &ipv6FlowPutKey->ipv6Dst, sizeof ipv6Key.ipv6_dst); ipv6Key.ipv6_label = ipv6FlowPutKey->ipv6Label; ipv6Key.ipv6_proto = ipv6FlowPutKey->nwProto; ipv6Key.ipv6_tclass = ipv6FlowPutKey->nwTos; ipv6Key.ipv6_hlimit = ipv6FlowPutKey->nwTtl; ipv6Key.ipv6_frag = ipv6FlowPutKey->nwFrag; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_IPV6, (PCHAR)(&ipv6Key), sizeof(ipv6Key))) { rc = STATUS_UNSUCCESSFUL; goto done; } switch (ipv6Key.ipv6_proto) { case IPPROTO_TCP: { struct ovs_key_tcp tcpKey; tcpKey.tcp_src = ipv6FlowPutKey->l4.tpSrc; tcpKey.tcp_dst = ipv6FlowPutKey->l4.tpDst; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_TCP, (PCHAR)(&tcpKey), sizeof(tcpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } case IPPROTO_UDP: { struct ovs_key_udp udpKey; udpKey.udp_src = ipv6FlowPutKey->l4.tpSrc; udpKey.udp_dst = ipv6FlowPutKey->l4.tpDst; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_UDP, (PCHAR)(&udpKey), sizeof(udpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } case IPPROTO_SCTP: { struct ovs_key_sctp sctpKey; sctpKey.sctp_src = ipv6FlowPutKey->l4.tpSrc; sctpKey.sctp_dst = ipv6FlowPutKey->l4.tpDst; if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_SCTP, (PCHAR)(&sctpKey), sizeof(sctpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } case IPPROTO_ICMPV6: { struct ovs_key_icmpv6 icmpV6Key; struct ovs_key_nd ndKey; /* XXX: revisit to see if htons is needed */ icmpV6Key.icmpv6_type = (__u8)(icmpv6FlowPutKey->l4.tpSrc); icmpV6Key.icmpv6_code = (__u8)(icmpv6FlowPutKey->l4.tpDst); if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ICMPV6, (PCHAR)(&icmpV6Key), sizeof(icmpV6Key))) { rc = STATUS_UNSUCCESSFUL; goto done; } RtlCopyMemory(&(ndKey.nd_target), &icmpv6FlowPutKey->ndTarget, sizeof(icmpv6FlowPutKey->ndTarget)); RtlCopyMemory(&(ndKey.nd_sll), &icmpv6FlowPutKey->arpSha, ETH_ADDR_LEN); RtlCopyMemory(&(ndKey.nd_tll), &icmpv6FlowPutKey->arpTha, ETH_ADDR_LEN); if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ND, (PCHAR)(&ndKey), sizeof(ndKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } break; } default: break; } done: return rc; } /* *---------------------------------------------------------------------------- * _MapFlowArpKeyToNlKey -- * Maps _MapFlowArpKeyToNlKey to OVS_KEY_ATTR_ARP attribute. *---------------------------------------------------------------------------- */ static NTSTATUS _MapFlowArpKeyToNlKey(PNL_BUFFER nlBuf, ArpKey *arpFlowPutKey) { NTSTATUS rc = STATUS_SUCCESS; struct ovs_key_arp arpKey; arpKey.arp_sip = arpFlowPutKey->nwSrc; arpKey.arp_tip = arpFlowPutKey->nwDst; RtlCopyMemory(&(arpKey.arp_sha), arpFlowPutKey->arpSha, ETH_ADDR_LEN); RtlCopyMemory(&(arpKey.arp_tha), arpFlowPutKey->arpTha, ETH_ADDR_LEN); /* * Flow_Extract() stores 'nwProto' in host order for ARP since 'nwProto' is * 1 byte field and the ARP opcode is 2 bytes, and all of the kernel code * understand this while looking at an ARP key. * While we pass up the ARP key to userspace, convert from host order to * network order. Likewise, when processing an ARP key from userspace, * convert from network order to host order. * * It is important to note that the flow table stores the ARP opcode field * in host order. */ arpKey.arp_op = htons(arpFlowPutKey->nwProto); if (!NlMsgPutTailUnspec(nlBuf, OVS_KEY_ATTR_ARP, (PCHAR)(&arpKey), sizeof(arpKey))) { rc = STATUS_UNSUCCESSFUL; goto done; } done: return rc; } /* *---------------------------------------------------------------------------- * _MapNlToFlowPut -- * Maps input netlink message to OvsFlowPut. *---------------------------------------------------------------------------- */ static NTSTATUS _MapNlToFlowPut(POVS_MESSAGE msgIn, PNL_ATTR keyAttr, PNL_ATTR actionAttr, PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow) { NTSTATUS rc = STATUS_SUCCESS; PNL_MSG_HDR nlMsgHdr = &(msgIn->nlMsg); PGENL_MSG_HDR genlMsgHdr = &(msgIn->genlMsg); POVS_HDR ovsHdr = &(msgIn->ovsHdr); UINT32 keyAttrOffset = (UINT32)((PCHAR)keyAttr - (PCHAR)nlMsgHdr); UINT32 tunnelKeyAttrOffset; PNL_ATTR keyAttrs[__OVS_KEY_ATTR_MAX] = {NULL}; PNL_ATTR tunnelAttrs[__OVS_TUNNEL_KEY_ATTR_MAX] = {NULL}; /* Get flow keys attributes */ if ((NlAttrParseNested(nlMsgHdr, keyAttrOffset, NlAttrLen(keyAttr), nlFlowKeyPolicy, ARRAY_SIZE(nlFlowKeyPolicy), keyAttrs, ARRAY_SIZE(keyAttrs))) != TRUE) { OVS_LOG_ERROR("Key Attr Parsing failed for msg: %p", nlMsgHdr); rc = STATUS_INVALID_PARAMETER; goto done; } if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) { tunnelKeyAttrOffset = (UINT32)((PCHAR) (keyAttrs[OVS_KEY_ATTR_TUNNEL]) - (PCHAR)nlMsgHdr); /* Get tunnel keys attributes */ if ((NlAttrParseNested(nlMsgHdr, tunnelKeyAttrOffset, NlAttrLen(keyAttrs[OVS_KEY_ATTR_TUNNEL]), nlFlowTunnelKeyPolicy, ARRAY_SIZE(nlFlowTunnelKeyPolicy), tunnelAttrs, ARRAY_SIZE(tunnelAttrs))) != TRUE) { OVS_LOG_ERROR("Tunnel key Attr Parsing failed for msg: %p", nlMsgHdr); rc = STATUS_INVALID_PARAMETER; goto done; } } _MapKeyAttrToFlowPut(keyAttrs, tunnelAttrs, &(mappedFlow->key)); /* Map the action */ if (actionAttr) { mappedFlow->actionsLen = NlAttrGetSize(actionAttr); mappedFlow->actions = NlAttrGet(actionAttr); } mappedFlow->dpNo = ovsHdr->dp_ifindex; _MapNlToFlowPutFlags(genlMsgHdr, flowAttrClear, mappedFlow); done: return rc; } /* *---------------------------------------------------------------------------- * _MapNlToFlowPutFlags -- * Maps netlink message to OvsFlowPut->flags. *---------------------------------------------------------------------------- */ static VOID _MapNlToFlowPutFlags(PGENL_MSG_HDR genlMsgHdr, PNL_ATTR flowAttrClear, OvsFlowPut *mappedFlow) { uint32_t flags = 0; switch (genlMsgHdr->cmd) { case OVS_FLOW_CMD_NEW: flags |= OVSWIN_FLOW_PUT_CREATE; break; case OVS_FLOW_CMD_DEL: flags |= OVSWIN_FLOW_PUT_DELETE; break; case OVS_FLOW_CMD_SET: flags |= OVSWIN_FLOW_PUT_MODIFY; break; default: ASSERT(0); } if (flowAttrClear) { flags |= OVSWIN_FLOW_PUT_CLEAR; } mappedFlow->flags = flags; } /* *---------------------------------------------------------------------------- * _MapKeyAttrToFlowPut -- * Converts FLOW_KEY attribute to OvsFlowPut->key. *---------------------------------------------------------------------------- */ static VOID _MapKeyAttrToFlowPut(PNL_ATTR *keyAttrs, PNL_ATTR *tunnelAttrs, OvsFlowKey *destKey) { _MapTunAttrToFlowPut(keyAttrs, tunnelAttrs, destKey); /* ===== L2 headers ===== */ destKey->l2.inPort = NlAttrGetU32(keyAttrs[OVS_KEY_ATTR_IN_PORT]); if (keyAttrs[OVS_KEY_ATTR_ETHERNET]) { const struct ovs_key_ethernet *eth_key; eth_key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ETHERNET]); RtlCopyMemory(destKey->l2.dlSrc, eth_key->eth_src, ETH_ADDR_LEN); RtlCopyMemory(destKey->l2.dlDst, eth_key->eth_dst, ETH_ADDR_LEN); } /* TODO: Ideally ETHERTYPE should not be optional. * But during vswitchd bootup we are seeing FLOW_ADD * requests with no ETHERTYPE attributes. * Need to verify this. */ if (keyAttrs[OVS_KEY_ATTR_ETHERTYPE]) { destKey->l2.dlType = (NlAttrGetU16(keyAttrs [OVS_KEY_ATTR_ETHERTYPE])); } if (keyAttrs[OVS_KEY_ATTR_VLAN]) { destKey->l2.vlanTci = NlAttrGetU16(keyAttrs[OVS_KEY_ATTR_VLAN]); } /* ==== L3 + L4. ==== */ destKey->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - destKey->l2.offset; switch (ntohs(destKey->l2.dlType)) { case ETH_TYPE_IPV4: { if (keyAttrs[OVS_KEY_ATTR_IPV4]) { const struct ovs_key_ipv4 *ipv4Key; ipv4Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV4]); IpKey *ipv4FlowPutKey = &(destKey->ipKey); ipv4FlowPutKey->nwSrc = ipv4Key->ipv4_src; ipv4FlowPutKey->nwDst = ipv4Key->ipv4_dst; ipv4FlowPutKey->nwProto = ipv4Key->ipv4_proto; ipv4FlowPutKey->nwTos = ipv4Key->ipv4_tos; ipv4FlowPutKey->nwTtl = ipv4Key->ipv4_ttl; ipv4FlowPutKey->nwFrag = ipv4Key->ipv4_frag; if (keyAttrs[OVS_KEY_ATTR_TCP]) { const struct ovs_key_tcp *tcpKey; tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]); ipv4FlowPutKey->l4.tpSrc = tcpKey->tcp_src; ipv4FlowPutKey->l4.tpDst = tcpKey->tcp_dst; } if (keyAttrs[OVS_KEY_ATTR_UDP]) { const struct ovs_key_udp *udpKey; udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]); ipv4FlowPutKey->l4.tpSrc = udpKey->udp_src; ipv4FlowPutKey->l4.tpDst = udpKey->udp_dst; } if (keyAttrs[OVS_KEY_ATTR_SCTP]) { const struct ovs_key_sctp *sctpKey; sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]); ipv4FlowPutKey->l4.tpSrc = sctpKey->sctp_src; ipv4FlowPutKey->l4.tpDst = sctpKey->sctp_dst; } destKey->l2.keyLen += OVS_IP_KEY_SIZE; } break; } case ETH_TYPE_IPV6: { if (keyAttrs[OVS_KEY_ATTR_IPV6]) { const struct ovs_key_ipv6 *ipv6Key; ipv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_IPV6]); Ipv6Key *ipv6FlowPutKey = &(destKey->ipv6Key); RtlCopyMemory(&ipv6FlowPutKey->ipv6Src, ipv6Key->ipv6_src, sizeof ipv6Key->ipv6_src); RtlCopyMemory(&ipv6FlowPutKey->ipv6Dst, ipv6Key->ipv6_dst, sizeof ipv6Key->ipv6_dst); ipv6FlowPutKey->ipv6Label = ipv6Key->ipv6_label; ipv6FlowPutKey->nwProto = ipv6Key->ipv6_proto; ipv6FlowPutKey->nwTos = ipv6Key->ipv6_tclass; ipv6FlowPutKey->nwTtl = ipv6Key->ipv6_hlimit; ipv6FlowPutKey->nwFrag = ipv6Key->ipv6_frag; if (keyAttrs[OVS_KEY_ATTR_TCP]) { const struct ovs_key_tcp *tcpKey; tcpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_TCP]); ipv6FlowPutKey->l4.tpSrc = tcpKey->tcp_src; ipv6FlowPutKey->l4.tpDst = tcpKey->tcp_dst; } if (keyAttrs[OVS_KEY_ATTR_UDP]) { const struct ovs_key_udp *udpKey; udpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_UDP]); ipv6FlowPutKey->l4.tpSrc = udpKey->udp_src; ipv6FlowPutKey->l4.tpDst = udpKey->udp_dst; } if (keyAttrs[OVS_KEY_ATTR_SCTP]) { const struct ovs_key_sctp *sctpKey; sctpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_SCTP]); ipv6FlowPutKey->l4.tpSrc = sctpKey->sctp_src; ipv6FlowPutKey->l4.tpDst = sctpKey->sctp_dst; } if (keyAttrs[OVS_KEY_ATTR_ICMPV6]) { const struct ovs_key_icmpv6 *icmpv6Key; Icmp6Key *icmp6FlowPutKey= &(destKey->icmp6Key); icmpv6Key = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ICMPV6]); icmp6FlowPutKey->l4.tpSrc = icmpv6Key->icmpv6_type; icmp6FlowPutKey->l4.tpDst = icmpv6Key->icmpv6_code; if (keyAttrs[OVS_KEY_ATTR_ND]) { const struct ovs_key_nd *ndKey; ndKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ND]); RtlCopyMemory(&icmp6FlowPutKey->ndTarget, ndKey->nd_target, sizeof (icmp6FlowPutKey->ndTarget)); RtlCopyMemory(icmp6FlowPutKey->arpSha, ndKey->nd_sll, ETH_ADDR_LEN); RtlCopyMemory(icmp6FlowPutKey->arpTha, ndKey->nd_tll, ETH_ADDR_LEN); } destKey->l2.keyLen += OVS_ICMPV6_KEY_SIZE; } else { destKey->l2.keyLen += OVS_IPV6_KEY_SIZE; } ipv6FlowPutKey->pad = 0; } break; } case ETH_TYPE_ARP: case ETH_TYPE_RARP: { if (keyAttrs[OVS_KEY_ATTR_ARP]) { ArpKey *arpFlowPutKey = &destKey->arpKey; const struct ovs_key_arp *arpKey; arpKey = NlAttrGet(keyAttrs[OVS_KEY_ATTR_ARP]); arpFlowPutKey->nwSrc = arpKey->arp_sip; arpFlowPutKey->nwDst = arpKey->arp_tip; RtlCopyMemory(arpFlowPutKey->arpSha, arpKey->arp_sha, ETH_ADDR_LEN); RtlCopyMemory(arpFlowPutKey->arpTha, arpKey->arp_tha, ETH_ADDR_LEN); /* Kernel datapath assumes 'arpFlowPutKey->nwProto' to be in host * order. */ arpFlowPutKey->nwProto = (UINT8)ntohs((arpKey->arp_op)); arpFlowPutKey->pad[0] = 0; arpFlowPutKey->pad[1] = 0; arpFlowPutKey->pad[2] = 0; destKey->l2.keyLen += OVS_ARP_KEY_SIZE; break; } } } } /* *---------------------------------------------------------------------------- * _MapTunAttrToFlowPut -- * Converts FLOW_TUNNEL_KEY attribute to OvsFlowKey->tunKey. *---------------------------------------------------------------------------- */ static VOID _MapTunAttrToFlowPut(PNL_ATTR *keyAttrs, PNL_ATTR *tunAttrs, OvsFlowKey *destKey) { if (keyAttrs[OVS_KEY_ATTR_TUNNEL]) { if (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]) { destKey->tunKey.tunnelId = NlAttrGetU64 (tunAttrs[OVS_TUNNEL_KEY_ATTR_ID]); destKey->tunKey.flags |= OVS_TNL_F_KEY; } if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]) { destKey->tunKey.dst = NlAttrGetU32 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_DST]); } if (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]) { destKey->tunKey.src = NlAttrGetU32 (tunAttrs[OVS_TUNNEL_KEY_ATTR_IPV4_SRC]); } if (tunAttrs[OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT]) { destKey->tunKey.flags |= OVS_TNL_F_DONT_FRAGMENT; } if (tunAttrs[OVS_TUNNEL_KEY_ATTR_CSUM]) { destKey->tunKey.flags |= OVS_TNL_F_CSUM; } if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]) { destKey->tunKey.tos = NlAttrGetU8 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TOS]); } if (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]) { destKey->tunKey.ttl = NlAttrGetU8 (tunAttrs[OVS_TUNNEL_KEY_ATTR_TTL]); } destKey->tunKey.pad = 0; destKey->l2.offset = 0; } else { destKey->tunKey.attr[0] = 0; destKey->tunKey.attr[1] = 0; destKey->tunKey.attr[2] = 0; destKey->l2.offset = sizeof destKey->tunKey; } } /* *---------------------------------------------------------------------------- * OvsDeleteFlowTable -- * Results: * NDIS_STATUS_SUCCESS always. *---------------------------------------------------------------------------- */ NDIS_STATUS OvsDeleteFlowTable(OVS_DATAPATH *datapath) { if (datapath == NULL || datapath->flowTable == NULL) { return NDIS_STATUS_SUCCESS; } DeleteAllFlows(datapath); OvsFreeMemoryWithTag(datapath->flowTable, OVS_FLOW_POOL_TAG); datapath->flowTable = NULL; if (datapath->lock == NULL) { return NDIS_STATUS_SUCCESS; } NdisFreeRWLock(datapath->lock); return NDIS_STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * OvsAllocateFlowTable -- * Results: * NDIS_STATUS_SUCCESS on success. * NDIS_STATUS_RESOURCES if memory couldn't be allocated *---------------------------------------------------------------------------- */ NDIS_STATUS OvsAllocateFlowTable(OVS_DATAPATH *datapath, POVS_SWITCH_CONTEXT switchContext) { PLIST_ENTRY bucket; int i; datapath->flowTable = OvsAllocateMemoryWithTag( OVS_FLOW_TABLE_SIZE * sizeof(LIST_ENTRY), OVS_FLOW_POOL_TAG); if (!datapath->flowTable) { return NDIS_STATUS_RESOURCES; } for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) { bucket = &(datapath->flowTable[i]); InitializeListHead(bucket); } datapath->lock = NdisAllocateRWLock(switchContext->NdisFilterHandle); if (!datapath->lock) { return NDIS_STATUS_RESOURCES; } return NDIS_STATUS_SUCCESS; } /* *---------------------------------------------------------------------------- * GetStartAddrNBL -- * Get the virtual address of the frame. * * Results: * Virtual address of the frame. *---------------------------------------------------------------------------- */ static __inline VOID * GetStartAddrNBL(const NET_BUFFER_LIST *_pNB) { PMDL curMdl; PUINT8 curBuffer; PEthHdr curHeader; ASSERT(_pNB); // Ethernet Header is a guaranteed safe access. curMdl = (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdl; curBuffer = MmGetSystemAddressForMdlSafe(curMdl, LowPagePriority); if (!curBuffer) { return NULL; } curHeader = (PEthHdr) (curBuffer + (NET_BUFFER_LIST_FIRST_NB(_pNB))->CurrentMdlOffset); return (VOID *) curHeader; } VOID OvsFlowUsed(OvsFlow *flow, const NET_BUFFER_LIST *packet, const POVS_PACKET_HDR_INFO layers) { LARGE_INTEGER tickCount; KeQueryTickCount(&tickCount); flow->used = tickCount.QuadPart * ovsTimeIncrementPerTick; flow->packetCount++; flow->byteCount += OvsPacketLenNBL(packet); flow->tcpFlags |= OvsGetTcpFlags(packet, &flow->key, layers); } VOID DeleteAllFlows(OVS_DATAPATH *datapath) { INT i; PLIST_ENTRY bucket; for (i = 0; i < OVS_FLOW_TABLE_SIZE; i++) { PLIST_ENTRY next; bucket = &(datapath->flowTable[i]); while (!IsListEmpty(bucket)) { OvsFlow *flow; next = bucket->Flink; flow = CONTAINING_RECORD(next, OvsFlow, ListEntry); RemoveFlow(datapath, &flow); } } } /* *---------------------------------------------------------------------------- * Initializes 'flow' members from 'packet', 'skb_priority', 'tun_id', and * 'ofp_in_port'. * * Initializes 'packet' header pointers as follows: * * - packet->l2 to the start of the Ethernet header. * * - packet->l3 to just past the Ethernet header, or just past the * vlan_header if one is present, to the first byte of the payload of the * Ethernet frame. * * - packet->l4 to just past the IPv4 header, if one is present and has a * correct length, and otherwise NULL. * * - packet->l7 to just past the TCP, UDP, SCTP or ICMP header, if one is * present and has a correct length, and otherwise NULL. * * Returns NDIS_STATUS_SUCCESS normally. Fails only if packet data cannot be accessed * (e.g. if Pkt_CopyBytesOut() returns an error). *---------------------------------------------------------------------------- */ NDIS_STATUS OvsExtractFlow(const NET_BUFFER_LIST *packet, UINT32 inPort, OvsFlowKey *flow, POVS_PACKET_HDR_INFO layers, OvsIPv4TunnelKey *tunKey) { struct Eth_Header *eth; UINT8 offset = 0; PVOID vlanTagValue; layers->value = 0; if (tunKey) { ASSERT(tunKey->dst != 0); RtlMoveMemory(&flow->tunKey, tunKey, sizeof flow->tunKey); flow->l2.offset = 0; } else { flow->tunKey.dst = 0; flow->l2.offset = OVS_WIN_TUNNEL_KEY_SIZE; } flow->l2.inPort = inPort; if ( OvsPacketLenNBL(packet) < ETH_HEADER_LEN_DIX) { flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + 8 - flow->l2.offset; return NDIS_STATUS_SUCCESS; } /* Link layer. */ eth = (Eth_Header *)GetStartAddrNBL((NET_BUFFER_LIST *)packet); memcpy(flow->l2.dlSrc, eth->src, ETH_ADDR_LENGTH); memcpy(flow->l2.dlDst, eth->dst, ETH_ADDR_LENGTH); /* * vlan_tci. */ vlanTagValue = NET_BUFFER_LIST_INFO(packet, Ieee8021QNetBufferListInfo); if (vlanTagValue) { PNDIS_NET_BUFFER_LIST_8021Q_INFO vlanTag = (PNDIS_NET_BUFFER_LIST_8021Q_INFO)(PVOID *)&vlanTagValue; flow->l2.vlanTci = htons(vlanTag->TagHeader.VlanId | OVSWIN_VLAN_CFI | (vlanTag->TagHeader.UserPriority << 13)); } else { if (eth->dix.typeNBO == ETH_TYPE_802_1PQ_NBO) { Eth_802_1pq_Tag *tag= (Eth_802_1pq_Tag *)ð->dix.typeNBO; flow->l2.vlanTci = ((UINT16)tag->priority << 13) | OVSWIN_VLAN_CFI | ((UINT16)tag->vidHi << 8) | tag->vidLo; offset = sizeof (Eth_802_1pq_Tag); } else { flow->l2.vlanTci = 0; } /* * XXX * Please note after this point, src mac and dst mac should * not be accessed through eth */ eth = (Eth_Header *)((UINT8 *)eth + offset); } /* * dl_type. * * XXX assume that at least the first * 12 bytes of received packets are mapped. This code has the stronger * assumption that at least the first 22 bytes of 'packet' is mapped (if my * arithmetic is right). */ if (ETH_TYPENOT8023(eth->dix.typeNBO)) { flow->l2.dlType = eth->dix.typeNBO; layers->l3Offset = ETH_HEADER_LEN_DIX + offset; } else if (OvsPacketLenNBL(packet) >= ETH_HEADER_LEN_802_3 && eth->e802_3.llc.dsap == 0xaa && eth->e802_3.llc.ssap == 0xaa && eth->e802_3.llc.control == ETH_LLC_CONTROL_UFRAME && eth->e802_3.snap.snapOrg[0] == 0x00 && eth->e802_3.snap.snapOrg[1] == 0x00 && eth->e802_3.snap.snapOrg[2] == 0x00) { flow->l2.dlType = eth->e802_3.snap.snapType.typeNBO; layers->l3Offset = ETH_HEADER_LEN_802_3 + offset; } else { flow->l2.dlType = htons(OVSWIN_DL_TYPE_NONE); layers->l3Offset = ETH_HEADER_LEN_DIX + offset; } flow->l2.keyLen = OVS_WIN_TUNNEL_KEY_SIZE + OVS_L2_KEY_SIZE - flow->l2.offset; /* Network layer. */ if (flow->l2.dlType == htons(ETH_TYPE_IPV4)) { struct IPHdr ip_storage; const struct IPHdr *nh; IpKey *ipKey = &flow->ipKey; flow->l2.keyLen += OVS_IP_KEY_SIZE; layers->isIPv4 = 1; nh = OvsGetIp(packet, layers->l3Offset, &ip_storage); if (nh) { layers->l4Offset = layers->l3Offset + nh->ihl * 4; ipKey->nwSrc = nh->saddr; ipKey->nwDst = nh->daddr; ipKey->nwProto = nh->protocol; ipKey->nwTos = nh->tos; if (nh->frag_off & htons(IP_MF | IP_OFFSET)) { ipKey->nwFrag = OVS_FRAG_TYPE_FIRST; if (nh->frag_off & htons(IP_OFFSET)) { ipKey->nwFrag = OVS_FRAG_TYPE_LATER; } } else { ipKey->nwFrag = OVS_FRAG_TYPE_NONE; } ipKey->nwTtl = nh->ttl; ipKey->l4.tpSrc = 0; ipKey->l4.tpDst = 0; if (!(nh->frag_off & htons(IP_OFFSET))) { if (ipKey->nwProto == SOCKET_IPPROTO_TCP) { OvsParseTcp(packet, &ipKey->l4, layers); } else if (ipKey->nwProto == SOCKET_IPPROTO_UDP) { OvsParseUdp(packet, &ipKey->l4, layers); } else if (ipKey->nwProto == SOCKET_IPPROTO_SCTP) { OvsParseSctp(packet, &ipKey->l4, layers); } else if (ipKey->nwProto == SOCKET_IPPROTO_ICMP) { ICMPHdr icmpStorage; const ICMPHdr *icmp; icmp = OvsGetIcmp(packet, layers->l4Offset, &icmpStorage); if (icmp) { ipKey->l4.tpSrc = htons(icmp->type); ipKey->l4.tpDst = htons(icmp->code); layers->l7Offset = layers->l4Offset + sizeof *icmp; } } } } else { ((UINT64 *)ipKey)[0] = 0; ((UINT64 *)ipKey)[1] = 0; } } else if (flow->l2.dlType == htons(ETH_TYPE_IPV6)) { NDIS_STATUS status; flow->l2.keyLen += OVS_IPV6_KEY_SIZE; status = OvsParseIPv6(packet, flow, layers); if (status != NDIS_STATUS_SUCCESS) { memset(&flow->ipv6Key, 0, sizeof (Ipv6Key)); return status; } layers->isIPv6 = 1; flow->ipv6Key.l4.tpSrc = 0; flow->ipv6Key.l4.tpDst = 0; flow->ipv6Key.pad = 0; if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_TCP) { OvsParseTcp(packet, &(flow->ipv6Key.l4), layers); } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_UDP) { OvsParseUdp(packet, &(flow->ipv6Key.l4), layers); } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_SCTP) { OvsParseSctp(packet, &flow->ipv6Key.l4, layers); } else if (flow->ipv6Key.nwProto == SOCKET_IPPROTO_ICMPV6) { OvsParseIcmpV6(packet, flow, layers); flow->l2.keyLen += (OVS_ICMPV6_KEY_SIZE - OVS_IPV6_KEY_SIZE); } } else if (flow->l2.dlType == htons(ETH_TYPE_ARP)) { EtherArp arpStorage; const EtherArp *arp; ArpKey *arpKey = &flow->arpKey; ((UINT64 *)arpKey)[0] = 0; ((UINT64 *)arpKey)[1] = 0; ((UINT64 *)arpKey)[2] = 0; flow->l2.keyLen += OVS_ARP_KEY_SIZE; arp = OvsGetArp(packet, layers->l3Offset, &arpStorage); if (arp && arp->ea_hdr.ar_hrd == htons(1) && arp->ea_hdr.ar_pro == htons(ETH_TYPE_IPV4) && arp->ea_hdr.ar_hln == ETH_ADDR_LENGTH && arp->ea_hdr.ar_pln == 4) { /* We only match on the lower 8 bits of the opcode. */ if (ntohs(arp->ea_hdr.ar_op) <= 0xff) { arpKey->nwProto = (UINT8)ntohs(arp->ea_hdr.ar_op); } if (arpKey->nwProto == ARPOP_REQUEST || arpKey->nwProto == ARPOP_REPLY) { memcpy(&arpKey->nwSrc, arp->arp_spa, 4); memcpy(&arpKey->nwDst, arp->arp_tpa, 4); memcpy(arpKey->arpSha, arp->arp_sha, ETH_ADDR_LENGTH); memcpy(arpKey->arpTha, arp->arp_tha, ETH_ADDR_LENGTH); } } } return NDIS_STATUS_SUCCESS; } __inline BOOLEAN FlowEqual(UINT64 *src, UINT64 *dst, UINT32 size) { UINT32 i; ASSERT((size & 0x7) == 0); ASSERT(((UINT64)src & 0x7) == 0); ASSERT(((UINT64)dst & 0x7) == 0); for (i = 0; i < (size >> 3); i++) { if (src[i] != dst[i]) { return FALSE; } } return TRUE; } /* * ---------------------------------------------------------------------------- * AddFlow -- * Add a flow to flow table. * * Results: * NDIS_STATUS_SUCCESS if no same flow in the flow table. * ---------------------------------------------------------------------------- */ NTSTATUS AddFlow(OVS_DATAPATH *datapath, OvsFlow *flow) { PLIST_ENTRY head; if (OvsLookupFlow(datapath, &flow->key, &flow->hash, TRUE) != NULL) { return STATUS_INVALID_HANDLE; } head = &(datapath->flowTable[HASH_BUCKET(flow->hash)]); /* * We need fence here to make sure flow's nextPtr is updated before * head->nextPtr is updated. */ KeMemoryBarrier(); //KeAcquireSpinLock(&FilterDeviceExtension->NblQueueLock, &oldIrql); InsertTailList(head, &flow->ListEntry); //KeReleaseSpinLock(&FilterDeviceExtension->NblQueueLock, oldIrql); datapath->nFlows++; return STATUS_SUCCESS; } /* ---------------------------------------------------------------------------- * RemoveFlow -- * Remove a flow from flow table, and added to wait list * ---------------------------------------------------------------------------- */ VOID RemoveFlow(OVS_DATAPATH *datapath, OvsFlow **flow) { OvsFlow *f = *flow; *flow = NULL; ASSERT(datapath->nFlows); datapath->nFlows--; // Remove the flow from queue RemoveEntryList(&f->ListEntry); FreeFlow(f); } /* * ---------------------------------------------------------------------------- * OvsLookupFlow -- * * Find flow from flow table based on flow key. * Caller should either hold portset handle or should * have a flowRef in datapath or Acquired datapath. * * Results: * Flow pointer if lookup successful. * NULL if not exists. * ---------------------------------------------------------------------------- */ OvsFlow * OvsLookupFlow(OVS_DATAPATH *datapath, const OvsFlowKey *key, UINT64 *hash, BOOLEAN hashValid) { PLIST_ENTRY link, head; UINT16 offset = key->l2.offset; UINT16 size = key->l2.keyLen; UINT8 *start; ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey)); ASSERT(!key->tunKey.dst || offset == 0); start = (UINT8 *)key + offset; if (!hashValid) { *hash = OvsJhashBytes(start, size, 0); } head = &datapath->flowTable[HASH_BUCKET(*hash)]; link = head->Flink; while (link != head) { OvsFlow *flow = CONTAINING_RECORD(link, OvsFlow, ListEntry); if (flow->hash == *hash && flow->key.l2.val == key->l2.val && FlowEqual((UINT64 *)((uint8 *)&flow->key + offset), (UINT64 *)start, size)) { return flow; } link = link->Flink; } return NULL; } /* * ---------------------------------------------------------------------------- * OvsHashFlow -- * Calculate the hash for the given flow key. * ---------------------------------------------------------------------------- */ UINT64 OvsHashFlow(const OvsFlowKey *key) { UINT16 offset = key->l2.offset; UINT16 size = key->l2.keyLen; UINT8 *start; ASSERT(key->tunKey.dst || offset == sizeof (OvsIPv4TunnelKey)); ASSERT(!key->tunKey.dst || offset == 0); start = (UINT8 *)key + offset; return OvsJhashBytes(start, size, 0); } /* * ---------------------------------------------------------------------------- * FreeFlow -- * Free a flow and its actions. * ---------------------------------------------------------------------------- */ VOID FreeFlow(OvsFlow *flow) { ASSERT(flow); OvsFreeMemoryWithTag(flow, OVS_FLOW_POOL_TAG); } NTSTATUS OvsDoDumpFlows(OvsFlowDumpInput *dumpInput, OvsFlowDumpOutput *dumpOutput, UINT32 *replyLen) { UINT32 dpNo; OVS_DATAPATH *datapath = NULL; OvsFlow *flow; PLIST_ENTRY node, head; UINT32 column = 0; UINT32 rowIndex, columnIndex; LOCK_STATE_EX dpLockState; NTSTATUS status = STATUS_SUCCESS; BOOLEAN findNextNonEmpty = FALSE; dpNo = dumpInput->dpNo; if (gOvsSwitchContext->dpNo != dpNo) { status = STATUS_INVALID_PARAMETER; goto exit; } rowIndex = dumpInput->position[0]; if (rowIndex >= OVS_FLOW_TABLE_SIZE) { dumpOutput->n = 0; *replyLen = sizeof(*dumpOutput); goto exit; } columnIndex = dumpInput->position[1]; datapath = &gOvsSwitchContext->datapath; ASSERT(datapath); OvsAcquireDatapathRead(datapath, &dpLockState, FALSE); head = &datapath->flowTable[rowIndex]; node = head->Flink; while (column < columnIndex) { if (node == head) { break; } node = node->Flink; column++; } if (node == head) { findNextNonEmpty = TRUE; columnIndex = 0; } if (findNextNonEmpty) { while (head == node) { if (++rowIndex >= OVS_FLOW_TABLE_SIZE) { dumpOutput->n = 0; goto dp_unlock; } head = &datapath->flowTable[rowIndex]; node = head->Flink; } } ASSERT(node != head); ASSERT(rowIndex < OVS_FLOW_TABLE_SIZE); flow = CONTAINING_RECORD(node, OvsFlow, ListEntry); status = ReportFlowInfo(flow, dumpInput->getFlags, &dumpOutput->flow); if (status == STATUS_BUFFER_TOO_SMALL) { dumpOutput->n = sizeof(OvsFlowDumpOutput) + flow->actionsLen; *replyLen = sizeof(*dumpOutput); } else { dumpOutput->n = 1; //one flow reported. *replyLen = sizeof(*dumpOutput) + dumpOutput->flow.actionsLen; } dumpOutput->position[0] = rowIndex; dumpOutput->position[1] = ++columnIndex; dp_unlock: OvsReleaseDatapath(datapath, &dpLockState); exit: return status; } static NTSTATUS ReportFlowInfo(OvsFlow *flow, UINT32 getFlags, OvsFlowInfo *info) { NTSTATUS status = STATUS_SUCCESS; if (getFlags & FLOW_GET_KEY) { // always copy the tunnel key part RtlCopyMemory(&info->key, &flow->key, flow->key.l2.keyLen + flow->key.l2.offset); } if (getFlags & FLOW_GET_STATS) { OvsFlowStats *stats = &info->stats; stats->packetCount = flow->packetCount; stats->byteCount = flow->byteCount; stats->used = (UINT32)flow->used; stats->tcpFlags = flow->tcpFlags; } if (getFlags & FLOW_GET_ACTIONS) { if (flow->actionsLen == 0) { info->actionsLen = 0; } else { info->actions = flow->actions; info->actionsLen = flow->actionsLen; } } return status; } NTSTATUS OvsPutFlowIoctl(PVOID inputBuffer, UINT32 inputLength, struct OvsFlowStats *stats) { NTSTATUS status = STATUS_SUCCESS; OVS_DATAPATH *datapath = NULL; ULONG actionsLen; OvsFlowPut *put; UINT32 dpNo; LOCK_STATE_EX dpLockState; if ((inputLength < sizeof(OvsFlowPut)) || (inputBuffer == NULL)) { return STATUS_INFO_LENGTH_MISMATCH; } put = (OvsFlowPut *)inputBuffer; if (put->actionsLen > 0) { actionsLen = put->actionsLen; } else { actionsLen = 0; } dpNo = put->dpNo; if (gOvsSwitchContext->dpNo != dpNo) { status = STATUS_INVALID_PARAMETER; goto exit; } datapath = &gOvsSwitchContext->datapath; ASSERT(datapath); OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE); status = HandleFlowPut(put, datapath, stats); OvsReleaseDatapath(datapath, &dpLockState); exit: return status; } /* Handles flow add, modify as well as delete */ static NTSTATUS HandleFlowPut(OvsFlowPut *put, OVS_DATAPATH *datapath, struct OvsFlowStats *stats) { BOOLEAN mayCreate, mayModify, mayDelete; OvsFlow *KernelFlow; UINT64 hash; NTSTATUS status = STATUS_SUCCESS; mayCreate = (put->flags & OVSWIN_FLOW_PUT_CREATE) != 0; mayModify = (put->flags & OVSWIN_FLOW_PUT_MODIFY) != 0; mayDelete = (put->flags & OVSWIN_FLOW_PUT_DELETE) != 0; if ((mayCreate || mayModify) == mayDelete) { return STATUS_INVALID_PARAMETER; } KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, FALSE); if (!KernelFlow) { if (!mayCreate) { return STATUS_INVALID_PARAMETER; } status = OvsPrepareFlow(&KernelFlow, put, hash); if (status != STATUS_SUCCESS) { return STATUS_UNSUCCESSFUL; } status = AddFlow(datapath, KernelFlow); if (status != STATUS_SUCCESS) { FreeFlow(KernelFlow); return STATUS_UNSUCCESSFUL; } /* Validate the flow addition */ { UINT64 newHash; OvsFlow *flow = OvsLookupFlow(datapath, &put->key, &newHash, FALSE); ASSERT(flow); ASSERT(newHash == hash); if (!flow || newHash != hash) { return STATUS_UNSUCCESSFUL; } } } else { stats->packetCount = KernelFlow->packetCount; stats->byteCount = KernelFlow->byteCount; stats->tcpFlags = KernelFlow->tcpFlags; stats->used = (UINT32)KernelFlow->used; if (mayModify) { OvsFlow *newFlow; status = OvsPrepareFlow(&newFlow, put, hash); if (status != STATUS_SUCCESS) { return STATUS_UNSUCCESSFUL; } KernelFlow = OvsLookupFlow(datapath, &put->key, &hash, TRUE); if (KernelFlow) { if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) { newFlow->packetCount = KernelFlow->packetCount; newFlow->byteCount = KernelFlow->byteCount; newFlow->tcpFlags = KernelFlow->tcpFlags; } RemoveFlow(datapath, &KernelFlow); } else { if ((put->flags & OVSWIN_FLOW_PUT_CLEAR) == 0) { newFlow->packetCount = stats->packetCount; newFlow->byteCount = stats->byteCount; newFlow->tcpFlags = stats->tcpFlags; } } status = AddFlow(datapath, newFlow); ASSERT(status == STATUS_SUCCESS); /* Validate the flow addition */ { UINT64 newHash; OvsFlow *testflow = OvsLookupFlow(datapath, &put->key, &newHash, FALSE); ASSERT(testflow); ASSERT(newHash == hash); if (!testflow || newHash != hash) { FreeFlow(newFlow); return STATUS_UNSUCCESSFUL; } } } else { if (mayDelete) { if (KernelFlow) { RemoveFlow(datapath, &KernelFlow); } } else { /* Return success if an identical flow already exists. */ /* XXX: should we return EEXIST in a netlink error? */ return STATUS_SUCCESS; } } } return STATUS_SUCCESS; } static NTSTATUS OvsPrepareFlow(OvsFlow **flow, const OvsFlowPut *put, UINT64 hash) { OvsFlow *localFlow = *flow; NTSTATUS status = STATUS_SUCCESS; do { *flow = localFlow = OvsAllocateMemoryWithTag(sizeof(OvsFlow) + put->actionsLen, OVS_FLOW_POOL_TAG); if (localFlow == NULL) { status = STATUS_NO_MEMORY; break; } localFlow->key = put->key; localFlow->actionsLen = put->actionsLen; if (put->actionsLen) { NdisMoveMemory((PUCHAR)localFlow->actions, put->actions, put->actionsLen); } localFlow->userActionsLen = 0; // 0 indicate no conversion is made localFlow->used = 0; localFlow->packetCount = 0; localFlow->byteCount = 0; localFlow->tcpFlags = 0; localFlow->hash = hash; } while(FALSE); return status; } NTSTATUS OvsGetFlowIoctl(PVOID inputBuffer, PVOID outputBuffer) { NTSTATUS status = STATUS_SUCCESS; OVS_DATAPATH *datapath = NULL; OvsFlow *flow; UINT32 getFlags, getActionsLen; OvsFlowGetInput *getInput; OvsFlowGetOutput *getOutput; UINT64 hash; UINT32 dpNo; LOCK_STATE_EX dpLockState; getInput = (OvsFlowGetInput *) inputBuffer; getFlags = getInput->getFlags; getActionsLen = getInput->actionsLen; if (outputBuffer == NULL) { return STATUS_INFO_LENGTH_MISMATCH; } dpNo = getInput->dpNo; if (gOvsSwitchContext->dpNo != dpNo) { status = STATUS_INVALID_PARAMETER; goto exit; } datapath = &gOvsSwitchContext->datapath; ASSERT(datapath); OvsAcquireDatapathRead(datapath, &dpLockState, FALSE); flow = OvsLookupFlow(datapath, &getInput->key, &hash, FALSE); if (!flow) { status = STATUS_INVALID_PARAMETER; goto dp_unlock; } getOutput = (OvsFlowGetOutput *)outputBuffer; ReportFlowInfo(flow, getFlags, &getOutput->info); dp_unlock: OvsReleaseDatapath(datapath, &dpLockState); exit: return status; } NTSTATUS OvsFlushFlowIoctl(UINT32 dpNo) { NTSTATUS status = STATUS_SUCCESS; OVS_DATAPATH *datapath = NULL; LOCK_STATE_EX dpLockState; if (gOvsSwitchContext->dpNo != dpNo) { status = STATUS_INVALID_PARAMETER; goto exit; } datapath = &gOvsSwitchContext->datapath; ASSERT(datapath); OvsAcquireDatapathWrite(datapath, &dpLockState, FALSE); DeleteAllFlows(datapath); OvsReleaseDatapath(datapath, &dpLockState); exit: return status; } UINT32 OvsFlowKeyAttrSize(void) { return NlAttrTotalSize(4) /* OVS_KEY_ATTR_PRIORITY */ + NlAttrTotalSize(0) /* OVS_KEY_ATTR_TUNNEL */ + OvsTunKeyAttrSize() + NlAttrTotalSize(4) /* OVS_KEY_ATTR_IN_PORT */ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_SKB_MARK */ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_DP_HASH */ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_RECIRC_ID */ + NlAttrTotalSize(12) /* OVS_KEY_ATTR_ETHERNET */ + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */ + NlAttrTotalSize(4) /* OVS_KEY_ATTR_VLAN */ + NlAttrTotalSize(0) /* OVS_KEY_ATTR_ENCAP */ + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ETHERTYPE */ + NlAttrTotalSize(40) /* OVS_KEY_ATTR_IPV6 */ + NlAttrTotalSize(2) /* OVS_KEY_ATTR_ICMPV6 */ + NlAttrTotalSize(28); /* OVS_KEY_ATTR_ND */ } UINT32 OvsTunKeyAttrSize(void) { /* Whenever adding new OVS_TUNNEL_KEY_ FIELDS, we should consider * updating this function. */ return NlAttrTotalSize(8) /* OVS_TUNNEL_KEY_ATTR_ID */ + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_SRC */ + NlAttrTotalSize(4) /* OVS_TUNNEL_KEY_ATTR_IPV4_DST */ + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TOS */ + NlAttrTotalSize(1) /* OVS_TUNNEL_KEY_ATTR_TTL */ + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_DONT_FRAGMENT */ + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_CSUM */ + NlAttrTotalSize(0) /* OVS_TUNNEL_KEY_ATTR_OAM */ + NlAttrTotalSize(256) /* OVS_TUNNEL_KEY_ATTR_GENEVE_OPTS */ + NlAttrTotalSize(2) /* OVS_TUNNEL_KEY_ATTR_TP_SRC */ + NlAttrTotalSize(2); /* OVS_TUNNEL_KEY_ATTR_TP_DST */ } #pragma warning( pop ) openvswitch-2.5.0/datapath-windows/ovsext/PaxHeaders.69223/User.h0000644000000000000000000000013212631676262021541 xustar0030 mtime=1449622706.986439891 30 atime=1456592667.315090569 30 ctime=1456594660.225290164 openvswitch-2.5.0/datapath-windows/ovsext/User.h0000664000175000017500000001051312631676262023231 0ustar00jpettitjpettit00000000000000 /* * Copyright (c) 2014 VMware, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* This file contains structures and function definitions necessary for * forwarding packet to user space. */ #ifndef __USER_H_ #define __USER_H_ 1 #include "Datapath.h" /* * Even we have more cores, I don't think we need * more than 32 queues for processing packets to * userspace */ #define OVS_DEFAULT_PACKET_QUEUE 1 #define OVS_MAX_PACKET_QUEUE_LEN 4096 /* * Only when OVS_PER_VPORT_QUEUE_CTRL is defined * we will apply this constraint */ #define OVS_MAX_PACKETS_PER_VPORT 128 #define OVS_MAX_PACKETS_PER_TUNNEL 1024 typedef struct _OVS_USER_PACKET_QUEUE { UINT32 pid; UINT32 numPackets; LIST_ENTRY packetList; PVOID instance; PIRP pendingIrp; NDIS_SPIN_LOCK queueLock; } OVS_USER_PACKET_QUEUE, *POVS_USER_PACKET_QUEUE; typedef struct _OVS_PACKET_QUEUE_ELEM { UINT32 upcallPid; LIST_ENTRY link; OVS_PACKET_HDR_INFO hdrInfo; OVS_PACKET_INFO packet; } OVS_PACKET_QUEUE_ELEM, *POVS_PACKET_QUEUE_ELEM; struct _OVS_OPEN_INSTANCE; typedef struct _OVS_USER_STATS { UINT64 miss; UINT64 action; UINT32 dropDuetoResource; UINT32 dropDuetoChecksum; UINT32 ipCsum; UINT32 recalTcpCsum; UINT32 vlanInsert; UINT32 l4Csum; } OVS_USER_STATS, *POVS_USER_STATS; VOID OvsCleanupPacketQueue(struct _OVS_OPEN_INSTANCE *instance); POVS_PACKET_QUEUE_ELEM OvsCreateQueueNlPacket(PVOID userData, UINT32 userDataLen, UINT32 cmd, POVS_VPORT_ENTRY vport, OvsFlowKey *key, PNET_BUFFER_LIST nbl, PNET_BUFFER nb, BOOLEAN isRecv, POVS_PACKET_HDR_INFO hdrInfo); VOID OvsQueuePackets(PLIST_ENTRY packetList, UINT32 numElems); NTSTATUS OvsCreateAndAddPackets(PVOID userData, UINT32 userDataLen, UINT32 cmd, POVS_VPORT_ENTRY vport, OvsFlowKey *key, PNET_BUFFER_LIST nbl, BOOLEAN isRecv, POVS_PACKET_HDR_INFO hdrInfo, POVS_SWITCH_CONTEXT switchContext, LIST_ENTRY *list, UINT32 *num); NTSTATUS OvsSubscribeDpIoctl(PVOID instanceP, UINT32 pid, UINT8 join); NTSTATUS OvsReadDpIoctl(PFILE_OBJECT fileObject, PVOID outputBuffer, UINT32 outputLength, UINT32 *replyLen); NTSTATUS OvsExecuteDpIoctl(OvsPacketExecute *execute); NTSTATUS OvsPurgeDpIoctl(PFILE_OBJECT fileObject); NTSTATUS OvsWaitDpIoctl(PIRP irp, PFILE_OBJECT fileObject); NTSTATUS OvsNlExecuteCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); POVS_OPEN_INSTANCE OvsGetPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid); VOID OvsAddPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid, POVS_OPEN_INSTANCE instance); VOID OvsDelPidInstance(POVS_SWITCH_CONTEXT switchContext, UINT32 pid); NTSTATUS OvsReadPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); NTSTATUS OvsSubscribePacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); NTSTATUS OvsPendPacketCmdHandler(POVS_USER_PARAMS_CONTEXT usrParamsCtx, UINT32 *replyLen); #endif /* __USER_H_ */ openvswitch-2.5.0/datapath-windows/PaxHeaders.69223/automake.mk0000644000000000000000000000013112664352753021262 xustar0030 mtime=1456592363.426620342 30 atime=1456592368.170815194 29 ctime=1456594659.58526326 openvswitch-2.5.0/datapath-windows/automake.mk0000664000175000017500000000510212664352753022751 0ustar00jpettitjpettit00000000000000EXTRA_DIST += \ datapath-windows/CodingStyle \ datapath-windows/DESIGN \ datapath-windows/Package/package.VcxProj \ datapath-windows/Package/package.VcxProj.user \ datapath-windows/include/OvsDpInterfaceExt.h \ datapath-windows/misc/OVS.psm1 \ datapath-windows/misc/install.cmd \ datapath-windows/misc/uninstall.cmd \ datapath-windows/ovsext.sln \ datapath-windows/ovsext/Actions.c \ datapath-windows/ovsext/Atomic.h \ datapath-windows/ovsext/BufferMgmt.c \ datapath-windows/ovsext/BufferMgmt.h \ datapath-windows/ovsext/Checksum.c \ datapath-windows/ovsext/Checksum.h \ datapath-windows/ovsext/Datapath.c \ datapath-windows/ovsext/Datapath.h \ datapath-windows/ovsext/Debug.c \ datapath-windows/ovsext/Debug.h \ datapath-windows/ovsext/DpInternal.h\ datapath-windows/ovsext/Driver.c \ datapath-windows/ovsext/Ethernet.h \ datapath-windows/ovsext/Event.c \ datapath-windows/ovsext/Event.h \ datapath-windows/ovsext/Flow.c \ datapath-windows/ovsext/Flow.h \ datapath-windows/ovsext/Gre.h \ datapath-windows/ovsext/Gre.c \ datapath-windows/ovsext/IpHelper.c \ datapath-windows/ovsext/IpHelper.h \ datapath-windows/ovsext/Jhash.c \ datapath-windows/ovsext/Jhash.h \ datapath-windows/ovsext/NetProto.h \ datapath-windows/ovsext/Netlink/Netlink.c \ datapath-windows/ovsext/Netlink/Netlink.h \ datapath-windows/ovsext/Netlink/NetlinkBuf.c \ datapath-windows/ovsext/Netlink/NetlinkBuf.h \ datapath-windows/ovsext/Netlink/NetlinkError.h \ datapath-windows/ovsext/Netlink/NetlinkProto.h \ datapath-windows/ovsext/Oid.c \ datapath-windows/ovsext/Oid.h \ datapath-windows/ovsext/PacketIO.c \ datapath-windows/ovsext/PacketIO.h \ datapath-windows/ovsext/PacketParser.c \ datapath-windows/ovsext/PacketParser.h \ datapath-windows/ovsext/Stt.c \ datapath-windows/ovsext/Stt.h \ datapath-windows/ovsext/Switch.c \ datapath-windows/ovsext/Switch.h \ datapath-windows/ovsext/Tunnel.c \ datapath-windows/ovsext/Tunnel.h \ datapath-windows/ovsext/TunnelFilter.c \ datapath-windows/ovsext/TunnelIntf.h \ datapath-windows/ovsext/Types.h \ datapath-windows/ovsext/User.c \ datapath-windows/ovsext/User.h \ datapath-windows/ovsext/Util.c \ datapath-windows/ovsext/Util.h \ datapath-windows/ovsext/Vport.c \ datapath-windows/ovsext/Vport.h \ datapath-windows/ovsext/Vxlan.c \ datapath-windows/ovsext/Vxlan.h \ datapath-windows/ovsext/ovsext.inf \ datapath-windows/ovsext/ovsext.rc \ datapath-windows/ovsext/ovsext.vcxproj \ datapath-windows/ovsext/ovsext.vcxproj.user \ datapath-windows/ovsext/precomp.h \ datapath-windows/ovsext/precompsrc.c \ datapath-windows/ovsext/resource.h openvswitch-2.5.0/PaxHeaders.69223/DESIGN.md0000644000000000000000000000013212631676262015137 xustar0030 mtime=1449622706.874435954 30 atime=1456592667.279089093 30 ctime=1456594659.641265614 openvswitch-2.5.0/DESIGN.md0000664000175000017500000013416612631676262016642 0ustar00jpettitjpettit00000000000000Design Decisions In Open vSwitch ================================ This document describes design decisions that went into implementing Open vSwitch. While we believe these to be reasonable decisions, it is impossible to predict how Open vSwitch will be used in all environments. Understanding assumptions made by Open vSwitch is critical to a successful deployment. The end of this document contains contact information that can be used to let us know how we can make Open vSwitch more generally useful. Asynchronous Messages ===================== Over time, Open vSwitch has added many knobs that control whether a given controller receives OpenFlow asynchronous messages. This section describes how all of these features interact. First, a service controller never receives any asynchronous messages unless it changes its miss_send_len from the service controller default of zero in one of the following ways: - Sending an OFPT_SET_CONFIG message with nonzero miss_send_len. - Sending any NXT_SET_ASYNC_CONFIG message: as a side effect, this message changes the miss_send_len to OFP_DEFAULT_MISS_SEND_LEN (128) for service controllers. Second, OFPT_FLOW_REMOVED and NXT_FLOW_REMOVED messages are generated only if the flow that was removed had the OFPFF_SEND_FLOW_REM flag set. Third, OFPT_PACKET_IN and NXT_PACKET_IN messages are sent only to OpenFlow controller connections that have the correct connection ID (see "struct nx_controller_id" and "struct nx_action_controller"): - For packet-in messages generated by a NXAST_CONTROLLER action, the controller ID specified in the action. - For other packet-in messages, controller ID zero. (This is the default ID when an OpenFlow controller does not configure one.) Finally, Open vSwitch consults a per-connection table indexed by the message type, reason code, and current role. The following table shows how this table is initialized by default when an OpenFlow connection is made. An entry labeled "yes" means that the message is sent, an entry labeled "---" means that the message is suppressed. ``` master/ message and reason code other slave ---------------------------------------- ------- ----- OFPT_PACKET_IN / NXT_PACKET_IN OFPR_NO_MATCH yes --- OFPR_ACTION yes --- OFPR_INVALID_TTL --- --- OFPR_ACTION_SET (OF1.4+) yes --- OFPR_GROUP (OF1.4+) yes --- OFPT_FLOW_REMOVED / NXT_FLOW_REMOVED OFPRR_IDLE_TIMEOUT yes --- OFPRR_HARD_TIMEOUT yes --- OFPRR_DELETE yes --- OFPRR_GROUP_DELETE (OF1.4+) yes --- OFPRR_METER_DELETE (OF1.4+) yes --- OFPRR_EVICTION (OF1.4+) yes --- OFPT_PORT_STATUS OFPPR_ADD yes yes OFPPR_DELETE yes yes OFPPR_MODIFY yes yes OFPT_ROLE_REQUEST / OFPT_ROLE_REPLY (OF1.4+) OFPCRR_MASTER_REQUEST --- --- OFPCRR_CONFIG --- --- OFPCRR_EXPERIMENTER --- --- OFPT_TABLE_STATUS (OF1.4+) OFPTR_VACANCY_DOWN --- --- OFPTR_VACANCY_UP --- --- OFPT_REQUESTFORWARD (OF1.4+) OFPRFR_GROUP_MOD --- --- OFPRFR_METER_MOD --- --- ``` The NXT_SET_ASYNC_CONFIG message directly sets all of the values in this table for the current connection. The OFPC_INVALID_TTL_TO_CONTROLLER bit in the OFPT_SET_CONFIG message controls the setting for OFPR_INVALID_TTL for the "master" role. OFPAT_ENQUEUE ============= The OpenFlow 1.0 specification requires the output port of the OFPAT_ENQUEUE action to "refer to a valid physical port (i.e. < OFPP_MAX) or OFPP_IN_PORT". Although OFPP_LOCAL is not less than OFPP_MAX, it is an 'internal' port which can have QoS applied to it in Linux. Since we allow the OFPAT_ENQUEUE to apply to 'internal' ports whose port numbers are less than OFPP_MAX, we interpret OFPP_LOCAL as a physical port and support OFPAT_ENQUEUE on it as well. OFPT_FLOW_MOD ============= The OpenFlow specification for the behavior of OFPT_FLOW_MOD is confusing. The following tables summarize the Open vSwitch implementation of its behavior in the following categories: - "match on priority": Whether the flow_mod acts only on flows whose priority matches that included in the flow_mod message. - "match on out_port": Whether the flow_mod acts only on flows that output to the out_port included in the flow_mod message (if out_port is not OFPP_NONE). OpenFlow 1.1 and later have a similar feature (not listed separately here) for out_group. - "match on flow_cookie": Whether the flow_mod acts only on flows whose flow_cookie matches an optional controller-specified value and mask. - "updates flow_cookie": Whether the flow_mod changes the flow_cookie of the flow or flows that it matches to the flow_cookie included in the flow_mod message. - "updates OFPFF_ flags": Whether the flow_mod changes the OFPFF_SEND_FLOW_REM flag of the flow or flows that it matches to the setting included in the flags of the flow_mod message. - "honors OFPFF_CHECK_OVERLAP": Whether the OFPFF_CHECK_OVERLAP flag in the flow_mod is significant. - "updates idle_timeout" and "updates hard_timeout": Whether the idle_timeout and hard_timeout in the flow_mod, respectively, have an effect on the flow or flows matched by the flow_mod. - "updates idle timer": Whether the flow_mod resets the per-flow timer that measures how long a flow has been idle. - "updates hard timer": Whether the flow_mod resets the per-flow timer that measures how long it has been since a flow was modified. - "zeros counters": Whether the flow_mod resets per-flow packet and byte counters to zero. - "may add a new flow": Whether the flow_mod may add a new flow to the flow table. (Obviously this is always true for "add" commands but in some OpenFlow versions "modify" and "modify-strict" can also add new flows.) - "sends flow_removed message": Whether the flow_mod generates a flow_removed message for the flow or flows that it affects. An entry labeled "yes" means that the flow mod type does have the indicated behavior, "---" means that it does not, an empty cell means that the property is not applicable, and other values are explained below the table. OpenFlow 1.0 ------------ ``` MODIFY DELETE ADD MODIFY STRICT DELETE STRICT === ====== ====== ====== ====== match on priority yes --- yes --- yes match on out_port --- --- --- yes yes match on flow_cookie --- --- --- --- --- match on table_id --- --- --- --- --- controller chooses table_id --- --- --- updates flow_cookie yes yes yes updates OFPFF_SEND_FLOW_REM yes + + honors OFPFF_CHECK_OVERLAP yes + + updates idle_timeout yes + + updates hard_timeout yes + + resets idle timer yes + + resets hard timer yes yes yes zeros counters yes + + may add a new flow yes yes yes sends flow_removed message --- --- --- % % (+) "modify" and "modify-strict" only take these actions when they create a new flow, not when they update an existing flow. (%) "delete" and "delete_strict" generates a flow_removed message if the deleted flow or flows have the OFPFF_SEND_FLOW_REM flag set. (Each controller can separately control whether it wants to receive the generated messages.) ``` OpenFlow 1.1 ------------ OpenFlow 1.1 makes these changes: - The controller now must specify the table_id of the flow match searched and into which a flow may be inserted. Behavior for a table_id of 255 is undefined. - A flow_mod, except an "add", can now match on the flow_cookie. - When a flow_mod matches on the flow_cookie, "modify" and "modify-strict" never insert a new flow. ``` MODIFY DELETE ADD MODIFY STRICT DELETE STRICT === ====== ====== ====== ====== match on priority yes --- yes --- yes match on out_port --- --- --- yes yes match on flow_cookie --- yes yes yes yes match on table_id yes yes yes yes yes controller chooses table_id yes yes yes updates flow_cookie yes --- --- updates OFPFF_SEND_FLOW_REM yes + + honors OFPFF_CHECK_OVERLAP yes + + updates idle_timeout yes + + updates hard_timeout yes + + resets idle timer yes + + resets hard timer yes yes yes zeros counters yes + + may add a new flow yes # # sends flow_removed message --- --- --- % % (+) "modify" and "modify-strict" only take these actions when they create a new flow, not when they update an existing flow. (%) "delete" and "delete_strict" generates a flow_removed message if the deleted flow or flows have the OFPFF_SEND_FLOW_REM flag set. (Each controller can separately control whether it wants to receive the generated messages.) (#) "modify" and "modify-strict" only add a new flow if the flow_mod does not match on any bits of the flow cookie ``` OpenFlow 1.2 ------------ OpenFlow 1.2 makes these changes: - Only "add" commands ever add flows, "modify" and "modify-strict" never do. - A new flag OFPFF_RESET_COUNTS now controls whether "modify" and "modify-strict" reset counters, whereas previously they never reset counters (except when they inserted a new flow). ``` MODIFY DELETE ADD MODIFY STRICT DELETE STRICT === ====== ====== ====== ====== match on priority yes --- yes --- yes match on out_port --- --- --- yes yes match on flow_cookie --- yes yes yes yes match on table_id yes yes yes yes yes controller chooses table_id yes yes yes updates flow_cookie yes --- --- updates OFPFF_SEND_FLOW_REM yes --- --- honors OFPFF_CHECK_OVERLAP yes --- --- updates idle_timeout yes --- --- updates hard_timeout yes --- --- resets idle timer yes --- --- resets hard timer yes yes yes zeros counters yes & & may add a new flow yes --- --- sends flow_removed message --- --- --- % % (%) "delete" and "delete_strict" generates a flow_removed message if the deleted flow or flows have the OFPFF_SEND_FLOW_REM flag set. (Each controller can separately control whether it wants to receive the generated messages.) (&) "modify" and "modify-strict" reset counters if the OFPFF_RESET_COUNTS flag is specified. ``` OpenFlow 1.3 ------------ OpenFlow 1.3 makes these changes: - Behavior for a table_id of 255 is now defined, for "delete" and "delete-strict" commands, as meaning to delete from all tables. A table_id of 255 is now explicitly invalid for other commands. - New flags OFPFF_NO_PKT_COUNTS and OFPFF_NO_BYT_COUNTS for "add" operations. The table for 1.3 is the same as the one shown above for 1.2. OpenFlow 1.4 ----------- OpenFlow 1.4 makes these changes: - Adds the "importance" field to flow_mods, but it does not explicitly specify which kinds of flow_mods set the importance. For consistency, Open vSwitch uses the same rule for importance as for idle_timeout and hard_timeout, that is, only an "ADD" flow_mod sets the importance. (This issue has been filed with the ONF as EXT-496.) - Eviction Mechanism to automatically delete entries of lower importance to make space for newer entries. OpenFlow 1.4 Bundles ==================== Open vSwitch makes all flow table modifications atomically, i.e., any datapath packet only sees flow table configurations either before or after any change made by any flow_mod. For example, if a controller removes all flows with a single OpenFlow "flow_mod", no packet sees an intermediate version of the OpenFlow pipeline where only some of the flows have been deleted. It should be noted that Open vSwitch caches datapath flows, and that the cached flows are NOT flushed immediately when a flow table changes. Instead, the datapath flows are revalidated against the new flow table as soon as possible, and usually within one second of the modification. This design amortizes the cost of datapath cache flushing across multiple flow table changes, and has a significant performance effect during simultaneous heavy flow table churn and high traffic load. This means that different cached datapath flows may have been computed based on a different flow table configurations, but each of the datapath flows is guaranteed to have been computed over a coherent view of the flow tables, as described above. With OpenFlow 1.4 bundles this atomicity can be extended across an arbitrary set of flow_mods. Bundles are supported for flow_mod and port_mod messages only. For flow_mods, both 'atomic' and 'ordered' bundle flags are trivially supported, as all bundled messages are executed in the order they were added and all flow table modifications are now atomic to the datapath. Port mods may not appear in atomic bundles, as port status modifications are not atomic. To support bundles, ovs-ofctl has a '--bundle' option that makes the flow mod commands ('add-flow', 'add-flows', 'mod-flows', 'del-flows', and 'replace-flows') use an OpenFlow 1.4 bundle to operate the modifications as a single atomic transaction. If any of the flow mods in a transaction fail, none of them are executed. All flow mods in a bundle appear to datapath lookups simultaneously. Furthermore, ovs-ofctl 'add-flow' and 'add-flows' commands now accept arbitrary flow mods as an input by allowing the flow specification to start with an explicit 'add', 'modify', 'modify_strict', 'delete', or 'delete_strict' keyword. A missing keyword is treated as 'add', so this is fully backwards compatible. With the new '--bundle' option all the flow mods are executed as a single atomic transaction using an OpenFlow 1.4 bundle. Without the '--bundle' option the flow mods are executed in order up to the first failing flow_mod, and in case of an error the earlier successful flow_mods are not rolled back. OFPT_PACKET_IN ============== The OpenFlow 1.1 specification for OFPT_PACKET_IN is confusing. The definition in OF1.1 openflow.h is[*]: ``` /* Packet received on port (datapath -> controller). */ struct ofp_packet_in { struct ofp_header header; uint32_t buffer_id; /* ID assigned by datapath. */ uint32_t in_port; /* Port on which frame was received. */ uint32_t in_phy_port; /* Physical Port on which frame was received. */ uint16_t total_len; /* Full length of frame. */ uint8_t reason; /* Reason packet is being sent (one of OFPR_*) */ uint8_t table_id; /* ID of the table that was looked up */ uint8_t data[0]; /* Ethernet frame, halfway through 32-bit word, so the IP header is 32-bit aligned. The amount of data is inferred from the length field in the header. Because of padding, offsetof(struct ofp_packet_in, data) == sizeof(struct ofp_packet_in) - 2. */ }; OFP_ASSERT(sizeof(struct ofp_packet_in) == 24); ``` The confusing part is the comment on the data[] member. This comment is a leftover from OF1.0 openflow.h, in which the comment was correct: sizeof(struct ofp_packet_in) is 20 in OF1.0 and offsetof(struct ofp_packet_in, data) is 18. When OF1.1 was written, the structure members were changed but the comment was carelessly not updated, and the comment became wrong: sizeof(struct ofp_packet_in) and offsetof(struct ofp_packet_in, data) are both 24 in OF1.1. That leaves the question of how to implement ofp_packet_in in OF1.1. The OpenFlow reference implementation for OF1.1 does not include any padding, that is, the first byte of the encapsulated frame immediately follows the 'table_id' member without a gap. Open vSwitch therefore implements it the same way for compatibility. For an earlier discussion, please see the thread archived at: https://mailman.stanford.edu/pipermail/openflow-discuss/2011-August/002604.html [*] The quoted definition is directly from OF1.1. Definitions used inside OVS omit the 8-byte ofp_header members, so the sizes in this discussion are 8 bytes larger than those declared in OVS header files. VLAN Matching ============= The 802.1Q VLAN header causes more trouble than any other 4 bytes in networking. More specifically, three versions of OpenFlow and Open vSwitch have among them four different ways to match the contents and presence of the VLAN header. The following table describes how each version works. Match NXM OF1.0 OF1.1 OF1.2 ----- --------- ----------- ----------- ------------ [1] 0000/0000 ????/1,??/? ????/1,??/? 0000/0000,-- [2] 0000/ffff ffff/0,??/? ffff/0,??/? 0000/ffff,-- [3] 1xxx/1fff 0xxx/0,??/1 0xxx/0,??/1 1xxx/ffff,-- [4] z000/f000 ????/1,0y/0 fffe/0,0y/0 1000/1000,0y [5] zxxx/ffff 0xxx/0,0y/0 0xxx/0,0y/0 1xxx/ffff,0y [6] 0000/0fff [7] 0000/f000 [8] 0000/efff [9] 1001/1001 1001/1001,-- [10] 3000/3000 Each column is interpreted as follows. - Match: See the list below. - NXM: xxxx/yyyy means NXM_OF_VLAN_TCI_W with value xxxx and mask yyyy. A mask of 0000 is equivalent to omitting NXM_OF_VLAN_TCI(_W), a mask of ffff is equivalent to NXM_OF_VLAN_TCI. - OF1.0 and OF1.1: wwww/x,yy/z means dl_vlan wwww, OFPFW_DL_VLAN x, dl_vlan_pcp yy, and OFPFW_DL_VLAN_PCP z. If OFPFW_DL_VLAN or OFPFW_DL_VLAN_PCP is 1, the corresponding field value is wildcarded, otherwise it is matched. ? means that the given bits are ignored (their conventional values are 0000/x,00/0 in OF1.0, 0000/x,00/1 in OF1.1; x is never ignored). means that the given match is not supported. - OF1.2: xxxx/yyyy,zz means OXM_OF_VLAN_VID_W with value xxxx and mask yyyy, and OXM_OF_VLAN_PCP (which is not maskable) with value zz. A mask of 0000 is equivalent to omitting OXM_OF_VLAN_VID(_W), a mask of ffff is equivalent to OXM_OF_VLAN_VID. -- means that OXM_OF_VLAN_PCP is omitted. means that the given match is not supported. The matches are: [1] Matches any packet, that is, one without an 802.1Q header or with an 802.1Q header with any TCI value. [2] Matches only packets without an 802.1Q header. NXM: Any match with (vlan_tci == 0) and (vlan_tci_mask & 0x1000) != 0 is equivalent to the one listed in the table. OF1.0: The spec doesn't define behavior if dl_vlan is set to 0xffff and OFPFW_DL_VLAN_PCP is not set. OF1.1: The spec says explicitly to ignore dl_vlan_pcp when dl_vlan is set to 0xffff. OF1.2: The spec doesn't say what should happen if (vlan_vid == 0) and (vlan_vid_mask & 0x1000) != 0 but (vlan_vid_mask != 0x1000), but it would be straightforward to also interpret as [2]. [3] Matches only packets that have an 802.1Q header with VID xxx (and any PCP). [4] Matches only packets that have an 802.1Q header with PCP y (and any VID). NXM: z is ((y << 1) | 1). OF1.0: The spec isn't very clear, but OVS implements it this way. OF1.2: Presumably other masks such that (vlan_vid_mask & 0x1fff) == 0x1000 would also work, but the spec doesn't define their behavior. [5] Matches only packets that have an 802.1Q header with VID xxx and PCP y. NXM: z is ((y << 1) | 1). OF1.2: Presumably other masks such that (vlan_vid_mask & 0x1fff) == 0x1fff would also work. [6] Matches packets with no 802.1Q header or with an 802.1Q header with a VID of 0. Only possible with NXM. [7] Matches packets with no 802.1Q header or with an 802.1Q header with a PCP of 0. Only possible with NXM. [8] Matches packets with no 802.1Q header or with an 802.1Q header with both VID and PCP of 0. Only possible with NXM. [9] Matches only packets that have an 802.1Q header with an odd-numbered VID (and any PCP). Only possible with NXM and OF1.2. (This is just an example; one can match on any desired VID bit pattern.) [10] Matches only packets that have an 802.1Q header with an odd-numbered PCP (and any VID). Only possible with NXM. (This is just an example; one can match on any desired VID bit pattern.) Additional notes: - OF1.2: The top three bits of OXM_OF_VLAN_VID are fixed to zero, so bits 13, 14, and 15 in the masks listed in the table may be set to arbitrary values, as long as the corresponding value bits are also zero. The suggested ffff mask for [2], [3], and [5] allows a shorter OXM representation (the mask is omitted) than the minimal 1fff mask. Flow Cookies ============ OpenFlow 1.0 and later versions have the concept of a "flow cookie", which is a 64-bit integer value attached to each flow. The treatment of the flow cookie has varied greatly across OpenFlow versions, however. In OpenFlow 1.0: - OFPFC_ADD set the cookie in the flow that it added. - OFPFC_MODIFY and OFPFC_MODIFY_STRICT updated the cookie for the flow or flows that it modified. - OFPST_FLOW messages included the flow cookie. - OFPT_FLOW_REMOVED messages reported the cookie of the flow that was removed. OpenFlow 1.1 made the following changes: - Flow mod operations OFPFC_MODIFY, OFPFC_MODIFY_STRICT, OFPFC_DELETE, and OFPFC_DELETE_STRICT, plus flow stats requests and aggregate stats requests, gained the ability to match on flow cookies with an arbitrary mask. - OFPFC_MODIFY and OFPFC_MODIFY_STRICT were changed to add a new flow, in the case of no match, only if the flow table modification operation did not match on the cookie field. (In OpenFlow 1.0, modify operations always added a new flow when there was no match.) - OFPFC_MODIFY and OFPFC_MODIFY_STRICT no longer updated flow cookies. OpenFlow 1.2 made the following changes: - OFPC_MODIFY and OFPFC_MODIFY_STRICT were changed to never add a new flow, regardless of whether the flow cookie was used for matching. Open vSwitch support for OpenFlow 1.0 implements the OpenFlow 1.0 behavior with the following extensions: - An NXM extension field NXM_NX_COOKIE(_W) allows the NXM versions of OFPFC_MODIFY, OFPFC_MODIFY_STRICT, OFPFC_DELETE, and OFPFC_DELETE_STRICT flow_mods, plus flow stats requests and aggregate stats requests, to match on flow cookies with arbitrary masks. This is much like the equivalent OpenFlow 1.1 feature. - Like OpenFlow 1.1, OFPC_MODIFY and OFPFC_MODIFY_STRICT add a new flow if there is no match and the mask is zero (or not given). - The "cookie" field in OFPT_FLOW_MOD and NXT_FLOW_MOD messages is used as the cookie value for OFPFC_ADD commands, as described in OpenFlow 1.0. For OFPFC_MODIFY and OFPFC_MODIFY_STRICT commands, the "cookie" field is used as a new cookie for flows that match unless it is UINT64_MAX, in which case the flow's cookie is not updated. - NXT_PACKET_IN (the Nicira extended version of OFPT_PACKET_IN) reports the cookie of the rule that generated the packet, or all-1-bits if no rule generated the packet. (Older versions of OVS used all-0-bits instead of all-1-bits.) The following table shows the handling of different protocols when receiving OFPFC_MODIFY and OFPFC_MODIFY_STRICT messages. A mask of 0 indicates either an explicit mask of zero or an implicit one by not specifying the NXM_NX_COOKIE(_W) field. ``` Match Update Add on miss Add on miss cookie cookie mask!=0 mask==0 ====== ====== =========== =========== OpenFlow 1.0 no yes OpenFlow 1.1 yes no no yes OpenFlow 1.2 yes no no no NXM yes yes* no yes * Updates the flow's cookie unless the "cookie" field is UINT64_MAX. ``` Multiple Table Support ====================== OpenFlow 1.0 has only rudimentary support for multiple flow tables. Notably, OpenFlow 1.0 does not allow the controller to specify the flow table to which a flow is to be added. Open vSwitch adds an extension for this purpose, which is enabled on a per-OpenFlow connection basis using the NXT_FLOW_MOD_TABLE_ID message. When the extension is enabled, the upper 8 bits of the 'command' member in an OFPT_FLOW_MOD or NXT_FLOW_MOD message designates the table to which a flow is to be added. The Open vSwitch software switch implementation offers 255 flow tables. On packet ingress, only the first flow table (table 0) is searched, and the contents of the remaining tables are not considered in any way. Tables other than table 0 only come into play when an NXAST_RESUBMIT_TABLE action specifies another table to search. Tables 128 and above are reserved for use by the switch itself. Controllers should use only tables 0 through 127. OFPTC_* Table Configuration =========================== This section covers the history of the OFPTC_* table configuration bits across OpenFlow versions. OpenFlow 1.0 flow tables had fixed configurations. OpenFlow 1.1 enabled controllers to configure behavior upon flow table miss and added the OFPTC_MISS_* constants for that purpose. OFPTC_* did not control anything else but it was nevertheless conceptualized as a set of bit-fields instead of an enum. OF1.1 added the OFPT_TABLE_MOD message to set OFPTC_MISS_* for a flow table and added the 'config' field to the OFPST_TABLE reply to report the current setting. OpenFlow 1.2 did not change anything in this regard. OpenFlow 1.3 switched to another means to changing flow table miss behavior and deprecated OFPTC_MISS_* without adding any more OFPTC_* constants. This meant that OFPT_TABLE_MOD now had no purpose at all, but OF1.3 kept it around "for backward compatibility with older and newer versions of the specification." At the same time, OF1.3 introduced a new message OFPMP_TABLE_FEATURES that included a field 'config' documented as reporting the OFPTC_* values set with OFPT_TABLE_MOD; of course this served no real purpose because no OFPTC_* values are defined. OF1.3 did remove the OFPTC_* field from OFPMP_TABLE (previously named OFPST_TABLE). OpenFlow 1.4 defined two new OFPTC_* constants, OFPTC_EVICTION and OFPTC_VACANCY_EVENTS, using bits that did not overlap with OFPTC_MISS_* even though those bits had not been defined since OF1.2. OFPT_TABLE_MOD still controlled these settings. The field for OFPTC_* values in OFPMP_TABLE_FEATURES was renamed from 'config' to 'capabilities' and documented as reporting the flags that are supported in a OFPT_TABLE_MOD message. The OFPMP_TABLE_DESC message newly added in OF1.4 reported the OFPTC_* setting. OpenFlow 1.5 did not change anything in this regard. The following table summarizes. The columns say: - OpenFlow version(s). - The OFPTC_* flags defined in those versions. - Whether OFPT_TABLE_MOD can modify OFPTC_* flags. - Whether OFPST_TABLE/OFPMP_TABLE reports the OFPTC_* flags. - What OFPMP_TABLE_FEATURES reports (if it exists): either the current configuration or the switch's capabilities. - Whether OFPMP_TABLE_DESC reports the current configuration. OpenFlow OFPTC_* flags TABLE_MOD stats? TABLE_FEATURES TABLE_DESC --------- ----------------------- --------- ------ -------------- ---------- OF1.0 none no[*][+] no[*] nothing[*][+] no[*][+] OF1.1/1.2 MISS_* yes yes nothing[+] no[+] OF1.3 none yes[*] no[*] config[*] no[*][+] OF1.4/1.5 EVICTION/VACANCY_EVENTS yes no capabilities yes [*] Nothing to report/change anyway. [+] No such message. IPv6 ==== Open vSwitch supports stateless handling of IPv6 packets. Flows can be written to support matching TCP, UDP, and ICMPv6 headers within an IPv6 packet. Deeper matching of some Neighbor Discovery messages is also supported. IPv6 was not designed to interact well with middle-boxes. This, combined with Open vSwitch's stateless nature, have affected the processing of IPv6 traffic, which is detailed below. Extension Headers ----------------- The base IPv6 header is incredibly simple with the intention of only containing information relevant for routing packets between two endpoints. IPv6 relies heavily on the use of extension headers to provide any other functionality. Unfortunately, the extension headers were designed in such a way that it is impossible to move to the next header (including the layer-4 payload) unless the current header is understood. Open vSwitch will process the following extension headers and continue to the next header: * Fragment (see the next section) * AH (Authentication Header) * Hop-by-Hop Options * Routing * Destination Options When a header is encountered that is not in that list, it is considered "terminal". A terminal header's IPv6 protocol value is stored in "nw_proto" for matching purposes. If a terminal header is TCP, UDP, or ICMPv6, the packet will be further processed in an attempt to extract layer-4 information. Fragments --------- IPv6 requires that every link in the internet have an MTU of 1280 octets or greater (RFC 2460). As such, a terminal header (as described above in "Extension Headers") in the first fragment should generally be reachable. In this case, the terminal header's IPv6 protocol type is stored in the "nw_proto" field for matching purposes. If a terminal header cannot be found in the first fragment (one with a fragment offset of zero), the "nw_proto" field is set to 0. Subsequent fragments (those with a non-zero fragment offset) have the "nw_proto" field set to the IPv6 protocol type for fragments (44). Jumbograms ---------- An IPv6 jumbogram (RFC 2675) is a packet containing a payload longer than 65,535 octets. A jumbogram is only relevant in subnets with a link MTU greater than 65,575 octets, and are not required to be supported on nodes that do not connect to link with such large MTUs. Currently, Open vSwitch doesn't process jumbograms. In-Band Control =============== Motivation ---------- An OpenFlow switch must establish and maintain a TCP network connection to its controller. There are two basic ways to categorize the network that this connection traverses: either it is completely separate from the one that the switch is otherwise controlling, or its path may overlap the network that the switch controls. We call the former case "out-of-band control", the latter case "in-band control". Out-of-band control has the following benefits: - Simplicity: Out-of-band control slightly simplifies the switch implementation. - Reliability: Excessive switch traffic volume cannot interfere with control traffic. - Integrity: Machines not on the control network cannot impersonate a switch or a controller. - Confidentiality: Machines not on the control network cannot snoop on control traffic. In-band control, on the other hand, has the following advantages: - No dedicated port: There is no need to dedicate a physical switch port to control, which is important on switches that have few ports (e.g. wireless routers, low-end embedded platforms). - No dedicated network: There is no need to build and maintain a separate control network. This is important in many environments because it reduces proliferation of switches and wiring. Open vSwitch supports both out-of-band and in-band control. This section describes the principles behind in-band control. See the description of the Controller table in ovs-vswitchd.conf.db(5) to configure OVS for in-band control. Principles ---------- The fundamental principle of in-band control is that an OpenFlow switch must recognize and switch control traffic without involving the OpenFlow controller. All the details of implementing in-band control are special cases of this principle. The rationale for this principle is simple. If the switch does not handle in-band control traffic itself, then it will be caught in a contradiction: it must contact the controller, but it cannot, because only the controller can set up the flows that are needed to contact the controller. The following points describe important special cases of this principle. - In-band control must be implemented regardless of whether the switch is connected. It is tempting to implement the in-band control rules only when the switch is not connected to the controller, using the reasoning that the controller should have complete control once it has established a connection with the switch. This does not work in practice. Consider the case where the switch is connected to the controller. Occasionally it can happen that the controller forgets or otherwise needs to obtain the MAC address of the switch. To do so, the controller sends a broadcast ARP request. A switch that implements the in-band control rules only when it is disconnected will then send an OFPT_PACKET_IN message up to the controller. The controller will be unable to respond, because it does not know the MAC address of the switch. This is a deadlock situation that can only be resolved by the switch noticing that its connection to the controller has hung and reconnecting. - In-band control must override flows set up by the controller. It is reasonable to assume that flows set up by the OpenFlow controller should take precedence over in-band control, on the basis that the controller should be in charge of the switch. Again, this does not work in practice. Reasonable controller implementations may set up a "last resort" fallback rule that wildcards every field and, e.g., sends it up to the controller or discards it. If a controller does that, then it will isolate itself from the switch. - The switch must recognize all control traffic. The fundamental principle of in-band control states, in part, that a switch must recognize control traffic without involving the OpenFlow controller. More specifically, the switch must recognize *all* control traffic. "False negatives", that is, packets that constitute control traffic but that the switch does not recognize as control traffic, lead to control traffic storms. Consider an OpenFlow switch that only recognizes control packets sent to or from that switch. Now suppose that two switches of this type, named A and B, are connected to ports on an Ethernet hub (not a switch) and that an OpenFlow controller is connected to a third hub port. In this setup, control traffic sent by switch A will be seen by switch B, which will send it to the controller as part of an OFPT_PACKET_IN message. Switch A will then see the OFPT_PACKET_IN message's packet, re-encapsulate it in another OFPT_PACKET_IN, and send it to the controller. Switch B will then see that OFPT_PACKET_IN, and so on in an infinite loop. Incidentally, the consequences of "false positives", where packets that are not control traffic are nevertheless recognized as control traffic, are much less severe. The controller will not be able to control their behavior, but the network will remain in working order. False positives do constitute a security problem. - The switch should use echo-requests to detect disconnection. TCP will notice that a connection has hung, but this can take a considerable amount of time. For example, with default settings the Linux kernel TCP implementation will retransmit for between 13 and 30 minutes, depending on the connection's retransmission timeout, according to kernel documentation. This is far too long for a switch to be disconnected, so an OpenFlow switch should implement its own connection timeout. OpenFlow OFPT_ECHO_REQUEST messages are the best way to do this, since they test the OpenFlow connection itself. Implementation -------------- This section describes how Open vSwitch implements in-band control. Correctly implementing in-band control has proven difficult due to its many subtleties, and has thus gone through many iterations. Please read through and understand the reasoning behind the chosen rules before making modifications. Open vSwitch implements in-band control as "hidden" flows, that is, flows that are not visible through OpenFlow, and at a higher priority than wildcarded flows can be set up through OpenFlow. This is done so that the OpenFlow controller cannot interfere with them and possibly break connectivity with its switches. It is possible to see all flows, including in-band ones, with the ovs-appctl "bridge/dump-flows" command. The Open vSwitch implementation of in-band control can hide traffic to arbitrary "remotes", where each remote is one TCP port on one IP address. Currently the remotes are automatically configured as the in-band OpenFlow controllers plus the OVSDB managers, if any. (The latter is a requirement because OVSDB managers are responsible for configuring OpenFlow controllers, so if the manager cannot be reached then OpenFlow cannot be reconfigured.) The following rules (with the OFPP_NORMAL action) are set up on any bridge that has any remotes: (a) DHCP requests sent from the local port. (b) ARP replies to the local port's MAC address. (c) ARP requests from the local port's MAC address. In-band also sets up the following rules for each unique next-hop MAC address for the remotes' IPs (the "next hop" is either the remote itself, if it is on a local subnet, or the gateway to reach the remote): (d) ARP replies to the next hop's MAC address. (e) ARP requests from the next hop's MAC address. In-band also sets up the following rules for each unique remote IP address: (f) ARP replies containing the remote's IP address as a target. (g) ARP requests containing the remote's IP address as a source. In-band also sets up the following rules for each unique remote (IP,port) pair: (h) TCP traffic to the remote's IP and port. (i) TCP traffic from the remote's IP and port. The goal of these rules is to be as narrow as possible to allow a switch to join a network and be able to communicate with the remotes. As mentioned earlier, these rules have higher priority than the controller's rules, so if they are too broad, they may prevent the controller from implementing its policy. As such, in-band actively monitors some aspects of flow and packet processing so that the rules can be made more precise. In-band control monitors attempts to add flows into the datapath that could interfere with its duties. The datapath only allows exact match entries, so in-band control is able to be very precise about the flows it prevents. Flows that miss in the datapath are sent to userspace to be processed, so preventing these flows from being cached in the "fast path" does not affect correctness. The only type of flow that is currently prevented is one that would prevent DHCP replies from being seen by the local port. For example, a rule that forwarded all DHCP traffic to the controller would not be allowed, but one that forwarded to all ports (including the local port) would. As mentioned earlier, packets that miss in the datapath are sent to the userspace for processing. The userspace has its own flow table, the "classifier", so in-band checks whether any special processing is needed before the classifier is consulted. If a packet is a DHCP response to a request from the local port, the packet is forwarded to the local port, regardless of the flow table. Note that this requires L7 processing of DHCP replies to determine whether the 'chaddr' field matches the MAC address of the local port. It is interesting to note that for an L3-based in-band control mechanism, the majority of rules are devoted to ARP traffic. At first glance, some of these rules appear redundant. However, each serves an important role. First, in order to determine the MAC address of the remote side (controller or gateway) for other ARP rules, we must allow ARP traffic for our local port with rules (b) and (c). If we are between a switch and its connection to the remote, we have to allow the other switch's ARP traffic to through. This is done with rules (d) and (e), since we do not know the addresses of the other switches a priori, but do know the remote's or gateway's. Finally, if the remote is running in a local guest VM that is not reached through the local port, the switch that is connected to the VM must allow ARP traffic based on the remote's IP address, since it will not know the MAC address of the local port that is sending the traffic or the MAC address of the remote in the guest VM. With a few notable exceptions below, in-band should work in most network setups. The following are considered "supported" in the current implementation: - Locally Connected. The switch and remote are on the same subnet. This uses rules (a), (b), (c), (h), and (i). - Reached through Gateway. The switch and remote are on different subnets and must go through a gateway. This uses rules (a), (b), (c), (h), and (i). - Between Switch and Remote. This switch is between another switch and the remote, and we want to allow the other switch's traffic through. This uses rules (d), (e), (h), and (i). It uses (b) and (c) indirectly in order to know the MAC address for rules (d) and (e). Note that DHCP for the other switch will not work unless an OpenFlow controller explicitly lets this switch pass the traffic. - Between Switch and Gateway. This switch is between another switch and the gateway, and we want to allow the other switch's traffic through. This uses the same rules and logic as the "Between Switch and Remote" configuration described earlier. - Remote on Local VM. The remote is a guest VM on the system running in-band control. This uses rules (a), (b), (c), (h), and (i). - Remote on Local VM with Different Networks. The remote is a guest VM on the system running in-band control, but the local port is not used to connect to the remote. For example, an IP address is configured on eth0 of the switch. The remote's VM is connected through eth1 of the switch, but an IP address has not been configured for that port on the switch. As such, the switch will use eth0 to connect to the remote, and eth1's rules about the local port will not work. In the example, the switch attached to eth0 would use rules (a), (b), (c), (h), and (i) on eth0. The switch attached to eth1 would use rules (f), (g), (h), and (i). The following are explicitly *not* supported by in-band control: - Specify Remote by Name. Currently, the remote must be identified by IP address. A naive approach would be to permit all DNS traffic. Unfortunately, this would prevent the controller from defining any policy over DNS. Since switches that are located behind us need to connect to the remote, in-band cannot simply add a rule that allows DNS traffic from the local port. The "correct" way to support this is to parse DNS requests to allow all traffic related to a request for the remote's name through. Due to the potential security problems and amount of processing, we decided to hold off for the time-being. - Differing Remotes for Switches. All switches must know the L3 addresses for all the remotes that other switches may use, since rules need to be set up to allow traffic related to those remotes through. See rules (f), (g), (h), and (i). - Differing Routes for Switches. In order for the switch to allow other switches to connect to a remote through a gateway, it allows the gateway's traffic through with rules (d) and (e). If the routes to the remote differ for the two switches, we will not know the MAC address of the alternate gateway. Action Reproduction =================== It seems likely that many controllers, at least at startup, use the OpenFlow "flow statistics" request to obtain existing flows, then compare the flows' actions against the actions that they expect to find. Before version 1.8.0, Open vSwitch always returned exact, byte-for-byte copies of the actions that had been added to the flow table. The current version of Open vSwitch does not always do this in some exceptional cases. This section lists the exceptions that controller authors must keep in mind if they compare actual actions against desired actions in a bytewise fashion: - Open vSwitch zeros padding bytes in action structures, regardless of their values when the flows were added. - Open vSwitch "normalizes" the instructions in OpenFlow 1.1 (and later) in the following way: * OVS sorts the instructions into the following order: Apply-Actions, Clear-Actions, Write-Actions, Write-Metadata, Goto-Table. * OVS drops Apply-Actions instructions that have empty action lists. * OVS drops Write-Actions instructions that have empty action sets. Please report other discrepancies, if you notice any, so that we can fix or document them. Suggestions =========== Suggestions to improve Open vSwitch are welcome at discuss@openvswitch.org. openvswitch-2.5.0/PaxHeaders.69223/vswitchd0000644000000000000000000000013212664357345015426 xustar0030 mtime=1456594661.109327329 30 atime=1456594661.705352384 30 ctime=1456594661.109327329 openvswitch-2.5.0/vswitchd/0000775000175000017500000000000012664357345017173 5ustar00jpettitjpettit00000000000000openvswitch-2.5.0/vswitchd/PaxHeaders.69223/xenserver.c0000644000000000000000000000013012631676263017663 xustar0030 mtime=1449622707.598461396 29 atime=1456592664.87099036 29 ctime=1456594661.10532716 openvswitch-2.5.0/vswitchd/xenserver.c0000664000175000017500000000443612631676263021364 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2009, 2010, 2013 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "xenserver.h" #include #include #include #include #include #include #include "dynamic-string.h" #include "process.h" #include "util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(xenserver); /* If running on a XenServer, the XenServer host UUID as a 36-character string, * otherwise null. */ static char *host_uuid; static void read_host_uuid(void) { static const char filename[] = "/etc/xensource-inventory"; char line[128]; FILE *file; file = fopen(filename, "r"); if (!file) { if (errno == ENOENT) { VLOG_DBG("not running on a XenServer"); } else { VLOG_INFO("%s: open: %s", filename, ovs_strerror(errno)); } return; } while (fgets(line, sizeof line, file)) { static const char leader[] = "INSTALLATION_UUID='"; const int leader_len = strlen(leader); const int uuid_len = 36; static const char trailer[] = "'\n"; const int trailer_len = strlen(trailer); if (strlen(line) == leader_len + uuid_len + trailer_len && !memcmp(line, leader, leader_len) && !memcmp(line + leader_len + uuid_len, trailer, trailer_len)) { host_uuid = xmemdup0(line + leader_len, uuid_len); VLOG_INFO("running on XenServer, host-uuid %s", host_uuid); fclose(file); return; } } fclose(file); VLOG_ERR("%s: INSTALLATION_UUID not found", filename); } const char * xenserver_get_host_uuid(void) { static pthread_once_t once = PTHREAD_ONCE_INIT; pthread_once(&once, read_host_uuid); return host_uuid; } openvswitch-2.5.0/vswitchd/PaxHeaders.69223/bridge.c0000644000000000000000000000013212664352753017101 xustar0030 mtime=1456592363.502623465 30 atime=1456592368.230817659 30 ctime=1456594661.101326991 openvswitch-2.5.0/vswitchd/bridge.c0000664000175000017500000051146112664352753020601 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "bridge.h" #include #include #include #include "async-append.h" #include "bfd.h" #include "bitmap.h" #include "cfm.h" #include "connectivity.h" #include "coverage.h" #include "daemon.h" #include "dirs.h" #include "dpif.h" #include "dynamic-string.h" #include "hash.h" #include "hmap.h" #include "hmapx.h" #include "jsonrpc.h" #include "lacp.h" #include "list.h" #include "ovs-lldp.h" #include "mac-learning.h" #include "mcast-snooping.h" #include "meta-flow.h" #include "netdev.h" #include "nx-match.h" #include "ofp-print.h" #include "ofp-util.h" #include "ofpbuf.h" #include "ofproto/bond.h" #include "ofproto/ofproto.h" #include "ovs-numa.h" #include "poll-loop.h" #include "if-notifier.h" #include "seq.h" #include "sha1.h" #include "shash.h" #include "smap.h" #include "socket-util.h" #include "stream.h" #include "stream-ssl.h" #include "sset.h" #include "system-stats.h" #include "timeval.h" #include "util.h" #include "unixctl.h" #include "vlandev.h" #include "lib/vswitch-idl.h" #include "xenserver.h" #include "openvswitch/vlog.h" #include "sflow_api.h" #include "vlan-bitmap.h" #include "packets.h" VLOG_DEFINE_THIS_MODULE(bridge); COVERAGE_DEFINE(bridge_reconfigure); struct iface { /* These members are always valid. * * They are immutable: they never change between iface_create() and * iface_destroy(). */ struct ovs_list port_elem; /* Element in struct port's "ifaces" list. */ struct hmap_node name_node; /* In struct bridge's "iface_by_name" hmap. */ struct hmap_node ofp_port_node; /* In struct bridge's "ifaces" hmap. */ struct port *port; /* Containing port. */ char *name; /* Host network device name. */ struct netdev *netdev; /* Network device. */ ofp_port_t ofp_port; /* OpenFlow port number. */ uint64_t change_seq; /* These members are valid only within bridge_reconfigure(). */ const char *type; /* Usually same as cfg->type. */ const struct ovsrec_interface *cfg; }; struct mirror { struct uuid uuid; /* UUID of this "mirror" record in database. */ struct hmap_node hmap_node; /* In struct bridge's "mirrors" hmap. */ struct bridge *bridge; char *name; const struct ovsrec_mirror *cfg; }; struct port { struct hmap_node hmap_node; /* Element in struct bridge's "ports" hmap. */ struct bridge *bridge; char *name; const struct ovsrec_port *cfg; /* An ordinary bridge port has 1 interface. * A bridge port for bonding has at least 2 interfaces. */ struct ovs_list ifaces; /* List of "struct iface"s. */ }; struct bridge { struct hmap_node node; /* In 'all_bridges'. */ char *name; /* User-specified arbitrary name. */ char *type; /* Datapath type. */ struct eth_addr ea; /* Bridge Ethernet Address. */ struct eth_addr default_ea; /* Default MAC. */ const struct ovsrec_bridge *cfg; /* OpenFlow switch processing. */ struct ofproto *ofproto; /* OpenFlow switch. */ /* Bridge ports. */ struct hmap ports; /* "struct port"s indexed by name. */ struct hmap ifaces; /* "struct iface"s indexed by ofp_port. */ struct hmap iface_by_name; /* "struct iface"s indexed by name. */ /* Port mirroring. */ struct hmap mirrors; /* "struct mirror" indexed by UUID. */ /* Auto Attach */ struct hmap mappings; /* "struct" indexed by UUID */ /* Used during reconfiguration. */ struct shash wanted_ports; /* Synthetic local port if necessary. */ struct ovsrec_port synth_local_port; struct ovsrec_interface synth_local_iface; struct ovsrec_interface *synth_local_ifacep; }; struct aa_mapping { struct hmap_node hmap_node; /* In struct bridge's "mappings" hmap. */ struct bridge *bridge; uint32_t isid; uint16_t vlan; char *br_name; }; /* All bridges, indexed by name. */ static struct hmap all_bridges = HMAP_INITIALIZER(&all_bridges); /* OVSDB IDL used to obtain configuration. */ static struct ovsdb_idl *idl; /* We want to complete daemonization, fully detaching from our parent process, * only after we have completed our initial configuration, committed our state * to the database, and received confirmation back from the database server * that it applied the commit. This allows our parent process to know that, * post-detach, ephemeral fields such as datapath-id and ofport are very likely * to have already been filled in. (It is only "very likely" rather than * certain because there is always a slim possibility that the transaction will * fail or that some other client has added new bridges, ports, etc. while * ovs-vswitchd was configuring using an old configuration.) * * We only need to do this once for our initial configuration at startup, so * 'initial_config_done' tracks whether we've already done it. While we are * waiting for a response to our commit, 'daemonize_txn' tracks the transaction * itself and is otherwise NULL. */ static bool initial_config_done; static struct ovsdb_idl_txn *daemonize_txn; /* Most recently processed IDL sequence number. */ static unsigned int idl_seqno; /* Track changes to port connectivity. */ static uint64_t connectivity_seqno = LLONG_MIN; /* Status update to database. * * Some information in the database must be kept as up-to-date as possible to * allow controllers to respond rapidly to network outages. Those status are * updated via the 'status_txn'. * * We use the global connectivity sequence number to detect the status change. * Also, to prevent the status update from sending too much to the database, * we check the return status of each update transaction and do not start new * update if the previous transaction status is 'TXN_INCOMPLETE'. * * 'statux_txn' is NULL if there is no ongoing status update. * * If the previous database transaction was failed (is not 'TXN_SUCCESS', * 'TXN_UNCHANGED' or 'TXN_INCOMPLETE'), 'status_txn_try_again' is set to true, * which will cause the main thread wake up soon and retry the status update. */ static struct ovsdb_idl_txn *status_txn; static bool status_txn_try_again; /* When the status update transaction returns 'TXN_INCOMPLETE', should register a * timeout in 'STATUS_CHECK_AGAIN_MSEC' to check again. */ #define STATUS_CHECK_AGAIN_MSEC 100 /* Statistics update to database. */ static struct ovsdb_idl_txn *stats_txn; /* Each time this timer expires, the bridge fetches interface and mirror * statistics and pushes them into the database. */ static int stats_timer_interval; static long long int stats_timer = LLONG_MIN; /* Each time this timer expires, the bridge fetches the list of port/VLAN * membership that has been modified by the AA. */ #define AA_REFRESH_INTERVAL (1000) /* In milliseconds. */ static long long int aa_refresh_timer = LLONG_MIN; /* Whenever system interfaces are added, removed or change state, the bridge * will be reconfigured. */ static struct if_notifier *ifnotifier; static bool ifaces_changed = false; static void add_del_bridges(const struct ovsrec_open_vswitch *); static void bridge_run__(void); static void bridge_create(const struct ovsrec_bridge *); static void bridge_destroy(struct bridge *, bool del); static struct bridge *bridge_lookup(const char *name); static unixctl_cb_func bridge_unixctl_dump_flows; static unixctl_cb_func bridge_unixctl_reconnect; static size_t bridge_get_controllers(const struct bridge *br, struct ovsrec_controller ***controllersp); static void bridge_collect_wanted_ports(struct bridge *, const unsigned long *splinter_vlans, struct shash *wanted_ports); static void bridge_delete_ofprotos(void); static void bridge_delete_or_reconfigure_ports(struct bridge *); static void bridge_del_ports(struct bridge *, const struct shash *wanted_ports); static void bridge_add_ports(struct bridge *, const struct shash *wanted_ports); static void bridge_configure_datapath_id(struct bridge *); static void bridge_configure_netflow(struct bridge *); static void bridge_configure_forward_bpdu(struct bridge *); static void bridge_configure_mac_table(struct bridge *); static void bridge_configure_mcast_snooping(struct bridge *); static void bridge_configure_sflow(struct bridge *, int *sflow_bridge_number); static void bridge_configure_ipfix(struct bridge *); static void bridge_configure_spanning_tree(struct bridge *); static void bridge_configure_tables(struct bridge *); static void bridge_configure_dp_desc(struct bridge *); static void bridge_configure_aa(struct bridge *); static void bridge_aa_refresh_queued(struct bridge *); static bool bridge_aa_need_refresh(struct bridge *); static void bridge_configure_remotes(struct bridge *, const struct sockaddr_in *managers, size_t n_managers); static void bridge_pick_local_hw_addr(struct bridge *, struct eth_addr *ea, struct iface **hw_addr_iface); static uint64_t bridge_pick_datapath_id(struct bridge *, const struct eth_addr bridge_ea, struct iface *hw_addr_iface); static uint64_t dpid_from_hash(const void *, size_t nbytes); static bool bridge_has_bond_fake_iface(const struct bridge *, const char *name); static bool port_is_bond_fake_iface(const struct port *); static unixctl_cb_func qos_unixctl_show; static struct port *port_create(struct bridge *, const struct ovsrec_port *); static void port_del_ifaces(struct port *); static void port_destroy(struct port *); static struct port *port_lookup(const struct bridge *, const char *name); static void port_configure(struct port *); static struct lacp_settings *port_configure_lacp(struct port *, struct lacp_settings *); static void port_configure_bond(struct port *, struct bond_settings *); static bool port_is_synthetic(const struct port *); static void reconfigure_system_stats(const struct ovsrec_open_vswitch *); static void run_system_stats(void); static void bridge_configure_mirrors(struct bridge *); static struct mirror *mirror_create(struct bridge *, const struct ovsrec_mirror *); static void mirror_destroy(struct mirror *); static bool mirror_configure(struct mirror *); static void mirror_refresh_stats(struct mirror *); static void iface_configure_lacp(struct iface *, struct lacp_slave_settings *); static bool iface_create(struct bridge *, const struct ovsrec_interface *, const struct ovsrec_port *); static bool iface_is_internal(const struct ovsrec_interface *iface, const struct ovsrec_bridge *br); static const char *iface_get_type(const struct ovsrec_interface *, const struct ovsrec_bridge *); static void iface_destroy(struct iface *); static void iface_destroy__(struct iface *); static struct iface *iface_lookup(const struct bridge *, const char *name); static struct iface *iface_find(const char *name); static struct iface *iface_from_ofp_port(const struct bridge *, ofp_port_t ofp_port); static void iface_set_mac(const struct bridge *, const struct port *, struct iface *); static void iface_set_ofport(const struct ovsrec_interface *, ofp_port_t ofport); static void iface_clear_db_record(const struct ovsrec_interface *if_cfg, char *errp); static void iface_configure_qos(struct iface *, const struct ovsrec_qos *); static void iface_configure_cfm(struct iface *); static void iface_refresh_cfm_stats(struct iface *); static void iface_refresh_stats(struct iface *); static void iface_refresh_netdev_status(struct iface *); static void iface_refresh_ofproto_status(struct iface *); static bool iface_is_synthetic(const struct iface *); static ofp_port_t iface_get_requested_ofp_port( const struct ovsrec_interface *); static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *); /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * * This is deprecated. It is only for compatibility with broken device drivers * in old versions of Linux that do not properly support VLANs when VLAN * devices are not used. When broken device drivers are no longer in * widespread use, we will delete these interfaces. */ /* True if VLAN splinters are enabled on any interface, false otherwise.*/ static bool vlan_splinters_enabled_anywhere; static bool vlan_splinters_is_enabled(const struct ovsrec_interface *); static unsigned long int *collect_splinter_vlans( const struct ovsrec_open_vswitch *); static void configure_splinter_port(struct port *); static void add_vlan_splinter_ports(struct bridge *, const unsigned long int *splinter_vlans, struct shash *ports); static void discover_types(const struct ovsrec_open_vswitch *cfg); static void bridge_init_ofproto(const struct ovsrec_open_vswitch *cfg) { struct shash iface_hints; static bool initialized = false; int i; if (initialized) { return; } shash_init(&iface_hints); if (cfg) { for (i = 0; i < cfg->n_bridges; i++) { const struct ovsrec_bridge *br_cfg = cfg->bridges[i]; int j; for (j = 0; j < br_cfg->n_ports; j++) { struct ovsrec_port *port_cfg = br_cfg->ports[j]; int k; for (k = 0; k < port_cfg->n_interfaces; k++) { struct ovsrec_interface *if_cfg = port_cfg->interfaces[k]; struct iface_hint *iface_hint; iface_hint = xmalloc(sizeof *iface_hint); iface_hint->br_name = br_cfg->name; iface_hint->br_type = br_cfg->datapath_type; iface_hint->ofp_port = iface_pick_ofport(if_cfg); shash_add(&iface_hints, if_cfg->name, iface_hint); } } } } ofproto_init(&iface_hints); shash_destroy_free_data(&iface_hints); initialized = true; } static void if_change_cb(void *aux OVS_UNUSED) { ifaces_changed = true; } /* Public functions. */ /* Initializes the bridge module, configuring it to obtain its configuration * from an OVSDB server accessed over 'remote', which should be a string in a * form acceptable to ovsdb_idl_create(). */ void bridge_init(const char *remote) { /* Create connection to database. */ idl = ovsdb_idl_create(remote, &ovsrec_idl_class, true, true); idl_seqno = ovsdb_idl_get_seqno(idl); ovsdb_idl_set_lock(idl, "ovs_vswitchd"); ovsdb_idl_verify_write_only(idl); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_cur_cfg); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_statistics); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_datapath_types); ovsdb_idl_omit_alert(idl, &ovsrec_open_vswitch_col_iface_types); ovsdb_idl_omit(idl, &ovsrec_open_vswitch_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_open_vswitch_col_ovs_version); ovsdb_idl_omit(idl, &ovsrec_open_vswitch_col_db_version); ovsdb_idl_omit(idl, &ovsrec_open_vswitch_col_system_type); ovsdb_idl_omit(idl, &ovsrec_open_vswitch_col_system_version); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_datapath_id); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_datapath_version); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_status); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_rstp_status); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_stp_enable); ovsdb_idl_omit_alert(idl, &ovsrec_bridge_col_rstp_enable); ovsdb_idl_omit(idl, &ovsrec_bridge_col_external_ids); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_status); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_rstp_status); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_rstp_statistics); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_statistics); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_bond_active_slave); ovsdb_idl_omit(idl, &ovsrec_port_col_external_ids); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_trunks); ovsdb_idl_omit_alert(idl, &ovsrec_port_col_vlan_mode); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_admin_state); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_duplex); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_speed); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_state); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_link_resets); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mac_in_use); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ifindex); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_mtu); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_ofport); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_statistics); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_status); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_fault_status); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_mpids); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_flap_count); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_health); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_cfm_remote_opstate); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_bfd_status); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_lacp_current); ovsdb_idl_omit_alert(idl, &ovsrec_interface_col_error); ovsdb_idl_omit(idl, &ovsrec_interface_col_external_ids); ovsdb_idl_omit_alert(idl, &ovsrec_controller_col_is_connected); ovsdb_idl_omit_alert(idl, &ovsrec_controller_col_role); ovsdb_idl_omit_alert(idl, &ovsrec_controller_col_status); ovsdb_idl_omit(idl, &ovsrec_controller_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_qos_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_queue_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_mirror_col_external_ids); ovsdb_idl_omit_alert(idl, &ovsrec_mirror_col_statistics); ovsdb_idl_omit(idl, &ovsrec_netflow_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_sflow_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_ipfix_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_flow_sample_collector_set_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_manager_col_external_ids); ovsdb_idl_omit(idl, &ovsrec_manager_col_inactivity_probe); ovsdb_idl_omit(idl, &ovsrec_manager_col_is_connected); ovsdb_idl_omit(idl, &ovsrec_manager_col_max_backoff); ovsdb_idl_omit(idl, &ovsrec_manager_col_status); ovsdb_idl_omit(idl, &ovsrec_ssl_col_external_ids); /* Register unixctl commands. */ unixctl_command_register("qos/show", "interface", 1, 1, qos_unixctl_show, NULL); unixctl_command_register("bridge/dump-flows", "bridge", 1, 1, bridge_unixctl_dump_flows, NULL); unixctl_command_register("bridge/reconnect", "[bridge]", 0, 1, bridge_unixctl_reconnect, NULL); lacp_init(); bond_init(); cfm_init(); bfd_init(); ovs_numa_init(); stp_init(); lldp_init(); rstp_init(); ifnotifier = if_notifier_create(if_change_cb, NULL); } void bridge_exit(void) { struct bridge *br, *next_br; if_notifier_destroy(ifnotifier); HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) { bridge_destroy(br, false); } ovsdb_idl_destroy(idl); } /* Looks at the list of managers in 'ovs_cfg' and extracts their remote IP * addresses and ports into '*managersp' and '*n_managersp'. The caller is * responsible for freeing '*managersp' (with free()). * * You may be asking yourself "why does ovs-vswitchd care?", because * ovsdb-server is responsible for connecting to the managers, and ovs-vswitchd * should not be and in fact is not directly involved in that. But * ovs-vswitchd needs to make sure that ovsdb-server can reach the managers, so * it has to tell in-band control where the managers are to enable that. * (Thus, only managers connected in-band and with non-loopback addresses * are collected.) */ static void collect_in_band_managers(const struct ovsrec_open_vswitch *ovs_cfg, struct sockaddr_in **managersp, size_t *n_managersp) { struct sockaddr_in *managers = NULL; size_t n_managers = 0; struct sset targets; size_t i; /* Collect all of the potential targets from the "targets" columns of the * rows pointed to by "manager_options", excluding any that are * out-of-band. */ sset_init(&targets); for (i = 0; i < ovs_cfg->n_manager_options; i++) { struct ovsrec_manager *m = ovs_cfg->manager_options[i]; if (m->connection_mode && !strcmp(m->connection_mode, "out-of-band")) { sset_find_and_delete(&targets, m->target); } else { sset_add(&targets, m->target); } } /* Now extract the targets' IP addresses. */ if (!sset_is_empty(&targets)) { const char *target; managers = xmalloc(sset_count(&targets) * sizeof *managers); SSET_FOR_EACH (target, &targets) { union { struct sockaddr_storage ss; struct sockaddr_in in; } sa; /* Ignore loopback. */ if (stream_parse_target_with_default_port(target, OVSDB_PORT, &sa.ss) && sa.ss.ss_family == AF_INET && sa.in.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { managers[n_managers++] = sa.in; } } } sset_destroy(&targets); *managersp = managers; *n_managersp = n_managers; } static void bridge_reconfigure(const struct ovsrec_open_vswitch *ovs_cfg) { unsigned long int *splinter_vlans; struct sockaddr_in *managers; struct bridge *br, *next; int sflow_bridge_number; size_t n_managers; COVERAGE_INC(bridge_reconfigure); ofproto_set_flow_limit(smap_get_int(&ovs_cfg->other_config, "flow-limit", OFPROTO_FLOW_LIMIT_DEFAULT)); ofproto_set_max_idle(smap_get_int(&ovs_cfg->other_config, "max-idle", OFPROTO_MAX_IDLE_DEFAULT)); ofproto_set_n_dpdk_rxqs(smap_get_int(&ovs_cfg->other_config, "n-dpdk-rxqs", 0)); ofproto_set_cpu_mask(smap_get(&ovs_cfg->other_config, "pmd-cpu-mask")); ofproto_set_threads( smap_get_int(&ovs_cfg->other_config, "n-handler-threads", 0), smap_get_int(&ovs_cfg->other_config, "n-revalidator-threads", 0)); /* Destroy "struct bridge"s, "struct port"s, and "struct iface"s according * to 'ovs_cfg', with only very minimal configuration otherwise. * * This is mostly an update to bridge data structures. Nothing is pushed * down to ofproto or lower layers. */ add_del_bridges(ovs_cfg); splinter_vlans = collect_splinter_vlans(ovs_cfg); HMAP_FOR_EACH (br, node, &all_bridges) { bridge_collect_wanted_ports(br, splinter_vlans, &br->wanted_ports); bridge_del_ports(br, &br->wanted_ports); } free(splinter_vlans); /* Start pushing configuration changes down to the ofproto layer: * * - Delete ofprotos that are no longer configured. * * - Delete ports that are no longer configured. * * - Reconfigure existing ports to their desired configurations, or * delete them if not possible. * * We have to do all the deletions before we can do any additions, because * the ports to be added might require resources that will be freed up by * deletions (they might especially overlap in name). */ bridge_delete_ofprotos(); HMAP_FOR_EACH (br, node, &all_bridges) { if (br->ofproto) { bridge_delete_or_reconfigure_ports(br); } } /* Finish pushing configuration changes to the ofproto layer: * * - Create ofprotos that are missing. * * - Add ports that are missing. */ HMAP_FOR_EACH_SAFE (br, next, node, &all_bridges) { if (!br->ofproto) { int error; error = ofproto_create(br->name, br->type, &br->ofproto); if (error) { VLOG_ERR("failed to create bridge %s: %s", br->name, ovs_strerror(error)); shash_destroy(&br->wanted_ports); bridge_destroy(br, true); } else { /* Trigger storing datapath version. */ seq_change(connectivity_seq_get()); } } } HMAP_FOR_EACH (br, node, &all_bridges) { bridge_add_ports(br, &br->wanted_ports); shash_destroy(&br->wanted_ports); } reconfigure_system_stats(ovs_cfg); /* Complete the configuration. */ sflow_bridge_number = 0; collect_in_band_managers(ovs_cfg, &managers, &n_managers); HMAP_FOR_EACH (br, node, &all_bridges) { struct port *port; /* We need the datapath ID early to allow LACP ports to use it as the * default system ID. */ bridge_configure_datapath_id(br); HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct iface *iface; port_configure(port); LIST_FOR_EACH (iface, port_elem, &port->ifaces) { iface_set_ofport(iface->cfg, iface->ofp_port); /* Clear eventual previous errors */ ovsrec_interface_set_error(iface->cfg, NULL); iface_configure_cfm(iface); iface_configure_qos(iface, port->cfg->qos); iface_set_mac(br, port, iface); ofproto_port_set_bfd(br->ofproto, iface->ofp_port, &iface->cfg->bfd); ofproto_port_set_lldp(br->ofproto, iface->ofp_port, &iface->cfg->lldp); } } bridge_configure_mirrors(br); bridge_configure_forward_bpdu(br); bridge_configure_mac_table(br); bridge_configure_mcast_snooping(br); bridge_configure_remotes(br, managers, n_managers); bridge_configure_netflow(br); bridge_configure_sflow(br, &sflow_bridge_number); bridge_configure_ipfix(br); bridge_configure_spanning_tree(br); bridge_configure_tables(br); bridge_configure_dp_desc(br); bridge_configure_aa(br); } free(managers); /* The ofproto-dpif provider does some final reconfiguration in its * ->type_run() function. We have to call it before notifying the database * client that reconfiguration is complete, otherwise there is a very * narrow race window in which e.g. ofproto/trace will not recognize the * new configuration (sometimes this causes unit test failures). */ bridge_run__(); } /* Delete ofprotos which aren't configured or have the wrong type. Create * ofprotos which don't exist but need to. */ static void bridge_delete_ofprotos(void) { struct bridge *br; struct sset names; struct sset types; const char *type; /* Delete ofprotos with no bridge or with the wrong type. */ sset_init(&names); sset_init(&types); ofproto_enumerate_types(&types); SSET_FOR_EACH (type, &types) { const char *name; ofproto_enumerate_names(type, &names); SSET_FOR_EACH (name, &names) { br = bridge_lookup(name); if (!br || strcmp(type, br->type)) { ofproto_delete(name, type); } } } sset_destroy(&names); sset_destroy(&types); } static ofp_port_t * add_ofp_port(ofp_port_t port, ofp_port_t *ports, size_t *n, size_t *allocated) { if (*n >= *allocated) { ports = x2nrealloc(ports, allocated, sizeof *ports); } ports[(*n)++] = port; return ports; } static void bridge_delete_or_reconfigure_ports(struct bridge *br) { struct ofproto_port ofproto_port; struct ofproto_port_dump dump; struct sset ofproto_ports; struct port *port, *port_next; /* List of "ofp_port"s to delete. We make a list instead of deleting them * right away because ofproto implementations aren't necessarily able to * iterate through a changing list of ports in an entirely robust way. */ ofp_port_t *del; size_t n, allocated; size_t i; del = NULL; n = allocated = 0; sset_init(&ofproto_ports); /* Main task: Iterate over the ports in 'br->ofproto' and remove the ports * that are not configured in the database. (This commonly happens when * ports have been deleted, e.g. with "ovs-vsctl del-port".) * * Side tasks: Reconfigure the ports that are still in 'br'. Delete ports * that have the wrong OpenFlow port number (and arrange to add them back * with the correct OpenFlow port number). */ OFPROTO_PORT_FOR_EACH (&ofproto_port, &dump, br->ofproto) { ofp_port_t requested_ofp_port; struct iface *iface; sset_add(&ofproto_ports, ofproto_port.name); iface = iface_lookup(br, ofproto_port.name); if (!iface) { /* No such iface is configured, so we should delete this * ofproto_port. * * As a corner case exception, keep the port if it's a bond fake * interface. */ if (bridge_has_bond_fake_iface(br, ofproto_port.name) && !strcmp(ofproto_port.type, "internal")) { continue; } goto delete; } if (strcmp(ofproto_port.type, iface->type) || netdev_set_config(iface->netdev, &iface->cfg->options, NULL)) { /* The interface is the wrong type or can't be configured. * Delete it. */ goto delete; } /* If the requested OpenFlow port for 'iface' changed, and it's not * already the correct port, then we might want to temporarily delete * this interface, so we can add it back again with the new OpenFlow * port number. */ requested_ofp_port = iface_get_requested_ofp_port(iface->cfg); if (iface->ofp_port != OFPP_LOCAL && requested_ofp_port != OFPP_NONE && requested_ofp_port != iface->ofp_port) { ofp_port_t victim_request; struct iface *victim; /* Check for an existing OpenFlow port currently occupying * 'iface''s requested port number. If there isn't one, then * delete this port. Otherwise we need to consider further. */ victim = iface_from_ofp_port(br, requested_ofp_port); if (!victim) { goto delete; } /* 'victim' is a port currently using 'iface''s requested port * number. Unless 'victim' specifically requested that port * number, too, then we can delete both 'iface' and 'victim' * temporarily. (We'll add both of them back again later with new * OpenFlow port numbers.) * * If 'victim' did request port number 'requested_ofp_port', just * like 'iface', then that's a configuration inconsistency that we * can't resolve. We might as well let it keep its current port * number. */ victim_request = iface_get_requested_ofp_port(victim->cfg); if (victim_request != requested_ofp_port) { del = add_ofp_port(victim->ofp_port, del, &n, &allocated); iface_destroy(victim); goto delete; } } /* Keep it. */ continue; delete: iface_destroy(iface); del = add_ofp_port(ofproto_port.ofp_port, del, &n, &allocated); } for (i = 0; i < n; i++) { ofproto_port_del(br->ofproto, del[i]); } free(del); /* Iterate over this module's idea of interfaces in 'br'. Remove any ports * that we didn't see when we iterated through the datapath, i.e. ports * that disappeared underneath use. This is an unusual situation, but it * can happen in some cases: * * - An admin runs a command like "ovs-dpctl del-port" (which is a bad * idea but could happen). * * - The port represented a device that disappeared, e.g. a tuntap * device destroyed via "tunctl -d", a physical Ethernet device * whose module was just unloaded via "rmmod", or a virtual NIC for a * VM whose VM was just terminated. */ HMAP_FOR_EACH_SAFE (port, port_next, hmap_node, &br->ports) { struct iface *iface, *iface_next; LIST_FOR_EACH_SAFE (iface, iface_next, port_elem, &port->ifaces) { if (!sset_contains(&ofproto_ports, iface->name)) { iface_destroy__(iface); } } if (list_is_empty(&port->ifaces)) { port_destroy(port); } } sset_destroy(&ofproto_ports); } static void bridge_add_ports__(struct bridge *br, const struct shash *wanted_ports, bool with_requested_port) { struct shash_node *port_node; SHASH_FOR_EACH (port_node, wanted_ports) { const struct ovsrec_port *port_cfg = port_node->data; size_t i; for (i = 0; i < port_cfg->n_interfaces; i++) { const struct ovsrec_interface *iface_cfg = port_cfg->interfaces[i]; ofp_port_t requested_ofp_port; requested_ofp_port = iface_get_requested_ofp_port(iface_cfg); if ((requested_ofp_port != OFPP_NONE) == with_requested_port) { struct iface *iface = iface_lookup(br, iface_cfg->name); if (!iface) { iface_create(br, iface_cfg, port_cfg); } } } } } static void bridge_add_ports(struct bridge *br, const struct shash *wanted_ports) { /* First add interfaces that request a particular port number. */ bridge_add_ports__(br, wanted_ports, true); /* Then add interfaces that want automatic port number assignment. * We add these afterward to avoid accidentally taking a specifically * requested port number. */ bridge_add_ports__(br, wanted_ports, false); } static void port_configure(struct port *port) { const struct ovsrec_port *cfg = port->cfg; struct bond_settings bond_settings; struct lacp_settings lacp_settings; struct ofproto_bundle_settings s; struct iface *iface; if (cfg->vlan_mode && !strcmp(cfg->vlan_mode, "splinter")) { configure_splinter_port(port); return; } /* Get name. */ s.name = port->name; /* Get slaves. */ s.n_slaves = 0; s.slaves = xmalloc(list_size(&port->ifaces) * sizeof *s.slaves); LIST_FOR_EACH (iface, port_elem, &port->ifaces) { s.slaves[s.n_slaves++] = iface->ofp_port; } /* Get VLAN tag. */ s.vlan = -1; if (cfg->tag && *cfg->tag >= 0 && *cfg->tag <= 4095) { s.vlan = *cfg->tag; } /* Get VLAN trunks. */ s.trunks = NULL; if (cfg->n_trunks) { s.trunks = vlan_bitmap_from_array(cfg->trunks, cfg->n_trunks); } /* Get VLAN mode. */ if (cfg->vlan_mode) { if (!strcmp(cfg->vlan_mode, "access")) { s.vlan_mode = PORT_VLAN_ACCESS; } else if (!strcmp(cfg->vlan_mode, "trunk")) { s.vlan_mode = PORT_VLAN_TRUNK; } else if (!strcmp(cfg->vlan_mode, "native-tagged")) { s.vlan_mode = PORT_VLAN_NATIVE_TAGGED; } else if (!strcmp(cfg->vlan_mode, "native-untagged")) { s.vlan_mode = PORT_VLAN_NATIVE_UNTAGGED; } else { /* This "can't happen" because ovsdb-server should prevent it. */ VLOG_WARN("port %s: unknown VLAN mode %s, falling " "back to trunk mode", port->name, cfg->vlan_mode); s.vlan_mode = PORT_VLAN_TRUNK; } } else { if (s.vlan >= 0) { s.vlan_mode = PORT_VLAN_ACCESS; if (cfg->n_trunks) { VLOG_WARN("port %s: ignoring trunks in favor of implicit vlan", port->name); } } else { s.vlan_mode = PORT_VLAN_TRUNK; } } s.use_priority_tags = smap_get_bool(&cfg->other_config, "priority-tags", false); /* Get LACP settings. */ s.lacp = port_configure_lacp(port, &lacp_settings); if (s.lacp) { size_t i = 0; s.lacp_slaves = xmalloc(s.n_slaves * sizeof *s.lacp_slaves); LIST_FOR_EACH (iface, port_elem, &port->ifaces) { iface_configure_lacp(iface, &s.lacp_slaves[i++]); } } else { s.lacp_slaves = NULL; } /* Get bond settings. */ if (s.n_slaves > 1) { s.bond = &bond_settings; port_configure_bond(port, &bond_settings); } else { s.bond = NULL; LIST_FOR_EACH (iface, port_elem, &port->ifaces) { netdev_set_miimon_interval(iface->netdev, 0); } } /* Register. */ ofproto_bundle_register(port->bridge->ofproto, port, &s); /* Clean up. */ free(s.slaves); free(s.trunks); free(s.lacp_slaves); } /* Pick local port hardware address and datapath ID for 'br'. */ static void bridge_configure_datapath_id(struct bridge *br) { struct eth_addr ea; uint64_t dpid; struct iface *local_iface; struct iface *hw_addr_iface; char *dpid_string; bridge_pick_local_hw_addr(br, &ea, &hw_addr_iface); local_iface = iface_from_ofp_port(br, OFPP_LOCAL); if (local_iface) { int error = netdev_set_etheraddr(local_iface->netdev, ea); if (error) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); VLOG_ERR_RL(&rl, "bridge %s: failed to set bridge " "Ethernet address: %s", br->name, ovs_strerror(error)); } } br->ea = ea; dpid = bridge_pick_datapath_id(br, ea, hw_addr_iface); if (dpid != ofproto_get_datapath_id(br->ofproto)) { VLOG_INFO("bridge %s: using datapath ID %016"PRIx64, br->name, dpid); ofproto_set_datapath_id(br->ofproto, dpid); } dpid_string = xasprintf("%016"PRIx64, dpid); ovsrec_bridge_set_datapath_id(br->cfg, dpid_string); free(dpid_string); } /* Returns a bitmap of "enum ofputil_protocol"s that are allowed for use with * 'br'. */ static uint32_t bridge_get_allowed_versions(struct bridge *br) { if (!br->cfg->n_protocols) { return 0; } return ofputil_versions_from_strings(br->cfg->protocols, br->cfg->n_protocols); } /* Set NetFlow configuration on 'br'. */ static void bridge_configure_netflow(struct bridge *br) { struct ovsrec_netflow *cfg = br->cfg->netflow; struct netflow_options opts; if (!cfg) { ofproto_set_netflow(br->ofproto, NULL); return; } memset(&opts, 0, sizeof opts); /* Get default NetFlow configuration from datapath. * Apply overrides from 'cfg'. */ ofproto_get_netflow_ids(br->ofproto, &opts.engine_type, &opts.engine_id); if (cfg->engine_type) { opts.engine_type = *cfg->engine_type; } if (cfg->engine_id) { opts.engine_id = *cfg->engine_id; } /* Configure active timeout interval. */ opts.active_timeout = cfg->active_timeout; if (!opts.active_timeout) { opts.active_timeout = -1; } else if (opts.active_timeout < 0) { VLOG_WARN("bridge %s: active timeout interval set to negative " "value, using default instead (%d seconds)", br->name, NF_ACTIVE_TIMEOUT_DEFAULT); opts.active_timeout = -1; } /* Add engine ID to interface number to disambiguate bridgs? */ opts.add_id_to_iface = cfg->add_id_to_interface; if (opts.add_id_to_iface) { if (opts.engine_id > 0x7f) { VLOG_WARN("bridge %s: NetFlow port mangling may conflict with " "another vswitch, choose an engine id less than 128", br->name); } if (hmap_count(&br->ports) > 508) { VLOG_WARN("bridge %s: NetFlow port mangling will conflict with " "another port when more than 508 ports are used", br->name); } } /* Collectors. */ sset_init(&opts.collectors); sset_add_array(&opts.collectors, cfg->targets, cfg->n_targets); /* Configure. */ if (ofproto_set_netflow(br->ofproto, &opts)) { VLOG_ERR("bridge %s: problem setting netflow collectors", br->name); } sset_destroy(&opts.collectors); } /* Set sFlow configuration on 'br'. */ static void bridge_configure_sflow(struct bridge *br, int *sflow_bridge_number) { const struct ovsrec_sflow *cfg = br->cfg->sflow; struct ovsrec_controller **controllers; struct ofproto_sflow_options oso; size_t n_controllers; size_t i; if (!cfg) { ofproto_set_sflow(br->ofproto, NULL); return; } memset(&oso, 0, sizeof oso); sset_init(&oso.targets); sset_add_array(&oso.targets, cfg->targets, cfg->n_targets); oso.sampling_rate = SFL_DEFAULT_SAMPLING_RATE; if (cfg->sampling) { oso.sampling_rate = *cfg->sampling; } oso.polling_interval = SFL_DEFAULT_POLLING_INTERVAL; if (cfg->polling) { oso.polling_interval = *cfg->polling; } oso.header_len = SFL_DEFAULT_HEADER_SIZE; if (cfg->header) { oso.header_len = *cfg->header; } oso.sub_id = (*sflow_bridge_number)++; oso.agent_device = cfg->agent; oso.control_ip = NULL; n_controllers = bridge_get_controllers(br, &controllers); for (i = 0; i < n_controllers; i++) { if (controllers[i]->local_ip) { oso.control_ip = controllers[i]->local_ip; break; } } ofproto_set_sflow(br->ofproto, &oso); sset_destroy(&oso.targets); } /* Returns whether a IPFIX row is valid. */ static bool ovsrec_ipfix_is_valid(const struct ovsrec_ipfix *ipfix) { return ipfix && ipfix->n_targets > 0; } /* Returns whether a Flow_Sample_Collector_Set row is valid. */ static bool ovsrec_fscs_is_valid(const struct ovsrec_flow_sample_collector_set *fscs, const struct bridge *br) { return ovsrec_ipfix_is_valid(fscs->ipfix) && fscs->bridge == br->cfg; } /* Set IPFIX configuration on 'br'. */ static void bridge_configure_ipfix(struct bridge *br) { const struct ovsrec_ipfix *be_cfg = br->cfg->ipfix; bool valid_be_cfg = ovsrec_ipfix_is_valid(be_cfg); const struct ovsrec_flow_sample_collector_set *fe_cfg; struct ofproto_ipfix_bridge_exporter_options be_opts; struct ofproto_ipfix_flow_exporter_options *fe_opts = NULL; size_t n_fe_opts = 0; OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) { if (ovsrec_fscs_is_valid(fe_cfg, br)) { n_fe_opts++; } } if (!valid_be_cfg && n_fe_opts == 0) { ofproto_set_ipfix(br->ofproto, NULL, NULL, 0); return; } if (valid_be_cfg) { memset(&be_opts, 0, sizeof be_opts); sset_init(&be_opts.targets); sset_add_array(&be_opts.targets, be_cfg->targets, be_cfg->n_targets); if (be_cfg->sampling) { be_opts.sampling_rate = *be_cfg->sampling; } else { be_opts.sampling_rate = SFL_DEFAULT_SAMPLING_RATE; } if (be_cfg->obs_domain_id) { be_opts.obs_domain_id = *be_cfg->obs_domain_id; } if (be_cfg->obs_point_id) { be_opts.obs_point_id = *be_cfg->obs_point_id; } if (be_cfg->cache_active_timeout) { be_opts.cache_active_timeout = *be_cfg->cache_active_timeout; } if (be_cfg->cache_max_flows) { be_opts.cache_max_flows = *be_cfg->cache_max_flows; } be_opts.enable_tunnel_sampling = smap_get_bool(&be_cfg->other_config, "enable-tunnel-sampling", true); be_opts.enable_input_sampling = !smap_get_bool(&be_cfg->other_config, "enable-input-sampling", false); be_opts.enable_output_sampling = !smap_get_bool(&be_cfg->other_config, "enable-output-sampling", false); } if (n_fe_opts > 0) { struct ofproto_ipfix_flow_exporter_options *opts; fe_opts = xcalloc(n_fe_opts, sizeof *fe_opts); opts = fe_opts; OVSREC_FLOW_SAMPLE_COLLECTOR_SET_FOR_EACH(fe_cfg, idl) { if (ovsrec_fscs_is_valid(fe_cfg, br)) { opts->collector_set_id = fe_cfg->id; sset_init(&opts->targets); sset_add_array(&opts->targets, fe_cfg->ipfix->targets, fe_cfg->ipfix->n_targets); opts->cache_active_timeout = fe_cfg->ipfix->cache_active_timeout ? *fe_cfg->ipfix->cache_active_timeout : 0; opts->cache_max_flows = fe_cfg->ipfix->cache_max_flows ? *fe_cfg->ipfix->cache_max_flows : 0; opts++; } } } ofproto_set_ipfix(br->ofproto, valid_be_cfg ? &be_opts : NULL, fe_opts, n_fe_opts); if (valid_be_cfg) { sset_destroy(&be_opts.targets); } if (n_fe_opts > 0) { struct ofproto_ipfix_flow_exporter_options *opts = fe_opts; size_t i; for (i = 0; i < n_fe_opts; i++) { sset_destroy(&opts->targets); opts++; } free(fe_opts); } } static void port_configure_stp(const struct ofproto *ofproto, struct port *port, struct ofproto_port_stp_settings *port_s, int *port_num_counter, unsigned long *port_num_bitmap) { const char *config_str; struct iface *iface; if (!smap_get_bool(&port->cfg->other_config, "stp-enable", true)) { port_s->enable = false; return; } else { port_s->enable = true; } /* STP over bonds is not supported. */ if (!list_is_singleton(&port->ifaces)) { VLOG_ERR("port %s: cannot enable STP on bonds, disabling", port->name); port_s->enable = false; return; } iface = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); /* Internal ports shouldn't participate in spanning tree, so * skip them. */ if (!strcmp(iface->type, "internal")) { VLOG_DBG("port %s: disable STP on internal ports", port->name); port_s->enable = false; return; } /* STP on mirror output ports is not supported. */ if (ofproto_is_mirror_output_bundle(ofproto, port)) { VLOG_DBG("port %s: disable STP on mirror ports", port->name); port_s->enable = false; return; } config_str = smap_get(&port->cfg->other_config, "stp-port-num"); if (config_str) { unsigned long int port_num = strtoul(config_str, NULL, 0); int port_idx = port_num - 1; if (port_num < 1 || port_num > STP_MAX_PORTS) { VLOG_ERR("port %s: invalid stp-port-num", port->name); port_s->enable = false; return; } if (bitmap_is_set(port_num_bitmap, port_idx)) { VLOG_ERR("port %s: duplicate stp-port-num %lu, disabling", port->name, port_num); port_s->enable = false; return; } bitmap_set1(port_num_bitmap, port_idx); port_s->port_num = port_idx; } else { if (*port_num_counter >= STP_MAX_PORTS) { VLOG_ERR("port %s: too many STP ports, disabling", port->name); port_s->enable = false; return; } port_s->port_num = (*port_num_counter)++; } config_str = smap_get(&port->cfg->other_config, "stp-path-cost"); if (config_str) { port_s->path_cost = strtoul(config_str, NULL, 10); } else { enum netdev_features current; unsigned int mbps; netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL); mbps = netdev_features_to_bps(current, 100 * 1000 * 1000) / 1000000; port_s->path_cost = stp_convert_speed_to_cost(mbps); } config_str = smap_get(&port->cfg->other_config, "stp-port-priority"); if (config_str) { port_s->priority = strtoul(config_str, NULL, 0); } else { port_s->priority = STP_DEFAULT_PORT_PRIORITY; } } static void port_configure_rstp(const struct ofproto *ofproto, struct port *port, struct ofproto_port_rstp_settings *port_s, int *port_num_counter) { const char *config_str; struct iface *iface; if (!smap_get_bool(&port->cfg->other_config, "rstp-enable", true)) { port_s->enable = false; return; } else { port_s->enable = true; } /* RSTP over bonds is not supported. */ if (!list_is_singleton(&port->ifaces)) { VLOG_ERR("port %s: cannot enable RSTP on bonds, disabling", port->name); port_s->enable = false; return; } iface = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); /* Internal ports shouldn't participate in spanning tree, so * skip them. */ if (!strcmp(iface->type, "internal")) { VLOG_DBG("port %s: disable RSTP on internal ports", port->name); port_s->enable = false; return; } /* RSTP on mirror output ports is not supported. */ if (ofproto_is_mirror_output_bundle(ofproto, port)) { VLOG_DBG("port %s: disable RSTP on mirror ports", port->name); port_s->enable = false; return; } config_str = smap_get(&port->cfg->other_config, "rstp-port-num"); if (config_str) { unsigned long int port_num = strtoul(config_str, NULL, 0); if (port_num < 1 || port_num > RSTP_MAX_PORTS) { VLOG_ERR("port %s: invalid rstp-port-num", port->name); port_s->enable = false; return; } port_s->port_num = port_num; } else { if (*port_num_counter >= RSTP_MAX_PORTS) { VLOG_ERR("port %s: too many RSTP ports, disabling", port->name); port_s->enable = false; return; } /* If rstp-port-num is not specified, use 0. * rstp_port_set_port_number() will look for the first free one. */ port_s->port_num = 0; } config_str = smap_get(&port->cfg->other_config, "rstp-path-cost"); if (config_str) { port_s->path_cost = strtoul(config_str, NULL, 10); } else { enum netdev_features current; unsigned int mbps; netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL); mbps = netdev_features_to_bps(current, 100 * 1000 * 1000) / 1000000; port_s->path_cost = rstp_convert_speed_to_cost(mbps); } config_str = smap_get(&port->cfg->other_config, "rstp-port-priority"); if (config_str) { port_s->priority = strtoul(config_str, NULL, 0); } else { port_s->priority = RSTP_DEFAULT_PORT_PRIORITY; } config_str = smap_get(&port->cfg->other_config, "rstp-admin-p2p-mac"); if (config_str) { port_s->admin_p2p_mac_state = strtoul(config_str, NULL, 0); } else { port_s->admin_p2p_mac_state = RSTP_ADMIN_P2P_MAC_FORCE_TRUE; } port_s->admin_port_state = smap_get_bool(&port->cfg->other_config, "rstp-admin-port-state", true); port_s->admin_edge_port = smap_get_bool(&port->cfg->other_config, "rstp-port-admin-edge", false); port_s->auto_edge = smap_get_bool(&port->cfg->other_config, "rstp-port-auto-edge", true); port_s->mcheck = smap_get_bool(&port->cfg->other_config, "rstp-port-mcheck", false); } /* Set spanning tree configuration on 'br'. */ static void bridge_configure_stp(struct bridge *br, bool enable_stp) { if (!enable_stp) { ofproto_set_stp(br->ofproto, NULL); } else { struct ofproto_stp_settings br_s; const char *config_str; struct port *port; int port_num_counter; unsigned long *port_num_bitmap; config_str = smap_get(&br->cfg->other_config, "stp-system-id"); if (config_str) { struct eth_addr ea; if (eth_addr_from_string(config_str, &ea)) { br_s.system_id = eth_addr_to_uint64(ea); } else { br_s.system_id = eth_addr_to_uint64(br->ea); VLOG_ERR("bridge %s: invalid stp-system-id, defaulting " "to "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(br->ea)); } } else { br_s.system_id = eth_addr_to_uint64(br->ea); } config_str = smap_get(&br->cfg->other_config, "stp-priority"); if (config_str) { br_s.priority = strtoul(config_str, NULL, 0); } else { br_s.priority = STP_DEFAULT_BRIDGE_PRIORITY; } config_str = smap_get(&br->cfg->other_config, "stp-hello-time"); if (config_str) { br_s.hello_time = strtoul(config_str, NULL, 10) * 1000; } else { br_s.hello_time = STP_DEFAULT_HELLO_TIME; } config_str = smap_get(&br->cfg->other_config, "stp-max-age"); if (config_str) { br_s.max_age = strtoul(config_str, NULL, 10) * 1000; } else { br_s.max_age = STP_DEFAULT_MAX_AGE; } config_str = smap_get(&br->cfg->other_config, "stp-forward-delay"); if (config_str) { br_s.fwd_delay = strtoul(config_str, NULL, 10) * 1000; } else { br_s.fwd_delay = STP_DEFAULT_FWD_DELAY; } /* Configure STP on the bridge. */ if (ofproto_set_stp(br->ofproto, &br_s)) { VLOG_ERR("bridge %s: could not enable STP", br->name); return; } /* Users must either set the port number with the "stp-port-num" * configuration on all ports or none. If manual configuration * is not done, then we allocate them sequentially. */ port_num_counter = 0; port_num_bitmap = bitmap_allocate(STP_MAX_PORTS); HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct ofproto_port_stp_settings port_s; struct iface *iface; port_configure_stp(br->ofproto, port, &port_s, &port_num_counter, port_num_bitmap); /* As bonds are not supported, just apply configuration to * all interfaces. */ LIST_FOR_EACH (iface, port_elem, &port->ifaces) { if (ofproto_port_set_stp(br->ofproto, iface->ofp_port, &port_s)) { VLOG_ERR("port %s: could not enable STP", port->name); continue; } } } if (bitmap_scan(port_num_bitmap, 1, 0, STP_MAX_PORTS) != STP_MAX_PORTS && port_num_counter) { VLOG_ERR("bridge %s: must manually configure all STP port " "IDs or none, disabling", br->name); ofproto_set_stp(br->ofproto, NULL); } bitmap_free(port_num_bitmap); } } static void bridge_configure_rstp(struct bridge *br, bool enable_rstp) { if (!enable_rstp) { ofproto_set_rstp(br->ofproto, NULL); } else { struct ofproto_rstp_settings br_s; const char *config_str; struct port *port; int port_num_counter; config_str = smap_get(&br->cfg->other_config, "rstp-address"); if (config_str) { struct eth_addr ea; if (eth_addr_from_string(config_str, &ea)) { br_s.address = eth_addr_to_uint64(ea); } else { br_s.address = eth_addr_to_uint64(br->ea); VLOG_ERR("bridge %s: invalid rstp-address, defaulting " "to "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(br->ea)); } } else { br_s.address = eth_addr_to_uint64(br->ea); } config_str = smap_get(&br->cfg->other_config, "rstp-priority"); if (config_str) { br_s.priority = strtoul(config_str, NULL, 0); } else { br_s.priority = RSTP_DEFAULT_PRIORITY; } config_str = smap_get(&br->cfg->other_config, "rstp-ageing-time"); if (config_str) { br_s.ageing_time = strtoul(config_str, NULL, 0); } else { br_s.ageing_time = RSTP_DEFAULT_AGEING_TIME; } config_str = smap_get(&br->cfg->other_config, "rstp-force-protocol-version"); if (config_str) { br_s.force_protocol_version = strtoul(config_str, NULL, 0); } else { br_s.force_protocol_version = FPV_DEFAULT; } config_str = smap_get(&br->cfg->other_config, "rstp-max-age"); if (config_str) { br_s.bridge_max_age = strtoul(config_str, NULL, 10); } else { br_s.bridge_max_age = RSTP_DEFAULT_BRIDGE_MAX_AGE; } config_str = smap_get(&br->cfg->other_config, "rstp-forward-delay"); if (config_str) { br_s.bridge_forward_delay = strtoul(config_str, NULL, 10); } else { br_s.bridge_forward_delay = RSTP_DEFAULT_BRIDGE_FORWARD_DELAY; } config_str = smap_get(&br->cfg->other_config, "rstp-transmit-hold-count"); if (config_str) { br_s.transmit_hold_count = strtoul(config_str, NULL, 10); } else { br_s.transmit_hold_count = RSTP_DEFAULT_TRANSMIT_HOLD_COUNT; } /* Configure RSTP on the bridge. */ if (ofproto_set_rstp(br->ofproto, &br_s)) { VLOG_ERR("bridge %s: could not enable RSTP", br->name); return; } port_num_counter = 0; HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct ofproto_port_rstp_settings port_s; struct iface *iface; port_configure_rstp(br->ofproto, port, &port_s, &port_num_counter); /* As bonds are not supported, just apply configuration to * all interfaces. */ LIST_FOR_EACH (iface, port_elem, &port->ifaces) { if (ofproto_port_set_rstp(br->ofproto, iface->ofp_port, &port_s)) { VLOG_ERR("port %s: could not enable RSTP", port->name); continue; } } } } } static void bridge_configure_spanning_tree(struct bridge *br) { bool enable_rstp = br->cfg->rstp_enable; bool enable_stp = br->cfg->stp_enable; if (enable_rstp && enable_stp) { VLOG_WARN("%s: RSTP and STP are mutually exclusive but both are " "configured; enabling RSTP", br->name); enable_stp = false; } bridge_configure_stp(br, enable_stp); bridge_configure_rstp(br, enable_rstp); } static bool bridge_has_bond_fake_iface(const struct bridge *br, const char *name) { const struct port *port = port_lookup(br, name); return port && port_is_bond_fake_iface(port); } static bool port_is_bond_fake_iface(const struct port *port) { return port->cfg->bond_fake_iface && !list_is_short(&port->ifaces); } static void add_del_bridges(const struct ovsrec_open_vswitch *cfg) { struct bridge *br, *next; struct shash_node *node; struct shash new_br; size_t i; /* Collect new bridges' names and types. */ shash_init(&new_br); for (i = 0; i < cfg->n_bridges; i++) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); const struct ovsrec_bridge *br_cfg = cfg->bridges[i]; if (strchr(br_cfg->name, '/')) { /* Prevent remote ovsdb-server users from accessing arbitrary * directories, e.g. consider a bridge named "../../../etc/". */ VLOG_WARN_RL(&rl, "ignoring bridge with invalid name \"%s\"", br_cfg->name); } else if (!shash_add_once(&new_br, br_cfg->name, br_cfg)) { VLOG_WARN_RL(&rl, "bridge %s specified twice", br_cfg->name); } } /* Get rid of deleted bridges or those whose types have changed. * Update 'cfg' of bridges that still exist. */ HMAP_FOR_EACH_SAFE (br, next, node, &all_bridges) { br->cfg = shash_find_data(&new_br, br->name); if (!br->cfg || strcmp(br->type, ofproto_normalize_type( br->cfg->datapath_type))) { bridge_destroy(br, true); } } /* Add new bridges. */ SHASH_FOR_EACH(node, &new_br) { const struct ovsrec_bridge *br_cfg = node->data; struct bridge *br = bridge_lookup(br_cfg->name); if (!br) { bridge_create(br_cfg); } } shash_destroy(&new_br); } /* Configures 'netdev' based on the "options" column in 'iface_cfg'. * Returns 0 if successful, otherwise a positive errno value. */ static int iface_set_netdev_config(const struct ovsrec_interface *iface_cfg, struct netdev *netdev, char **errp) { return netdev_set_config(netdev, &iface_cfg->options, errp); } /* Opens a network device for 'if_cfg' and configures it. Adds the network * device to br->ofproto and stores the OpenFlow port number in '*ofp_portp'. * * If successful, returns 0 and stores the network device in '*netdevp'. On * failure, returns a positive errno value and stores NULL in '*netdevp'. */ static int iface_do_create(const struct bridge *br, const struct ovsrec_interface *iface_cfg, const struct ovsrec_port *port_cfg, ofp_port_t *ofp_portp, struct netdev **netdevp, char **errp) { struct netdev *netdev = NULL; int error; if (netdev_is_reserved_name(iface_cfg->name)) { VLOG_WARN("could not create interface %s, name is reserved", iface_cfg->name); error = EINVAL; goto error; } error = netdev_open(iface_cfg->name, iface_get_type(iface_cfg, br->cfg), &netdev); if (error) { VLOG_WARN_BUF(errp, "could not open network device %s (%s)", iface_cfg->name, ovs_strerror(error)); goto error; } error = iface_set_netdev_config(iface_cfg, netdev, errp); if (error) { goto error; } *ofp_portp = iface_pick_ofport(iface_cfg); error = ofproto_port_add(br->ofproto, netdev, ofp_portp); if (error) { goto error; } VLOG_INFO("bridge %s: added interface %s on port %d", br->name, iface_cfg->name, *ofp_portp); if (port_cfg->vlan_mode && !strcmp(port_cfg->vlan_mode, "splinter")) { netdev_turn_flags_on(netdev, NETDEV_UP, NULL); } *netdevp = netdev; return 0; error: *netdevp = NULL; netdev_close(netdev); return error; } /* Creates a new iface on 'br' based on 'if_cfg'. The new iface has OpenFlow * port number 'ofp_port'. If ofp_port is OFPP_NONE, an OpenFlow port is * automatically allocated for the iface. Takes ownership of and * deallocates 'if_cfg'. * * Return true if an iface is successfully created, false otherwise. */ static bool iface_create(struct bridge *br, const struct ovsrec_interface *iface_cfg, const struct ovsrec_port *port_cfg) { struct netdev *netdev; struct iface *iface; ofp_port_t ofp_port; struct port *port; char *errp = NULL; int error; /* Do the bits that can fail up front. */ ovs_assert(!iface_lookup(br, iface_cfg->name)); error = iface_do_create(br, iface_cfg, port_cfg, &ofp_port, &netdev, &errp); if (error) { iface_clear_db_record(iface_cfg, errp); free(errp); return false; } /* Get or create the port structure. */ port = port_lookup(br, port_cfg->name); if (!port) { port = port_create(br, port_cfg); } /* Create the iface structure. */ iface = xzalloc(sizeof *iface); list_push_back(&port->ifaces, &iface->port_elem); hmap_insert(&br->iface_by_name, &iface->name_node, hash_string(iface_cfg->name, 0)); iface->port = port; iface->name = xstrdup(iface_cfg->name); iface->ofp_port = ofp_port; iface->netdev = netdev; iface->type = iface_get_type(iface_cfg, br->cfg); iface->cfg = iface_cfg; hmap_insert(&br->ifaces, &iface->ofp_port_node, hash_ofp_port(ofp_port)); /* Populate initial status in database. */ iface_refresh_stats(iface); iface_refresh_netdev_status(iface); /* Add bond fake iface if necessary. */ if (port_is_bond_fake_iface(port)) { struct ofproto_port ofproto_port; if (ofproto_port_query_by_name(br->ofproto, port->name, &ofproto_port)) { struct netdev *netdev; int error; error = netdev_open(port->name, "internal", &netdev); if (!error) { ofp_port_t fake_ofp_port = OFPP_NONE; ofproto_port_add(br->ofproto, netdev, &fake_ofp_port); netdev_close(netdev); } else { VLOG_WARN("could not open network device %s (%s)", port->name, ovs_strerror(error)); } } else { /* Already exists, nothing to do. */ ofproto_port_destroy(&ofproto_port); } } return true; } /* Set forward BPDU option. */ static void bridge_configure_forward_bpdu(struct bridge *br) { ofproto_set_forward_bpdu(br->ofproto, smap_get_bool(&br->cfg->other_config, "forward-bpdu", false)); } /* Set MAC learning table configuration for 'br'. */ static void bridge_configure_mac_table(struct bridge *br) { const char *idle_time_str; int idle_time; const char *mac_table_size_str; int mac_table_size; idle_time_str = smap_get(&br->cfg->other_config, "mac-aging-time"); idle_time = (idle_time_str && atoi(idle_time_str) ? atoi(idle_time_str) : MAC_ENTRY_DEFAULT_IDLE_TIME); mac_table_size_str = smap_get(&br->cfg->other_config, "mac-table-size"); mac_table_size = (mac_table_size_str && atoi(mac_table_size_str) ? atoi(mac_table_size_str) : MAC_DEFAULT_MAX); ofproto_set_mac_table_config(br->ofproto, idle_time, mac_table_size); } /* Set multicast snooping table configuration for 'br'. */ static void bridge_configure_mcast_snooping(struct bridge *br) { if (!br->cfg->mcast_snooping_enable) { ofproto_set_mcast_snooping(br->ofproto, NULL); } else { struct port *port; struct ofproto_mcast_snooping_settings br_s; const char *idle_time_str; const char *max_entries_str; idle_time_str = smap_get(&br->cfg->other_config, "mcast-snooping-aging-time"); br_s.idle_time = (idle_time_str && atoi(idle_time_str) ? atoi(idle_time_str) : MCAST_ENTRY_DEFAULT_IDLE_TIME); max_entries_str = smap_get(&br->cfg->other_config, "mcast-snooping-table-size"); br_s.max_entries = (max_entries_str && atoi(max_entries_str) ? atoi(max_entries_str) : MCAST_DEFAULT_MAX_ENTRIES); br_s.flood_unreg = !smap_get_bool(&br->cfg->other_config, "mcast-snooping-disable-flood-unregistered", false); /* Configure multicast snooping on the bridge */ if (ofproto_set_mcast_snooping(br->ofproto, &br_s)) { VLOG_ERR("bridge %s: could not enable multicast snooping", br->name); return; } HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct ofproto_mcast_snooping_port_settings port_s; port_s.flood = smap_get_bool(&port->cfg->other_config, "mcast-snooping-flood", false); port_s.flood_reports = smap_get_bool(&port->cfg->other_config, "mcast-snooping-flood-reports", false); if (ofproto_port_set_mcast_snooping(br->ofproto, port, &port_s)) { VLOG_ERR("port %s: could not configure mcast snooping", port->name); } } } } static void find_local_hw_addr(const struct bridge *br, struct eth_addr *ea, const struct port *fake_br, struct iface **hw_addr_iface) { struct hmapx mirror_output_ports; struct port *port; bool found_addr = false; int error; int i; /* Mirror output ports don't participate in picking the local hardware * address. ofproto can't help us find out whether a given port is a * mirror output because we haven't configured mirrors yet, so we need to * accumulate them ourselves. */ hmapx_init(&mirror_output_ports); for (i = 0; i < br->cfg->n_mirrors; i++) { struct ovsrec_mirror *m = br->cfg->mirrors[i]; if (m->output_port) { hmapx_add(&mirror_output_ports, m->output_port); } } /* Otherwise choose the minimum non-local MAC address among all of the * interfaces. */ HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct eth_addr iface_ea; struct iface *candidate; struct iface *iface; /* Mirror output ports don't participate. */ if (hmapx_contains(&mirror_output_ports, port->cfg)) { continue; } /* Choose the MAC address to represent the port. */ iface = NULL; if (port->cfg->mac && eth_addr_from_string(port->cfg->mac, &iface_ea)) { /* Find the interface with this Ethernet address (if any) so that * we can provide the correct devname to the caller. */ LIST_FOR_EACH (candidate, port_elem, &port->ifaces) { struct eth_addr candidate_ea; if (!netdev_get_etheraddr(candidate->netdev, &candidate_ea) && eth_addr_equals(iface_ea, candidate_ea)) { iface = candidate; } } } else { /* Choose the interface whose MAC address will represent the port. * The Linux kernel bonding code always chooses the MAC address of * the first slave added to a bond, and the Fedora networking * scripts always add slaves to a bond in alphabetical order, so * for compatibility we choose the interface with the name that is * first in alphabetical order. */ LIST_FOR_EACH (candidate, port_elem, &port->ifaces) { if (!iface || strcmp(candidate->name, iface->name) < 0) { iface = candidate; } } /* The local port doesn't count (since we're trying to choose its * MAC address anyway). */ if (iface->ofp_port == OFPP_LOCAL) { continue; } /* For fake bridges we only choose from ports with the same tag */ if (fake_br && fake_br->cfg && fake_br->cfg->tag) { if (!port->cfg->tag) { continue; } if (*port->cfg->tag != *fake_br->cfg->tag) { continue; } } /* Grab MAC. */ error = netdev_get_etheraddr(iface->netdev, &iface_ea); if (error) { continue; } } /* Compare against our current choice. */ if (!eth_addr_is_multicast(iface_ea) && !eth_addr_is_local(iface_ea) && !eth_addr_is_reserved(iface_ea) && !eth_addr_is_zero(iface_ea) && (!found_addr || eth_addr_compare_3way(iface_ea, *ea) < 0)) { *ea = iface_ea; *hw_addr_iface = iface; found_addr = true; } } if (!found_addr) { *ea = br->default_ea; *hw_addr_iface = NULL; } hmapx_destroy(&mirror_output_ports); } static void bridge_pick_local_hw_addr(struct bridge *br, struct eth_addr *ea, struct iface **hw_addr_iface) { const char *hwaddr; *hw_addr_iface = NULL; /* Did the user request a particular MAC? */ hwaddr = smap_get(&br->cfg->other_config, "hwaddr"); if (hwaddr && eth_addr_from_string(hwaddr, ea)) { if (eth_addr_is_multicast(*ea)) { VLOG_ERR("bridge %s: cannot set MAC address to multicast " "address "ETH_ADDR_FMT, br->name, ETH_ADDR_ARGS(*ea)); } else if (eth_addr_is_zero(*ea)) { VLOG_ERR("bridge %s: cannot set MAC address to zero", br->name); } else { return; } } /* Find a local hw address */ find_local_hw_addr(br, ea, NULL, hw_addr_iface); } /* Choose and returns the datapath ID for bridge 'br' given that the bridge * Ethernet address is 'bridge_ea'. If 'bridge_ea' is the Ethernet address of * an interface on 'br', then that interface must be passed in as * 'hw_addr_iface'; if 'bridge_ea' was derived some other way, then * 'hw_addr_iface' must be passed in as a null pointer. */ static uint64_t bridge_pick_datapath_id(struct bridge *br, const struct eth_addr bridge_ea, struct iface *hw_addr_iface) { /* * The procedure for choosing a bridge MAC address will, in the most * ordinary case, also choose a unique MAC that we can use as a datapath * ID. In some special cases, though, multiple bridges will end up with * the same MAC address. This is OK for the bridges, but it will confuse * the OpenFlow controller, because each datapath needs a unique datapath * ID. * * Datapath IDs must be unique. It is also very desirable that they be * stable from one run to the next, so that policy set on a datapath * "sticks". */ const char *datapath_id; uint64_t dpid; datapath_id = smap_get(&br->cfg->other_config, "datapath-id"); if (datapath_id && dpid_from_string(datapath_id, &dpid)) { return dpid; } if (!hw_addr_iface) { /* * A purely internal bridge, that is, one that has no non-virtual * network devices on it at all, is difficult because it has no * natural unique identifier at all. * * When the host is a XenServer, we handle this case by hashing the * host's UUID with the name of the bridge. Names of bridges are * persistent across XenServer reboots, although they can be reused if * an internal network is destroyed and then a new one is later * created, so this is fairly effective. * * When the host is not a XenServer, we punt by using a random MAC * address on each run. */ const char *host_uuid = xenserver_get_host_uuid(); if (host_uuid) { char *combined = xasprintf("%s,%s", host_uuid, br->name); dpid = dpid_from_hash(combined, strlen(combined)); free(combined); return dpid; } } return eth_addr_to_uint64(bridge_ea); } static uint64_t dpid_from_hash(const void *data, size_t n) { union { uint8_t bytes[SHA1_DIGEST_SIZE]; struct eth_addr ea; } hash; sha1_bytes(data, n, hash.bytes); eth_addr_mark_random(&hash.ea); return eth_addr_to_uint64(hash.ea); } static void iface_refresh_netdev_status(struct iface *iface) { struct smap smap; enum netdev_features current; enum netdev_flags flags; const char *link_state; struct eth_addr mac; int64_t bps, mtu_64, ifindex64, link_resets; int mtu, error; if (iface_is_synthetic(iface)) { return; } if (iface->change_seq == netdev_get_change_seq(iface->netdev) && !status_txn_try_again) { return; } iface->change_seq = netdev_get_change_seq(iface->netdev); smap_init(&smap); if (!netdev_get_status(iface->netdev, &smap)) { ovsrec_interface_set_status(iface->cfg, &smap); } else { ovsrec_interface_set_status(iface->cfg, NULL); } smap_destroy(&smap); error = netdev_get_flags(iface->netdev, &flags); if (!error) { const char *state = flags & NETDEV_UP ? "up" : "down"; ovsrec_interface_set_admin_state(iface->cfg, state); } else { ovsrec_interface_set_admin_state(iface->cfg, NULL); } link_state = netdev_get_carrier(iface->netdev) ? "up" : "down"; ovsrec_interface_set_link_state(iface->cfg, link_state); link_resets = netdev_get_carrier_resets(iface->netdev); ovsrec_interface_set_link_resets(iface->cfg, &link_resets, 1); error = netdev_get_features(iface->netdev, ¤t, NULL, NULL, NULL); bps = !error ? netdev_features_to_bps(current, 0) : 0; if (bps) { ovsrec_interface_set_duplex(iface->cfg, netdev_features_is_full_duplex(current) ? "full" : "half"); ovsrec_interface_set_link_speed(iface->cfg, &bps, 1); } else { ovsrec_interface_set_duplex(iface->cfg, NULL); ovsrec_interface_set_link_speed(iface->cfg, NULL, 0); } error = netdev_get_mtu(iface->netdev, &mtu); if (!error) { mtu_64 = mtu; ovsrec_interface_set_mtu(iface->cfg, &mtu_64, 1); } else { ovsrec_interface_set_mtu(iface->cfg, NULL, 0); } error = netdev_get_etheraddr(iface->netdev, &mac); if (!error) { char mac_string[32]; sprintf(mac_string, ETH_ADDR_FMT, ETH_ADDR_ARGS(mac)); ovsrec_interface_set_mac_in_use(iface->cfg, mac_string); } else { ovsrec_interface_set_mac_in_use(iface->cfg, NULL); } /* The netdev may return a negative number (such as -EOPNOTSUPP) * if there is no valid ifindex number. */ ifindex64 = netdev_get_ifindex(iface->netdev); if (ifindex64 < 0) { ifindex64 = 0; } ovsrec_interface_set_ifindex(iface->cfg, &ifindex64, 1); } static void iface_refresh_ofproto_status(struct iface *iface) { int current; if (iface_is_synthetic(iface)) { return; } current = ofproto_port_is_lacp_current(iface->port->bridge->ofproto, iface->ofp_port); if (current >= 0) { bool bl = current; ovsrec_interface_set_lacp_current(iface->cfg, &bl, 1); } else { ovsrec_interface_set_lacp_current(iface->cfg, NULL, 0); } if (ofproto_port_cfm_status_changed(iface->port->bridge->ofproto, iface->ofp_port) || status_txn_try_again) { iface_refresh_cfm_stats(iface); } if (ofproto_port_bfd_status_changed(iface->port->bridge->ofproto, iface->ofp_port) || status_txn_try_again) { struct smap smap; smap_init(&smap); ofproto_port_get_bfd_status(iface->port->bridge->ofproto, iface->ofp_port, &smap); ovsrec_interface_set_bfd_status(iface->cfg, &smap); smap_destroy(&smap); } } /* Writes 'iface''s CFM statistics to the database. 'iface' must not be * synthetic. */ static void iface_refresh_cfm_stats(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; struct cfm_status status; int error; error = ofproto_port_get_cfm_status(iface->port->bridge->ofproto, iface->ofp_port, &status); if (error > 0) { ovsrec_interface_set_cfm_fault(cfg, NULL, 0); ovsrec_interface_set_cfm_fault_status(cfg, NULL, 0); ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); ovsrec_interface_set_cfm_flap_count(cfg, NULL, 0); ovsrec_interface_set_cfm_health(cfg, NULL, 0); ovsrec_interface_set_cfm_remote_mpids(cfg, NULL, 0); } else { const char *reasons[CFM_FAULT_N_REASONS]; int64_t cfm_health = status.health; int64_t cfm_flap_count = status.flap_count; bool faulted = status.faults != 0; size_t i, j; ovsrec_interface_set_cfm_fault(cfg, &faulted, 1); j = 0; for (i = 0; i < CFM_FAULT_N_REASONS; i++) { int reason = 1 << i; if (status.faults & reason) { reasons[j++] = cfm_fault_reason_to_str(reason); } } ovsrec_interface_set_cfm_fault_status(cfg, reasons, j); ovsrec_interface_set_cfm_flap_count(cfg, &cfm_flap_count, 1); if (status.remote_opstate >= 0) { const char *remote_opstate = status.remote_opstate ? "up" : "down"; ovsrec_interface_set_cfm_remote_opstate(cfg, remote_opstate); } else { ovsrec_interface_set_cfm_remote_opstate(cfg, NULL); } ovsrec_interface_set_cfm_remote_mpids(cfg, (const int64_t *)status.rmps, status.n_rmps); if (cfm_health >= 0) { ovsrec_interface_set_cfm_health(cfg, &cfm_health, 1); } else { ovsrec_interface_set_cfm_health(cfg, NULL, 0); } free(status.rmps); } } static void iface_refresh_stats(struct iface *iface) { #define IFACE_STATS \ IFACE_STAT(rx_packets, "rx_packets") \ IFACE_STAT(tx_packets, "tx_packets") \ IFACE_STAT(rx_bytes, "rx_bytes") \ IFACE_STAT(tx_bytes, "tx_bytes") \ IFACE_STAT(rx_dropped, "rx_dropped") \ IFACE_STAT(tx_dropped, "tx_dropped") \ IFACE_STAT(rx_errors, "rx_errors") \ IFACE_STAT(tx_errors, "tx_errors") \ IFACE_STAT(rx_frame_errors, "rx_frame_err") \ IFACE_STAT(rx_over_errors, "rx_over_err") \ IFACE_STAT(rx_crc_errors, "rx_crc_err") \ IFACE_STAT(collisions, "collisions") #define IFACE_STAT(MEMBER, NAME) + 1 enum { N_IFACE_STATS = IFACE_STATS }; #undef IFACE_STAT int64_t values[N_IFACE_STATS]; const char *keys[N_IFACE_STATS]; int n; struct netdev_stats stats; if (iface_is_synthetic(iface)) { return; } /* Intentionally ignore return value, since errors will set 'stats' to * all-1s, and we will deal with that correctly below. */ netdev_get_stats(iface->netdev, &stats); /* Copy statistics into keys[] and values[]. */ n = 0; #define IFACE_STAT(MEMBER, NAME) \ if (stats.MEMBER != UINT64_MAX) { \ keys[n] = NAME; \ values[n] = stats.MEMBER; \ n++; \ } IFACE_STATS; #undef IFACE_STAT ovs_assert(n <= N_IFACE_STATS); ovsrec_interface_set_statistics(iface->cfg, keys, values, n); #undef IFACE_STATS } static void br_refresh_datapath_info(struct bridge *br) { const char *version; version = (br->ofproto && br->ofproto->ofproto_class->get_datapath_version ? br->ofproto->ofproto_class->get_datapath_version(br->ofproto) : NULL); ovsrec_bridge_set_datapath_version(br->cfg, version ? version : ""); } static void br_refresh_stp_status(struct bridge *br) { struct smap smap = SMAP_INITIALIZER(&smap); struct ofproto *ofproto = br->ofproto; struct ofproto_stp_status status; if (ofproto_get_stp_status(ofproto, &status)) { return; } if (!status.enabled) { ovsrec_bridge_set_status(br->cfg, NULL); return; } smap_add_format(&smap, "stp_bridge_id", STP_ID_FMT, STP_ID_ARGS(status.bridge_id)); smap_add_format(&smap, "stp_designated_root", STP_ID_FMT, STP_ID_ARGS(status.designated_root)); smap_add_format(&smap, "stp_root_path_cost", "%d", status.root_path_cost); ovsrec_bridge_set_status(br->cfg, &smap); smap_destroy(&smap); } static void port_refresh_stp_status(struct port *port) { struct ofproto *ofproto = port->bridge->ofproto; struct iface *iface; struct ofproto_port_stp_status status; struct smap smap; if (port_is_synthetic(port)) { return; } /* STP doesn't currently support bonds. */ if (!list_is_singleton(&port->ifaces)) { ovsrec_port_set_status(port->cfg, NULL); return; } iface = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); if (ofproto_port_get_stp_status(ofproto, iface->ofp_port, &status)) { return; } if (!status.enabled) { ovsrec_port_set_status(port->cfg, NULL); return; } /* Set Status column. */ smap_init(&smap); smap_add_format(&smap, "stp_port_id", STP_PORT_ID_FMT, status.port_id); smap_add(&smap, "stp_state", stp_state_name(status.state)); smap_add_format(&smap, "stp_sec_in_state", "%u", status.sec_in_state); smap_add(&smap, "stp_role", stp_role_name(status.role)); ovsrec_port_set_status(port->cfg, &smap); smap_destroy(&smap); } static void port_refresh_stp_stats(struct port *port) { struct ofproto *ofproto = port->bridge->ofproto; struct iface *iface; struct ofproto_port_stp_stats stats; const char *keys[3]; int64_t int_values[3]; if (port_is_synthetic(port)) { return; } /* STP doesn't currently support bonds. */ if (!list_is_singleton(&port->ifaces)) { return; } iface = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); if (ofproto_port_get_stp_stats(ofproto, iface->ofp_port, &stats)) { return; } if (!stats.enabled) { ovsrec_port_set_statistics(port->cfg, NULL, NULL, 0); return; } /* Set Statistics column. */ keys[0] = "stp_tx_count"; int_values[0] = stats.tx_count; keys[1] = "stp_rx_count"; int_values[1] = stats.rx_count; keys[2] = "stp_error_count"; int_values[2] = stats.error_count; ovsrec_port_set_statistics(port->cfg, keys, int_values, ARRAY_SIZE(int_values)); } static void br_refresh_rstp_status(struct bridge *br) { struct smap smap = SMAP_INITIALIZER(&smap); struct ofproto *ofproto = br->ofproto; struct ofproto_rstp_status status; if (ofproto_get_rstp_status(ofproto, &status)) { return; } if (!status.enabled) { ovsrec_bridge_set_rstp_status(br->cfg, NULL); return; } smap_add_format(&smap, "rstp_bridge_id", RSTP_ID_FMT, RSTP_ID_ARGS(status.bridge_id)); smap_add_format(&smap, "rstp_root_path_cost", "%"PRIu32, status.root_path_cost); smap_add_format(&smap, "rstp_root_id", RSTP_ID_FMT, RSTP_ID_ARGS(status.root_id)); smap_add_format(&smap, "rstp_designated_id", RSTP_ID_FMT, RSTP_ID_ARGS(status.designated_id)); smap_add_format(&smap, "rstp_designated_port_id", RSTP_PORT_ID_FMT, status.designated_port_id); smap_add_format(&smap, "rstp_bridge_port_id", RSTP_PORT_ID_FMT, status.bridge_port_id); ovsrec_bridge_set_rstp_status(br->cfg, &smap); smap_destroy(&smap); } static void port_refresh_rstp_status(struct port *port) { struct ofproto *ofproto = port->bridge->ofproto; struct iface *iface; struct ofproto_port_rstp_status status; const char *keys[4]; int64_t int_values[4]; struct smap smap; if (port_is_synthetic(port)) { return; } /* RSTP doesn't currently support bonds. */ if (!list_is_singleton(&port->ifaces)) { ovsrec_port_set_rstp_status(port->cfg, NULL); return; } iface = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); if (ofproto_port_get_rstp_status(ofproto, iface->ofp_port, &status)) { return; } if (!status.enabled) { ovsrec_port_set_rstp_status(port->cfg, NULL); ovsrec_port_set_rstp_statistics(port->cfg, NULL, NULL, 0); return; } /* Set Status column. */ smap_init(&smap); smap_add_format(&smap, "rstp_port_id", RSTP_PORT_ID_FMT, status.port_id); smap_add_format(&smap, "rstp_port_role", "%s", rstp_port_role_name(status.role)); smap_add_format(&smap, "rstp_port_state", "%s", rstp_state_name(status.state)); smap_add_format(&smap, "rstp_designated_bridge_id", RSTP_ID_FMT, RSTP_ID_ARGS(status.designated_bridge_id)); smap_add_format(&smap, "rstp_designated_port_id", RSTP_PORT_ID_FMT, status.designated_port_id); smap_add_format(&smap, "rstp_designated_path_cost", "%"PRIu32, status.designated_path_cost); ovsrec_port_set_rstp_status(port->cfg, &smap); smap_destroy(&smap); /* Set Statistics column. */ keys[0] = "rstp_tx_count"; int_values[0] = status.tx_count; keys[1] = "rstp_rx_count"; int_values[1] = status.rx_count; keys[2] = "rstp_uptime"; int_values[2] = status.uptime; keys[3] = "rstp_error_count"; int_values[3] = status.error_count; ovsrec_port_set_rstp_statistics(port->cfg, keys, int_values, ARRAY_SIZE(int_values)); } static void port_refresh_bond_status(struct port *port, bool force_update) { struct eth_addr mac; /* Return if port is not a bond */ if (list_is_singleton(&port->ifaces)) { return; } if (bond_get_changed_active_slave(port->name, &mac, force_update)) { struct ds mac_s; ds_init(&mac_s); ds_put_format(&mac_s, ETH_ADDR_FMT, ETH_ADDR_ARGS(mac)); ovsrec_port_set_bond_active_slave(port->cfg, ds_cstr(&mac_s)); ds_destroy(&mac_s); } } static bool enable_system_stats(const struct ovsrec_open_vswitch *cfg) { return smap_get_bool(&cfg->other_config, "enable-statistics", false); } static void reconfigure_system_stats(const struct ovsrec_open_vswitch *cfg) { bool enable = enable_system_stats(cfg); system_stats_enable(enable); if (!enable) { ovsrec_open_vswitch_set_statistics(cfg, NULL); } } static void run_system_stats(void) { const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(idl); struct smap *stats; stats = system_stats_run(); if (stats && cfg) { struct ovsdb_idl_txn *txn; struct ovsdb_datum datum; txn = ovsdb_idl_txn_create(idl); ovsdb_datum_from_smap(&datum, stats); ovsdb_idl_txn_write(&cfg->header_, &ovsrec_open_vswitch_col_statistics, &datum); ovsdb_idl_txn_commit(txn); ovsdb_idl_txn_destroy(txn); free(stats); } } static const char * ofp12_controller_role_to_str(enum ofp12_controller_role role) { switch (role) { case OFPCR12_ROLE_EQUAL: return "other"; case OFPCR12_ROLE_MASTER: return "master"; case OFPCR12_ROLE_SLAVE: return "slave"; case OFPCR12_ROLE_NOCHANGE: default: return "*** INVALID ROLE ***"; } } static void refresh_controller_status(void) { struct bridge *br; struct shash info; const struct ovsrec_controller *cfg; shash_init(&info); /* Accumulate status for controllers on all bridges. */ HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_get_ofproto_controller_info(br->ofproto, &info); } /* Update each controller in the database with current status. */ OVSREC_CONTROLLER_FOR_EACH(cfg, idl) { struct ofproto_controller_info *cinfo = shash_find_data(&info, cfg->target); if (cinfo) { ovsrec_controller_set_is_connected(cfg, cinfo->is_connected); ovsrec_controller_set_role(cfg, ofp12_controller_role_to_str( cinfo->role)); ovsrec_controller_set_status(cfg, &cinfo->pairs); } else { ovsrec_controller_set_is_connected(cfg, false); ovsrec_controller_set_role(cfg, NULL); ovsrec_controller_set_status(cfg, NULL); } } ofproto_free_ofproto_controller_info(&info); } /* Update interface and mirror statistics if necessary. */ static void run_stats_update(void) { const struct ovsrec_open_vswitch *cfg = ovsrec_open_vswitch_first(idl); int stats_interval; if (!cfg) { return; } /* Statistics update interval should always be greater than or equal to * 5000 ms. */ stats_interval = MAX(smap_get_int(&cfg->other_config, "stats-update-interval", 5000), 5000); if (stats_timer_interval != stats_interval) { stats_timer_interval = stats_interval; stats_timer = LLONG_MIN; } if (time_msec() >= stats_timer) { enum ovsdb_idl_txn_status status; /* Rate limit the update. Do not start a new update if the * previous one is not done. */ if (!stats_txn) { struct bridge *br; stats_txn = ovsdb_idl_txn_create(idl); HMAP_FOR_EACH (br, node, &all_bridges) { struct port *port; struct mirror *m; HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct iface *iface; LIST_FOR_EACH (iface, port_elem, &port->ifaces) { iface_refresh_stats(iface); } port_refresh_stp_stats(port); } HMAP_FOR_EACH (m, hmap_node, &br->mirrors) { mirror_refresh_stats(m); } } refresh_controller_status(); } status = ovsdb_idl_txn_commit(stats_txn); if (status != TXN_INCOMPLETE) { stats_timer = time_msec() + stats_timer_interval; ovsdb_idl_txn_destroy(stats_txn); stats_txn = NULL; } } } static void stats_update_wait(void) { /* If the 'stats_txn' is non-null (transaction incomplete), waits for the * transaction to complete. Otherwise, waits for the 'stats_timer'. */ if (stats_txn) { ovsdb_idl_txn_wait(stats_txn); } else { poll_timer_wait_until(stats_timer); } } /* Update bridge/port/interface status if necessary. */ static void run_status_update(void) { if (!status_txn) { uint64_t seq; /* Rate limit the update. Do not start a new update if the * previous one is not done. */ seq = seq_read(connectivity_seq_get()); if (seq != connectivity_seqno || status_txn_try_again) { struct bridge *br; connectivity_seqno = seq; status_txn = ovsdb_idl_txn_create(idl); HMAP_FOR_EACH (br, node, &all_bridges) { struct port *port; br_refresh_stp_status(br); br_refresh_rstp_status(br); br_refresh_datapath_info(br); HMAP_FOR_EACH (port, hmap_node, &br->ports) { struct iface *iface; port_refresh_stp_status(port); port_refresh_rstp_status(port); port_refresh_bond_status(port, status_txn_try_again); LIST_FOR_EACH (iface, port_elem, &port->ifaces) { iface_refresh_netdev_status(iface); iface_refresh_ofproto_status(iface); } } } } } /* Commit the transaction and get the status. If the transaction finishes, * then destroy the transaction. Otherwise, keep it so that we can check * progress the next time that this function is called. */ if (status_txn) { enum ovsdb_idl_txn_status status; status = ovsdb_idl_txn_commit(status_txn); if (status != TXN_INCOMPLETE) { ovsdb_idl_txn_destroy(status_txn); status_txn = NULL; /* Sets the 'status_txn_try_again' if the transaction fails. */ if (status == TXN_SUCCESS || status == TXN_UNCHANGED) { status_txn_try_again = false; } else { status_txn_try_again = true; } } } /* Refresh AA port status if necessary. */ if (time_msec() >= aa_refresh_timer) { struct bridge *br; HMAP_FOR_EACH (br, node, &all_bridges) { if (bridge_aa_need_refresh(br)) { struct ovsdb_idl_txn *txn; txn = ovsdb_idl_txn_create(idl); bridge_aa_refresh_queued(br); ovsdb_idl_txn_commit(txn); ovsdb_idl_txn_destroy(txn); } } aa_refresh_timer = time_msec() + AA_REFRESH_INTERVAL; } } static void status_update_wait(void) { /* If the 'status_txn' is non-null (transaction incomplete), waits for the * transaction to complete. If the status update to database needs to be * run again (transaction fails), registers a timeout in * 'STATUS_CHECK_AGAIN_MSEC'. Otherwise, waits on the global connectivity * sequence number. */ if (status_txn) { ovsdb_idl_txn_wait(status_txn); } else if (status_txn_try_again) { poll_timer_wait_until(time_msec() + STATUS_CHECK_AGAIN_MSEC); } else { seq_wait(connectivity_seq_get(), connectivity_seqno); } } static void bridge_run__(void) { struct bridge *br; struct sset types; const char *type; /* Let each datapath type do the work that it needs to do. */ sset_init(&types); ofproto_enumerate_types(&types); SSET_FOR_EACH (type, &types) { ofproto_type_run(type); } sset_destroy(&types); /* Let each bridge do the work that it needs to do. */ HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_run(br->ofproto); } } void bridge_run(void) { static struct ovsrec_open_vswitch null_cfg; const struct ovsrec_open_vswitch *cfg; bool vlan_splinters_changed; ovsrec_open_vswitch_init(&null_cfg); ovsdb_idl_run(idl); if_notifier_run(); if (ovsdb_idl_is_lock_contended(idl)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); struct bridge *br, *next_br; VLOG_ERR_RL(&rl, "another ovs-vswitchd process is running, " "disabling this process (pid %ld) until it goes away", (long int) getpid()); HMAP_FOR_EACH_SAFE (br, next_br, node, &all_bridges) { bridge_destroy(br, false); } /* Since we will not be running system_stats_run() in this process * with the current situation of multiple ovs-vswitchd daemons, * disable system stats collection. */ system_stats_enable(false); return; } else if (!ovsdb_idl_has_lock(idl) || !ovsdb_idl_has_ever_connected(idl)) { /* Returns if not holding the lock or not done retrieving db * contents. */ return; } cfg = ovsrec_open_vswitch_first(idl); /* Initialize the ofproto library. This only needs to run once, but * it must be done after the configuration is set. If the * initialization has already occurred, bridge_init_ofproto() * returns immediately. */ bridge_init_ofproto(cfg); /* Once the value of flow-restore-wait is false, we no longer should * check its value from the database. */ if (cfg && ofproto_get_flow_restore_wait()) { ofproto_set_flow_restore_wait(smap_get_bool(&cfg->other_config, "flow-restore-wait", false)); } bridge_run__(); /* Re-configure SSL. We do this on every trip through the main loop, * instead of just when the database changes, because the contents of the * key and certificate files can change without the database changing. * * We do this before bridge_reconfigure() because that function might * initiate SSL connections and thus requires SSL to be configured. */ if (cfg && cfg->ssl) { const struct ovsrec_ssl *ssl = cfg->ssl; stream_ssl_set_key_and_cert(ssl->private_key, ssl->certificate); stream_ssl_set_ca_cert_file(ssl->ca_cert, ssl->bootstrap_ca_cert); } /* If VLAN splinters are in use, then we need to reconfigure if VLAN * usage has changed. */ vlan_splinters_changed = false; if (vlan_splinters_enabled_anywhere) { struct bridge *br; HMAP_FOR_EACH (br, node, &all_bridges) { if (ofproto_has_vlan_usage_changed(br->ofproto)) { vlan_splinters_changed = true; break; } } } if (ovsdb_idl_get_seqno(idl) != idl_seqno || vlan_splinters_changed || ifaces_changed) { struct ovsdb_idl_txn *txn; ifaces_changed = false; idl_seqno = ovsdb_idl_get_seqno(idl); txn = ovsdb_idl_txn_create(idl); bridge_reconfigure(cfg ? cfg : &null_cfg); if (cfg) { ovsrec_open_vswitch_set_cur_cfg(cfg, cfg->next_cfg); discover_types(cfg); } /* If we are completing our initial configuration for this run * of ovs-vswitchd, then keep the transaction around to monitor * it for completion. */ if (initial_config_done) { /* Always sets the 'status_txn_try_again' to check again, * in case that this transaction fails. */ status_txn_try_again = true; ovsdb_idl_txn_commit(txn); ovsdb_idl_txn_destroy(txn); } else { initial_config_done = true; daemonize_txn = txn; } } if (daemonize_txn) { enum ovsdb_idl_txn_status status = ovsdb_idl_txn_commit(daemonize_txn); if (status != TXN_INCOMPLETE) { ovsdb_idl_txn_destroy(daemonize_txn); daemonize_txn = NULL; /* ovs-vswitchd has completed initialization, so allow the * process that forked us to exit successfully. */ daemonize_complete(); vlog_enable_async(); VLOG_INFO_ONCE("%s (Open vSwitch) %s", program_name, VERSION); } } run_stats_update(); run_status_update(); run_system_stats(); } void bridge_wait(void) { struct sset types; const char *type; ovsdb_idl_wait(idl); if (daemonize_txn) { ovsdb_idl_txn_wait(daemonize_txn); } if_notifier_wait(); if (ifaces_changed) { poll_immediate_wake(); } sset_init(&types); ofproto_enumerate_types(&types); SSET_FOR_EACH (type, &types) { ofproto_type_wait(type); } sset_destroy(&types); if (!hmap_is_empty(&all_bridges)) { struct bridge *br; HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_wait(br->ofproto); } stats_update_wait(); status_update_wait(); } system_stats_wait(); } /* Adds some memory usage statistics for bridges into 'usage', for use with * memory_report(). */ void bridge_get_memory_usage(struct simap *usage) { struct bridge *br; struct sset types; const char *type; sset_init(&types); ofproto_enumerate_types(&types); SSET_FOR_EACH (type, &types) { ofproto_type_get_memory_usage(type, usage); } sset_destroy(&types); HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_get_memory_usage(br->ofproto, usage); } } /* QoS unixctl user interface functions. */ struct qos_unixctl_show_cbdata { struct ds *ds; struct iface *iface; }; static void qos_unixctl_show_queue(unsigned int queue_id, const struct smap *details, struct iface *iface, struct ds *ds) { struct netdev_queue_stats stats; struct smap_node *node; int error; ds_put_cstr(ds, "\n"); if (queue_id) { ds_put_format(ds, "Queue %u:\n", queue_id); } else { ds_put_cstr(ds, "Default:\n"); } SMAP_FOR_EACH (node, details) { ds_put_format(ds, "\t%s: %s\n", node->key, node->value); } error = netdev_get_queue_stats(iface->netdev, queue_id, &stats); if (!error) { if (stats.tx_packets != UINT64_MAX) { ds_put_format(ds, "\ttx_packets: %"PRIu64"\n", stats.tx_packets); } if (stats.tx_bytes != UINT64_MAX) { ds_put_format(ds, "\ttx_bytes: %"PRIu64"\n", stats.tx_bytes); } if (stats.tx_errors != UINT64_MAX) { ds_put_format(ds, "\ttx_errors: %"PRIu64"\n", stats.tx_errors); } } else { ds_put_format(ds, "\tFailed to get statistics for queue %u: %s", queue_id, ovs_strerror(error)); } } static void qos_unixctl_show(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED) { struct ds ds = DS_EMPTY_INITIALIZER; struct smap smap = SMAP_INITIALIZER(&smap); struct iface *iface; const char *type; struct smap_node *node; iface = iface_find(argv[1]); if (!iface) { unixctl_command_reply_error(conn, "no such interface"); return; } netdev_get_qos(iface->netdev, &type, &smap); if (*type != '\0') { struct netdev_queue_dump dump; struct smap details; unsigned int queue_id; ds_put_format(&ds, "QoS: %s %s\n", iface->name, type); SMAP_FOR_EACH (node, &smap) { ds_put_format(&ds, "%s: %s\n", node->key, node->value); } smap_init(&details); NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &dump, iface->netdev) { qos_unixctl_show_queue(queue_id, &details, iface, &ds); } smap_destroy(&details); unixctl_command_reply(conn, ds_cstr(&ds)); } else { ds_put_format(&ds, "QoS not configured on %s\n", iface->name); unixctl_command_reply_error(conn, ds_cstr(&ds)); } smap_destroy(&smap); ds_destroy(&ds); } /* Bridge reconfiguration functions. */ static void bridge_create(const struct ovsrec_bridge *br_cfg) { struct bridge *br; ovs_assert(!bridge_lookup(br_cfg->name)); br = xzalloc(sizeof *br); br->name = xstrdup(br_cfg->name); br->type = xstrdup(ofproto_normalize_type(br_cfg->datapath_type)); br->cfg = br_cfg; /* Derive the default Ethernet address from the bridge's UUID. This should * be unique and it will be stable between ovs-vswitchd runs. */ memcpy(&br->default_ea, &br_cfg->header_.uuid, ETH_ADDR_LEN); eth_addr_mark_random(&br->default_ea); hmap_init(&br->ports); hmap_init(&br->ifaces); hmap_init(&br->iface_by_name); hmap_init(&br->mirrors); hmap_init(&br->mappings); hmap_insert(&all_bridges, &br->node, hash_string(br->name, 0)); } static void bridge_destroy(struct bridge *br, bool del) { if (br) { struct mirror *mirror, *next_mirror; struct port *port, *next_port; HMAP_FOR_EACH_SAFE (port, next_port, hmap_node, &br->ports) { port_destroy(port); } HMAP_FOR_EACH_SAFE (mirror, next_mirror, hmap_node, &br->mirrors) { mirror_destroy(mirror); } hmap_remove(&all_bridges, &br->node); ofproto_destroy(br->ofproto, del); hmap_destroy(&br->ifaces); hmap_destroy(&br->ports); hmap_destroy(&br->iface_by_name); hmap_destroy(&br->mirrors); hmap_destroy(&br->mappings); free(br->name); free(br->type); free(br); } } static struct bridge * bridge_lookup(const char *name) { struct bridge *br; HMAP_FOR_EACH_WITH_HASH (br, node, hash_string(name, 0), &all_bridges) { if (!strcmp(br->name, name)) { return br; } } return NULL; } /* Handle requests for a listing of all flows known by the OpenFlow * stack, including those normally hidden. */ static void bridge_unixctl_dump_flows(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[], void *aux OVS_UNUSED) { struct bridge *br; struct ds results; br = bridge_lookup(argv[1]); if (!br) { unixctl_command_reply_error(conn, "Unknown bridge"); return; } ds_init(&results); ofproto_get_all_flows(br->ofproto, &results); unixctl_command_reply(conn, ds_cstr(&results)); ds_destroy(&results); } /* "bridge/reconnect [BRIDGE]": makes BRIDGE drop all of its controller * connections and reconnect. If BRIDGE is not specified, then all bridges * drop their controller connections and reconnect. */ static void bridge_unixctl_reconnect(struct unixctl_conn *conn, int argc, const char *argv[], void *aux OVS_UNUSED) { struct bridge *br; if (argc > 1) { br = bridge_lookup(argv[1]); if (!br) { unixctl_command_reply_error(conn, "Unknown bridge"); return; } ofproto_reconnect_controllers(br->ofproto); } else { HMAP_FOR_EACH (br, node, &all_bridges) { ofproto_reconnect_controllers(br->ofproto); } } unixctl_command_reply(conn, NULL); } static size_t bridge_get_controllers(const struct bridge *br, struct ovsrec_controller ***controllersp) { struct ovsrec_controller **controllers; size_t n_controllers; controllers = br->cfg->controller; n_controllers = br->cfg->n_controller; if (n_controllers == 1 && !strcmp(controllers[0]->target, "none")) { controllers = NULL; n_controllers = 0; } if (controllersp) { *controllersp = controllers; } return n_controllers; } static void bridge_collect_wanted_ports(struct bridge *br, const unsigned long int *splinter_vlans, struct shash *wanted_ports) { size_t i; shash_init(wanted_ports); for (i = 0; i < br->cfg->n_ports; i++) { const char *name = br->cfg->ports[i]->name; if (!shash_add_once(wanted_ports, name, br->cfg->ports[i])) { VLOG_WARN("bridge %s: %s specified twice as bridge port", br->name, name); } } if (bridge_get_controllers(br, NULL) && !shash_find(wanted_ports, br->name)) { VLOG_WARN("bridge %s: no port named %s, synthesizing one", br->name, br->name); ovsrec_interface_init(&br->synth_local_iface); ovsrec_port_init(&br->synth_local_port); br->synth_local_port.interfaces = &br->synth_local_ifacep; br->synth_local_port.n_interfaces = 1; br->synth_local_port.name = br->name; br->synth_local_iface.name = br->name; br->synth_local_iface.type = "internal"; br->synth_local_ifacep = &br->synth_local_iface; shash_add(wanted_ports, br->name, &br->synth_local_port); } if (splinter_vlans) { add_vlan_splinter_ports(br, splinter_vlans, wanted_ports); } } /* Deletes "struct port"s and "struct iface"s under 'br' which aren't * consistent with 'br->cfg'. Updates 'br->if_cfg_queue' with interfaces which * 'br' needs to complete its configuration. */ static void bridge_del_ports(struct bridge *br, const struct shash *wanted_ports) { struct shash_node *port_node; struct port *port, *next; /* Get rid of deleted ports. * Get rid of deleted interfaces on ports that still exist. */ HMAP_FOR_EACH_SAFE (port, next, hmap_node, &br->ports) { port->cfg = shash_find_data(wanted_ports, port->name); if (!port->cfg) { port_destroy(port); } else { port_del_ifaces(port); } } /* Update iface->cfg and iface->type in interfaces that still exist. */ SHASH_FOR_EACH (port_node, wanted_ports) { const struct ovsrec_port *port = port_node->data; size_t i; for (i = 0; i < port->n_interfaces; i++) { const struct ovsrec_interface *cfg = port->interfaces[i]; struct iface *iface = iface_lookup(br, cfg->name); const char *type = iface_get_type(cfg, br->cfg); if (iface) { iface->cfg = cfg; iface->type = type; } else if (!strcmp(type, "null")) { VLOG_WARN_ONCE("%s: The null interface type is deprecated and" " may be removed in February 2013. Please email" " dev@openvswitch.org with concerns.", cfg->name); } else { /* We will add new interfaces later. */ } } } } /* Initializes 'oc' appropriately as a management service controller for * 'br'. * * The caller must free oc->target when it is no longer needed. */ static void bridge_ofproto_controller_for_mgmt(const struct bridge *br, struct ofproto_controller *oc) { oc->target = xasprintf("punix:%s/%s.mgmt", ovs_rundir(), br->name); oc->max_backoff = 0; oc->probe_interval = 60; oc->band = OFPROTO_OUT_OF_BAND; oc->rate_limit = 0; oc->burst_limit = 0; oc->enable_async_msgs = true; oc->dscp = 0; } /* Converts ovsrec_controller 'c' into an ofproto_controller in 'oc'. */ static void bridge_ofproto_controller_from_ovsrec(const struct ovsrec_controller *c, struct ofproto_controller *oc) { int dscp; oc->target = c->target; oc->max_backoff = c->max_backoff ? *c->max_backoff / 1000 : 8; oc->probe_interval = c->inactivity_probe ? *c->inactivity_probe / 1000 : 5; oc->band = (!c->connection_mode || !strcmp(c->connection_mode, "in-band") ? OFPROTO_IN_BAND : OFPROTO_OUT_OF_BAND); oc->rate_limit = c->controller_rate_limit ? *c->controller_rate_limit : 0; oc->burst_limit = (c->controller_burst_limit ? *c->controller_burst_limit : 0); oc->enable_async_msgs = (!c->enable_async_messages || *c->enable_async_messages); dscp = smap_get_int(&c->other_config, "dscp", DSCP_DEFAULT); if (dscp < 0 || dscp > 63) { dscp = DSCP_DEFAULT; } oc->dscp = dscp; } /* Configures the IP stack for 'br''s local interface properly according to the * configuration in 'c'. */ static void bridge_configure_local_iface_netdev(struct bridge *br, struct ovsrec_controller *c) { struct netdev *netdev; struct in_addr mask, gateway; struct iface *local_iface; struct in_addr ip; /* If there's no local interface or no IP address, give up. */ local_iface = iface_from_ofp_port(br, OFPP_LOCAL); if (!local_iface || !c->local_ip || !inet_pton(AF_INET, c->local_ip, &ip)) { return; } /* Bring up the local interface. */ netdev = local_iface->netdev; netdev_turn_flags_on(netdev, NETDEV_UP, NULL); /* Configure the IP address and netmask. */ if (!c->local_netmask || !inet_pton(AF_INET, c->local_netmask, &mask) || !mask.s_addr) { mask.s_addr = guess_netmask(ip.s_addr); } if (!netdev_set_in4(netdev, ip, mask)) { VLOG_INFO("bridge %s: configured IP address "IP_FMT", netmask "IP_FMT, br->name, IP_ARGS(ip.s_addr), IP_ARGS(mask.s_addr)); } /* Configure the default gateway. */ if (c->local_gateway && inet_pton(AF_INET, c->local_gateway, &gateway) && gateway.s_addr) { if (!netdev_add_router(netdev, gateway)) { VLOG_INFO("bridge %s: configured gateway "IP_FMT, br->name, IP_ARGS(gateway.s_addr)); } } } /* Returns true if 'a' and 'b' are the same except that any number of slashes * in either string are treated as equal to any number of slashes in the other, * e.g. "x///y" is equal to "x/y". * * Also, if 'b_stoplen' bytes from 'b' are found to be equal to corresponding * bytes from 'a', the function considers this success. Specify 'b_stoplen' as * SIZE_MAX to compare all of 'a' to all of 'b' rather than just a prefix of * 'b' against a prefix of 'a'. */ static bool equal_pathnames(const char *a, const char *b, size_t b_stoplen) { const char *b_start = b; for (;;) { if (b - b_start >= b_stoplen) { return true; } else if (*a != *b) { return false; } else if (*a == '/') { a += strspn(a, "/"); b += strspn(b, "/"); } else if (*a == '\0') { return true; } else { a++; b++; } } } static void bridge_configure_remotes(struct bridge *br, const struct sockaddr_in *managers, size_t n_managers) { bool disable_in_band; struct ovsrec_controller **controllers; size_t n_controllers; enum ofproto_fail_mode fail_mode; struct ofproto_controller *ocs; size_t n_ocs; size_t i; /* Check if we should disable in-band control on this bridge. */ disable_in_band = smap_get_bool(&br->cfg->other_config, "disable-in-band", false); /* Set OpenFlow queue ID for in-band control. */ ofproto_set_in_band_queue(br->ofproto, smap_get_int(&br->cfg->other_config, "in-band-queue", -1)); if (disable_in_band) { ofproto_set_extra_in_band_remotes(br->ofproto, NULL, 0); } else { ofproto_set_extra_in_band_remotes(br->ofproto, managers, n_managers); } n_controllers = bridge_get_controllers(br, &controllers); ocs = xmalloc((n_controllers + 1) * sizeof *ocs); n_ocs = 0; bridge_ofproto_controller_for_mgmt(br, &ocs[n_ocs++]); for (i = 0; i < n_controllers; i++) { struct ovsrec_controller *c = controllers[i]; if (!strncmp(c->target, "punix:", 6) || !strncmp(c->target, "unix:", 5)) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); char *whitelist; if (!strncmp(c->target, "unix:", 5)) { /* Connect to a listening socket */ whitelist = xasprintf("unix:%s/", ovs_rundir()); if (strchr(c->target, '/') && !equal_pathnames(c->target, whitelist, strlen(whitelist))) { /* Absolute path specified, but not in ovs_rundir */ VLOG_ERR_RL(&rl, "bridge %s: Not connecting to socket " "controller \"%s\" due to possibility for " "remote exploit. Instead, specify socket " "in whitelisted \"%s\" or connect to " "\"unix:%s/%s.mgmt\" (which is always " "available without special configuration).", br->name, c->target, whitelist, ovs_rundir(), br->name); free(whitelist); continue; } } else { whitelist = xasprintf("punix:%s/%s.", ovs_rundir(), br->name); if (!equal_pathnames(c->target, whitelist, strlen(whitelist)) || strchr(c->target + strlen(whitelist), '/')) { /* Prevent remote ovsdb-server users from accessing * arbitrary Unix domain sockets and overwriting arbitrary * local files. */ VLOG_ERR_RL(&rl, "bridge %s: Not adding Unix domain socket " "controller \"%s\" due to possibility of " "overwriting local files. Instead, specify " "path in whitelisted format \"%s*\" or " "connect to \"unix:%s/%s.mgmt\" (which is " "always available without special " "configuration).", br->name, c->target, whitelist, ovs_rundir(), br->name); free(whitelist); continue; } } free(whitelist); } bridge_configure_local_iface_netdev(br, c); bridge_ofproto_controller_from_ovsrec(c, &ocs[n_ocs]); if (disable_in_band) { ocs[n_ocs].band = OFPROTO_OUT_OF_BAND; } n_ocs++; } ofproto_set_controllers(br->ofproto, ocs, n_ocs, bridge_get_allowed_versions(br)); free(ocs[0].target); /* From bridge_ofproto_controller_for_mgmt(). */ free(ocs); /* Set the fail-mode. */ fail_mode = !br->cfg->fail_mode || !strcmp(br->cfg->fail_mode, "standalone") ? OFPROTO_FAIL_STANDALONE : OFPROTO_FAIL_SECURE; ofproto_set_fail_mode(br->ofproto, fail_mode); /* Configure OpenFlow controller connection snooping. */ if (!ofproto_has_snoops(br->ofproto)) { struct sset snoops; sset_init(&snoops); sset_add_and_free(&snoops, xasprintf("punix:%s/%s.snoop", ovs_rundir(), br->name)); ofproto_set_snoops(br->ofproto, &snoops); sset_destroy(&snoops); } } static void bridge_configure_tables(struct bridge *br) { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); int n_tables; int i, j, k; n_tables = ofproto_get_n_tables(br->ofproto); j = 0; for (i = 0; i < n_tables; i++) { struct ofproto_table_settings s; bool use_default_prefixes = true; s.name = NULL; s.max_flows = UINT_MAX; s.groups = NULL; s.enable_eviction = false; s.n_groups = 0; s.n_prefix_fields = 0; memset(s.prefix_fields, ~0, sizeof(s.prefix_fields)); if (j < br->cfg->n_flow_tables && i == br->cfg->key_flow_tables[j]) { struct ovsrec_flow_table *cfg = br->cfg->value_flow_tables[j++]; s.name = cfg->name; if (cfg->n_flow_limit && *cfg->flow_limit < UINT_MAX) { s.max_flows = *cfg->flow_limit; } s.enable_eviction = (cfg->overflow_policy && !strcmp(cfg->overflow_policy, "evict")); if (cfg->n_groups) { s.groups = xmalloc(cfg->n_groups * sizeof *s.groups); for (k = 0; k < cfg->n_groups; k++) { const char *string = cfg->groups[k]; char *msg; msg = mf_parse_subfield__(&s.groups[k], &string); if (msg) { VLOG_WARN_RL(&rl, "bridge %s table %d: error parsing " "'groups' (%s)", br->name, i, msg); free(msg); } else if (*string) { VLOG_WARN_RL(&rl, "bridge %s table %d: 'groups' " "element '%s' contains trailing garbage", br->name, i, cfg->groups[k]); } else { s.n_groups++; } } } /* Prefix lookup fields. */ s.n_prefix_fields = 0; for (k = 0; k < cfg->n_prefixes; k++) { const char *name = cfg->prefixes[k]; const struct mf_field *mf; if (strcmp(name, "none") == 0) { use_default_prefixes = false; s.n_prefix_fields = 0; break; } mf = mf_from_name(name); if (!mf) { VLOG_WARN("bridge %s: 'prefixes' with unknown field: %s", br->name, name); continue; } if (mf->flow_be32ofs < 0 || mf->n_bits % 32) { VLOG_WARN("bridge %s: 'prefixes' with incompatible field: " "%s", br->name, name); continue; } if (s.n_prefix_fields >= ARRAY_SIZE(s.prefix_fields)) { VLOG_WARN("bridge %s: 'prefixes' with too many fields, " "field not used: %s", br->name, name); continue; } use_default_prefixes = false; s.prefix_fields[s.n_prefix_fields++] = mf->id; } } if (use_default_prefixes) { /* Use default values. */ s.n_prefix_fields = ARRAY_SIZE(default_prefix_fields); memcpy(s.prefix_fields, default_prefix_fields, sizeof default_prefix_fields); } else { int k; struct ds ds = DS_EMPTY_INITIALIZER; for (k = 0; k < s.n_prefix_fields; k++) { if (k) { ds_put_char(&ds, ','); } ds_put_cstr(&ds, mf_from_id(s.prefix_fields[k])->name); } if (s.n_prefix_fields == 0) { ds_put_cstr(&ds, "none"); } VLOG_INFO("bridge %s table %d: Prefix lookup with: %s.", br->name, i, ds_cstr(&ds)); ds_destroy(&ds); } ofproto_configure_table(br->ofproto, i, &s); free(s.groups); } for (; j < br->cfg->n_flow_tables; j++) { VLOG_WARN_RL(&rl, "bridge %s: ignoring configuration for flow table " "%"PRId64" not supported by this datapath", br->name, br->cfg->key_flow_tables[j]); } } static void bridge_configure_dp_desc(struct bridge *br) { ofproto_set_dp_desc(br->ofproto, smap_get(&br->cfg->other_config, "dp-desc")); } static struct aa_mapping * bridge_aa_mapping_find(struct bridge *br, const int64_t isid) { struct aa_mapping *m; HMAP_FOR_EACH_IN_BUCKET (m, hmap_node, hash_bytes(&isid, sizeof isid, 0), &br->mappings) { if (isid == m->isid) { return m; } } return NULL; } static struct aa_mapping * bridge_aa_mapping_create(struct bridge *br, const int64_t isid, const int64_t vlan) { struct aa_mapping *m; m = xzalloc(sizeof *m); m->bridge = br; m->isid = isid; m->vlan = vlan; m->br_name = xstrdup(br->name); hmap_insert(&br->mappings, &m->hmap_node, hash_bytes(&isid, sizeof isid, 0)); return m; } static void bridge_aa_mapping_destroy(struct aa_mapping *m) { if (m) { struct bridge *br = m->bridge; if (br->ofproto) { ofproto_aa_mapping_unregister(br->ofproto, m); } hmap_remove(&br->mappings, &m->hmap_node); if (m->br_name) { free(m->br_name); } free(m); } } static bool bridge_aa_mapping_configure(struct aa_mapping *m) { struct aa_mapping_settings s; s.isid = m->isid; s.vlan = m->vlan; /* Configure. */ ofproto_aa_mapping_register(m->bridge->ofproto, m, &s); return true; } static void bridge_configure_aa(struct bridge *br) { const struct ovsdb_datum *mc; struct ovsrec_autoattach *auto_attach = br->cfg->auto_attach; struct aa_settings aa_s; struct aa_mapping *m, *next; size_t i; if (!auto_attach) { ofproto_set_aa(br->ofproto, NULL, NULL); return; } memset(&aa_s, 0, sizeof aa_s); aa_s.system_description = auto_attach->system_description; aa_s.system_name = auto_attach->system_name; ofproto_set_aa(br->ofproto, NULL, &aa_s); mc = ovsrec_autoattach_get_mappings(auto_attach, OVSDB_TYPE_INTEGER, OVSDB_TYPE_INTEGER); HMAP_FOR_EACH_SAFE (m, next, hmap_node, &br->mappings) { union ovsdb_atom atom; atom.integer = m->isid; if (ovsdb_datum_find_key(mc, &atom, OVSDB_TYPE_UUID) == UINT_MAX) { VLOG_INFO("Deleting isid=%"PRIu32", vlan=%"PRIu16, m->isid, m->vlan); bridge_aa_mapping_destroy(m); } } /* Add new mappings and reconfigure existing ones. */ for (i = 0; i < auto_attach->n_mappings; ++i) { struct aa_mapping *m = bridge_aa_mapping_find(br, auto_attach->key_mappings[i]); if (!m) { VLOG_INFO("Adding isid=%"PRId64", vlan=%"PRId64, auto_attach->key_mappings[i], auto_attach->value_mappings[i]); m = bridge_aa_mapping_create(br, auto_attach->key_mappings[i], auto_attach->value_mappings[i]); if (!bridge_aa_mapping_configure(m)) { bridge_aa_mapping_destroy(m); } } } } static bool bridge_aa_need_refresh(struct bridge *br) { return ofproto_aa_vlan_get_queue_size(br->ofproto) > 0; } static void bridge_aa_update_trunks(struct port *port, struct bridge_aa_vlan *m) { int64_t *trunks = NULL; unsigned int i = 0; bool found = false, reconfigure = false; for (i = 0; i < port->cfg->n_trunks; i++) { if (port->cfg->trunks[i] == m->vlan) { found = true; break; } } switch (m->oper) { case BRIDGE_AA_VLAN_OPER_ADD: if (!found) { trunks = xmalloc(sizeof *trunks * (port->cfg->n_trunks + 1)); for (i = 0; i < port->cfg->n_trunks; i++) { trunks[i] = port->cfg->trunks[i]; } trunks[i++] = m->vlan; reconfigure = true; } break; case BRIDGE_AA_VLAN_OPER_REMOVE: if (found) { unsigned int j = 0; trunks = xmalloc(sizeof *trunks * (port->cfg->n_trunks - 1)); for (i = 0; i < port->cfg->n_trunks; i++) { if (port->cfg->trunks[i] != m->vlan) { trunks[j++] = port->cfg->trunks[i]; } } i = j; reconfigure = true; } break; case BRIDGE_AA_VLAN_OPER_UNDEF: default: VLOG_WARN("unrecognized operation %u", m->oper); break; } if (reconfigure) { /* VLAN switching under trunk mode cause the trunk port to switch all * VLANs, see ovs-vswitchd.conf.db */ if (i == 0) { static char *vlan_mode_access = "access"; ovsrec_port_set_vlan_mode(port->cfg, vlan_mode_access); } if (i == 1) { static char *vlan_mode_trunk = "trunk"; ovsrec_port_set_vlan_mode(port->cfg, vlan_mode_trunk); } ovsrec_port_set_trunks(port->cfg, trunks, i); /* Force reconfigure of the port. */ port_configure(port); } } static void bridge_aa_refresh_queued(struct bridge *br) { struct ovs_list *list = xmalloc(sizeof *list); struct bridge_aa_vlan *node, *next; list_init(list); ofproto_aa_vlan_get_queued(br->ofproto, list); LIST_FOR_EACH_SAFE (node, next, list_node, list) { struct port *port; VLOG_INFO("ifname=%s, vlan=%u, oper=%u", node->port_name, node->vlan, node->oper); port = port_lookup(br, node->port_name); if (port) { bridge_aa_update_trunks(port, node); } list_remove(&node->list_node); free(node->port_name); free(node); } free(list); } /* Port functions. */ static struct port * port_create(struct bridge *br, const struct ovsrec_port *cfg) { struct port *port; port = xzalloc(sizeof *port); port->bridge = br; port->name = xstrdup(cfg->name); port->cfg = cfg; list_init(&port->ifaces); hmap_insert(&br->ports, &port->hmap_node, hash_string(port->name, 0)); return port; } /* Deletes interfaces from 'port' that are no longer configured for it. */ static void port_del_ifaces(struct port *port) { struct iface *iface, *next; struct sset new_ifaces; size_t i; /* Collect list of new interfaces. */ sset_init(&new_ifaces); for (i = 0; i < port->cfg->n_interfaces; i++) { const char *name = port->cfg->interfaces[i]->name; const char *type = port->cfg->interfaces[i]->type; if (strcmp(type, "null")) { sset_add(&new_ifaces, name); } } /* Get rid of deleted interfaces. */ LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) { if (!sset_contains(&new_ifaces, iface->name)) { iface_destroy(iface); } } sset_destroy(&new_ifaces); } static void port_destroy(struct port *port) { if (port) { struct bridge *br = port->bridge; struct iface *iface, *next; if (br->ofproto) { ofproto_bundle_unregister(br->ofproto, port); } LIST_FOR_EACH_SAFE (iface, next, port_elem, &port->ifaces) { iface_destroy__(iface); } hmap_remove(&br->ports, &port->hmap_node); free(port->name); free(port); } } static struct port * port_lookup(const struct bridge *br, const char *name) { struct port *port; HMAP_FOR_EACH_WITH_HASH (port, hmap_node, hash_string(name, 0), &br->ports) { if (!strcmp(port->name, name)) { return port; } } return NULL; } static bool enable_lacp(struct port *port, bool *activep) { if (!port->cfg->lacp) { /* XXX when LACP implementation has been sufficiently tested, enable by * default and make active on bonded ports. */ return false; } else if (!strcmp(port->cfg->lacp, "off")) { return false; } else if (!strcmp(port->cfg->lacp, "active")) { *activep = true; return true; } else if (!strcmp(port->cfg->lacp, "passive")) { *activep = false; return true; } else { VLOG_WARN("port %s: unknown LACP mode %s", port->name, port->cfg->lacp); return false; } } static struct lacp_settings * port_configure_lacp(struct port *port, struct lacp_settings *s) { const char *lacp_time, *system_id; int priority; if (!enable_lacp(port, &s->active)) { return NULL; } s->name = port->name; system_id = smap_get(&port->cfg->other_config, "lacp-system-id"); if (system_id) { if (!ovs_scan(system_id, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(s->id))) { VLOG_WARN("port %s: LACP system ID (%s) must be an Ethernet" " address.", port->name, system_id); return NULL; } } else { s->id = port->bridge->ea; } if (eth_addr_is_zero(s->id)) { VLOG_WARN("port %s: Invalid zero LACP system ID.", port->name); return NULL; } /* Prefer bondable links if unspecified. */ priority = smap_get_int(&port->cfg->other_config, "lacp-system-priority", 0); s->priority = (priority > 0 && priority <= UINT16_MAX ? priority : UINT16_MAX - !list_is_short(&port->ifaces)); lacp_time = smap_get(&port->cfg->other_config, "lacp-time"); s->fast = lacp_time && !strcasecmp(lacp_time, "fast"); s->fallback_ab_cfg = smap_get_bool(&port->cfg->other_config, "lacp-fallback-ab", false); return s; } static void iface_configure_lacp(struct iface *iface, struct lacp_slave_settings *s) { int priority, portid, key; portid = smap_get_int(&iface->cfg->other_config, "lacp-port-id", 0); priority = smap_get_int(&iface->cfg->other_config, "lacp-port-priority", 0); key = smap_get_int(&iface->cfg->other_config, "lacp-aggregation-key", 0); if (portid <= 0 || portid > UINT16_MAX) { portid = ofp_to_u16(iface->ofp_port); } if (priority <= 0 || priority > UINT16_MAX) { priority = UINT16_MAX; } if (key < 0 || key > UINT16_MAX) { key = 0; } s->name = iface->name; s->id = portid; s->priority = priority; s->key = key; } static void port_configure_bond(struct port *port, struct bond_settings *s) { const char *detect_s; struct iface *iface; const char *mac_s; int miimon_interval; s->name = port->name; s->balance = BM_AB; if (port->cfg->bond_mode) { if (!bond_mode_from_string(&s->balance, port->cfg->bond_mode)) { VLOG_WARN("port %s: unknown bond_mode %s, defaulting to %s", port->name, port->cfg->bond_mode, bond_mode_to_string(s->balance)); } } else { static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 1); /* XXX: Post version 1.5.*, the default bond_mode changed from SLB to * active-backup. At some point we should remove this warning. */ VLOG_WARN_RL(&rl, "port %s: Using the default bond_mode %s. Note that" " in previous versions, the default bond_mode was" " balance-slb", port->name, bond_mode_to_string(s->balance)); } if (s->balance == BM_SLB && port->bridge->cfg->n_flood_vlans) { VLOG_WARN("port %s: SLB bonds are incompatible with flood_vlans, " "please use another bond type or disable flood_vlans", port->name); } miimon_interval = smap_get_int(&port->cfg->other_config, "bond-miimon-interval", 0); if (miimon_interval <= 0) { miimon_interval = 200; } detect_s = smap_get(&port->cfg->other_config, "bond-detect-mode"); if (!detect_s || !strcmp(detect_s, "carrier")) { miimon_interval = 0; } else if (strcmp(detect_s, "miimon")) { VLOG_WARN("port %s: unsupported bond-detect-mode %s, " "defaulting to carrier", port->name, detect_s); miimon_interval = 0; } s->up_delay = MAX(0, port->cfg->bond_updelay); s->down_delay = MAX(0, port->cfg->bond_downdelay); s->basis = smap_get_int(&port->cfg->other_config, "bond-hash-basis", 0); s->rebalance_interval = smap_get_int(&port->cfg->other_config, "bond-rebalance-interval", 10000); if (s->rebalance_interval && s->rebalance_interval < 1000) { s->rebalance_interval = 1000; } s->lacp_fallback_ab_cfg = smap_get_bool(&port->cfg->other_config, "lacp-fallback-ab", false); LIST_FOR_EACH (iface, port_elem, &port->ifaces) { netdev_set_miimon_interval(iface->netdev, miimon_interval); } mac_s = port->cfg->bond_active_slave; if (!mac_s || !ovs_scan(mac_s, ETH_ADDR_SCAN_FMT, ETH_ADDR_SCAN_ARGS(s->active_slave_mac))) { /* OVSDB did not store the last active interface */ s->active_slave_mac = eth_addr_zero; } } /* Returns true if 'port' is synthetic, that is, if we constructed it locally * instead of obtaining it from the database. */ static bool port_is_synthetic(const struct port *port) { return ovsdb_idl_row_is_synthetic(&port->cfg->header_); } /* Interface functions. */ static bool iface_is_internal(const struct ovsrec_interface *iface, const struct ovsrec_bridge *br) { /* The local port and "internal" ports are always "internal". */ return !strcmp(iface->type, "internal") || !strcmp(iface->name, br->name); } /* Returns the correct network device type for interface 'iface' in bridge * 'br'. */ static const char * iface_get_type(const struct ovsrec_interface *iface, const struct ovsrec_bridge *br) { const char *type; /* The local port always has type "internal". Other ports take * their type from the database and default to "system" if none is * specified. */ if (iface_is_internal(iface, br)) { type = "internal"; } else { type = iface->type[0] ? iface->type : "system"; } return ofproto_port_open_type(br->datapath_type, type); } static void iface_destroy__(struct iface *iface) { if (iface) { struct port *port = iface->port; struct bridge *br = port->bridge; if (br->ofproto && iface->ofp_port != OFPP_NONE) { ofproto_port_unregister(br->ofproto, iface->ofp_port); } if (iface->ofp_port != OFPP_NONE) { hmap_remove(&br->ifaces, &iface->ofp_port_node); } list_remove(&iface->port_elem); hmap_remove(&br->iface_by_name, &iface->name_node); /* The user is changing configuration here, so netdev_remove needs to be * used as opposed to netdev_close */ netdev_remove(iface->netdev); free(iface->name); free(iface); } } static void iface_destroy(struct iface *iface) { if (iface) { struct port *port = iface->port; iface_destroy__(iface); if (list_is_empty(&port->ifaces)) { port_destroy(port); } } } static struct iface * iface_lookup(const struct bridge *br, const char *name) { struct iface *iface; HMAP_FOR_EACH_WITH_HASH (iface, name_node, hash_string(name, 0), &br->iface_by_name) { if (!strcmp(iface->name, name)) { return iface; } } return NULL; } static struct iface * iface_find(const char *name) { const struct bridge *br; HMAP_FOR_EACH (br, node, &all_bridges) { struct iface *iface = iface_lookup(br, name); if (iface) { return iface; } } return NULL; } static struct iface * iface_from_ofp_port(const struct bridge *br, ofp_port_t ofp_port) { struct iface *iface; HMAP_FOR_EACH_IN_BUCKET (iface, ofp_port_node, hash_ofp_port(ofp_port), &br->ifaces) { if (iface->ofp_port == ofp_port) { return iface; } } return NULL; } /* Set Ethernet address of 'iface', if one is specified in the configuration * file. */ static void iface_set_mac(const struct bridge *br, const struct port *port, struct iface *iface) { struct eth_addr ea, *mac = NULL; struct iface *hw_addr_iface; if (strcmp(iface->type, "internal")) { return; } if (iface->cfg->mac && eth_addr_from_string(iface->cfg->mac, &ea)) { mac = &ea; } else if (port->cfg->fake_bridge) { /* Fake bridge and no MAC set in the configuration. Pick a local one. */ find_local_hw_addr(br, &ea, port, &hw_addr_iface); mac = &ea; } if (mac) { if (iface->ofp_port == OFPP_LOCAL) { VLOG_ERR("interface %s: ignoring mac in Interface record " "(use Bridge record to set local port's mac)", iface->name); } else if (eth_addr_is_multicast(*mac)) { VLOG_ERR("interface %s: cannot set MAC to multicast address", iface->name); } else { int error = netdev_set_etheraddr(iface->netdev, *mac); if (error) { VLOG_ERR("interface %s: setting MAC failed (%s)", iface->name, ovs_strerror(error)); } } } } /* Sets the ofport column of 'if_cfg' to 'ofport'. */ static void iface_set_ofport(const struct ovsrec_interface *if_cfg, ofp_port_t ofport) { if (if_cfg && !ovsdb_idl_row_is_synthetic(&if_cfg->header_)) { int64_t port = ofport == OFPP_NONE ? -1 : ofp_to_u16(ofport); ovsrec_interface_set_ofport(if_cfg, &port, 1); } } /* Clears all of the fields in 'if_cfg' that indicate interface status, and * sets the "ofport" field to -1. * * This is appropriate when 'if_cfg''s interface cannot be created or is * otherwise invalid. */ static void iface_clear_db_record(const struct ovsrec_interface *if_cfg, char *errp) { if (!ovsdb_idl_row_is_synthetic(&if_cfg->header_)) { iface_set_ofport(if_cfg, OFPP_NONE); ovsrec_interface_set_error(if_cfg, errp); ovsrec_interface_set_status(if_cfg, NULL); ovsrec_interface_set_admin_state(if_cfg, NULL); ovsrec_interface_set_duplex(if_cfg, NULL); ovsrec_interface_set_link_speed(if_cfg, NULL, 0); ovsrec_interface_set_link_state(if_cfg, NULL); ovsrec_interface_set_mac_in_use(if_cfg, NULL); ovsrec_interface_set_mtu(if_cfg, NULL, 0); ovsrec_interface_set_cfm_fault(if_cfg, NULL, 0); ovsrec_interface_set_cfm_fault_status(if_cfg, NULL, 0); ovsrec_interface_set_cfm_remote_mpids(if_cfg, NULL, 0); ovsrec_interface_set_lacp_current(if_cfg, NULL, 0); ovsrec_interface_set_statistics(if_cfg, NULL, NULL, 0); ovsrec_interface_set_ifindex(if_cfg, NULL, 0); } } static bool queue_ids_include(const struct ovsdb_datum *queues, int64_t target) { union ovsdb_atom atom; atom.integer = target; return ovsdb_datum_find_key(queues, &atom, OVSDB_TYPE_INTEGER) != UINT_MAX; } static void iface_configure_qos(struct iface *iface, const struct ovsrec_qos *qos) { struct ofpbuf queues_buf; ofpbuf_init(&queues_buf, 0); if (!qos || qos->type[0] == '\0') { netdev_set_qos(iface->netdev, NULL, NULL); } else { const struct ovsdb_datum *queues; struct netdev_queue_dump dump; unsigned int queue_id; struct smap details; bool queue_zero; size_t i; /* Configure top-level Qos for 'iface'. */ netdev_set_qos(iface->netdev, qos->type, &qos->other_config); /* Deconfigure queues that were deleted. */ queues = ovsrec_qos_get_queues(qos, OVSDB_TYPE_INTEGER, OVSDB_TYPE_UUID); smap_init(&details); NETDEV_QUEUE_FOR_EACH (&queue_id, &details, &dump, iface->netdev) { if (!queue_ids_include(queues, queue_id)) { netdev_delete_queue(iface->netdev, queue_id); } } smap_destroy(&details); /* Configure queues for 'iface'. */ queue_zero = false; for (i = 0; i < qos->n_queues; i++) { const struct ovsrec_queue *queue = qos->value_queues[i]; unsigned int queue_id = qos->key_queues[i]; if (queue_id == 0) { queue_zero = true; } if (queue->n_dscp == 1) { struct ofproto_port_queue *port_queue; port_queue = ofpbuf_put_uninit(&queues_buf, sizeof *port_queue); port_queue->queue = queue_id; port_queue->dscp = queue->dscp[0]; } netdev_set_queue(iface->netdev, queue_id, &queue->other_config); } if (!queue_zero) { struct smap details; smap_init(&details); netdev_set_queue(iface->netdev, 0, &details); smap_destroy(&details); } } if (iface->ofp_port != OFPP_NONE) { const struct ofproto_port_queue *port_queues = queues_buf.data; size_t n_queues = queues_buf.size / sizeof *port_queues; ofproto_port_set_queues(iface->port->bridge->ofproto, iface->ofp_port, port_queues, n_queues); } netdev_set_policing(iface->netdev, MIN(UINT32_MAX, iface->cfg->ingress_policing_rate), MIN(UINT32_MAX, iface->cfg->ingress_policing_burst)); ofpbuf_uninit(&queues_buf); } static void iface_configure_cfm(struct iface *iface) { const struct ovsrec_interface *cfg = iface->cfg; const char *opstate_str; const char *cfm_ccm_vlan; struct cfm_settings s; struct smap netdev_args; if (!cfg->n_cfm_mpid) { ofproto_port_clear_cfm(iface->port->bridge->ofproto, iface->ofp_port); return; } s.check_tnl_key = false; smap_init(&netdev_args); if (!netdev_get_config(iface->netdev, &netdev_args)) { const char *key = smap_get(&netdev_args, "key"); const char *in_key = smap_get(&netdev_args, "in_key"); s.check_tnl_key = (key && !strcmp(key, "flow")) || (in_key && !strcmp(in_key, "flow")); } smap_destroy(&netdev_args); s.mpid = *cfg->cfm_mpid; s.interval = smap_get_int(&iface->cfg->other_config, "cfm_interval", 0); cfm_ccm_vlan = smap_get(&iface->cfg->other_config, "cfm_ccm_vlan"); s.ccm_pcp = smap_get_int(&iface->cfg->other_config, "cfm_ccm_pcp", 0); if (s.interval <= 0) { s.interval = 1000; } if (!cfm_ccm_vlan) { s.ccm_vlan = 0; } else if (!strcasecmp("random", cfm_ccm_vlan)) { s.ccm_vlan = CFM_RANDOM_VLAN; } else { s.ccm_vlan = atoi(cfm_ccm_vlan); if (s.ccm_vlan == CFM_RANDOM_VLAN) { s.ccm_vlan = 0; } } s.extended = smap_get_bool(&iface->cfg->other_config, "cfm_extended", false); s.demand = smap_get_bool(&iface->cfg->other_config, "cfm_demand", false); opstate_str = smap_get(&iface->cfg->other_config, "cfm_opstate"); s.opup = !opstate_str || !strcasecmp("up", opstate_str); ofproto_port_set_cfm(iface->port->bridge->ofproto, iface->ofp_port, &s); } /* Returns true if 'iface' is synthetic, that is, if we constructed it locally * instead of obtaining it from the database. */ static bool iface_is_synthetic(const struct iface *iface) { return ovsdb_idl_row_is_synthetic(&iface->cfg->header_); } static ofp_port_t iface_validate_ofport__(size_t n, int64_t *ofport) { return (n && *ofport >= 1 && *ofport < ofp_to_u16(OFPP_MAX) ? u16_to_ofp(*ofport) : OFPP_NONE); } static ofp_port_t iface_get_requested_ofp_port(const struct ovsrec_interface *cfg) { return iface_validate_ofport__(cfg->n_ofport_request, cfg->ofport_request); } static ofp_port_t iface_pick_ofport(const struct ovsrec_interface *cfg) { ofp_port_t requested_ofport = iface_get_requested_ofp_port(cfg); return (requested_ofport != OFPP_NONE ? requested_ofport : iface_validate_ofport__(cfg->n_ofport, cfg->ofport)); } /* Port mirroring. */ static struct mirror * mirror_find_by_uuid(struct bridge *br, const struct uuid *uuid) { struct mirror *m; HMAP_FOR_EACH_IN_BUCKET (m, hmap_node, uuid_hash(uuid), &br->mirrors) { if (uuid_equals(uuid, &m->uuid)) { return m; } } return NULL; } static void bridge_configure_mirrors(struct bridge *br) { const struct ovsdb_datum *mc; unsigned long *flood_vlans; struct mirror *m, *next; size_t i; /* Get rid of deleted mirrors. */ mc = ovsrec_bridge_get_mirrors(br->cfg, OVSDB_TYPE_UUID); HMAP_FOR_EACH_SAFE (m, next, hmap_node, &br->mirrors) { union ovsdb_atom atom; atom.uuid = m->uuid; if (ovsdb_datum_find_key(mc, &atom, OVSDB_TYPE_UUID) == UINT_MAX) { mirror_destroy(m); } } /* Add new mirrors and reconfigure existing ones. */ for (i = 0; i < br->cfg->n_mirrors; i++) { const struct ovsrec_mirror *cfg = br->cfg->mirrors[i]; struct mirror *m = mirror_find_by_uuid(br, &cfg->header_.uuid); if (!m) { m = mirror_create(br, cfg); } m->cfg = cfg; if (!mirror_configure(m)) { mirror_destroy(m); } } /* Update flooded vlans (for RSPAN). */ flood_vlans = vlan_bitmap_from_array(br->cfg->flood_vlans, br->cfg->n_flood_vlans); ofproto_set_flood_vlans(br->ofproto, flood_vlans); bitmap_free(flood_vlans); } static struct mirror * mirror_create(struct bridge *br, const struct ovsrec_mirror *cfg) { struct mirror *m; m = xzalloc(sizeof *m); m->uuid = cfg->header_.uuid; hmap_insert(&br->mirrors, &m->hmap_node, uuid_hash(&m->uuid)); m->bridge = br; m->name = xstrdup(cfg->name); return m; } static void mirror_destroy(struct mirror *m) { if (m) { struct bridge *br = m->bridge; if (br->ofproto) { ofproto_mirror_unregister(br->ofproto, m); } hmap_remove(&br->mirrors, &m->hmap_node); free(m->name); free(m); } } static void mirror_collect_ports(struct mirror *m, struct ovsrec_port **in_ports, int n_in_ports, void ***out_portsp, size_t *n_out_portsp) { void **out_ports = xmalloc(n_in_ports * sizeof *out_ports); size_t n_out_ports = 0; size_t i; for (i = 0; i < n_in_ports; i++) { const char *name = in_ports[i]->name; struct port *port = port_lookup(m->bridge, name); if (port) { out_ports[n_out_ports++] = port; } else { VLOG_WARN("bridge %s: mirror %s cannot match on nonexistent " "port %s", m->bridge->name, m->name, name); } } *out_portsp = out_ports; *n_out_portsp = n_out_ports; } static bool mirror_configure(struct mirror *m) { const struct ovsrec_mirror *cfg = m->cfg; struct ofproto_mirror_settings s; /* Set name. */ if (strcmp(cfg->name, m->name)) { free(m->name); m->name = xstrdup(cfg->name); } s.name = m->name; /* Get output port or VLAN. */ if (cfg->output_port) { s.out_bundle = port_lookup(m->bridge, cfg->output_port->name); if (!s.out_bundle) { VLOG_ERR("bridge %s: mirror %s outputs to port not on bridge", m->bridge->name, m->name); return false; } s.out_vlan = UINT16_MAX; if (cfg->output_vlan) { VLOG_ERR("bridge %s: mirror %s specifies both output port and " "output vlan; ignoring output vlan", m->bridge->name, m->name); } } else if (cfg->output_vlan) { /* The database should prevent invalid VLAN values. */ s.out_bundle = NULL; s.out_vlan = *cfg->output_vlan; } else { VLOG_ERR("bridge %s: mirror %s does not specify output; ignoring", m->bridge->name, m->name); return false; } /* Get port selection. */ if (cfg->select_all) { size_t n_ports = hmap_count(&m->bridge->ports); void **ports = xmalloc(n_ports * sizeof *ports); struct port *port; size_t i; i = 0; HMAP_FOR_EACH (port, hmap_node, &m->bridge->ports) { ports[i++] = port; } s.srcs = ports; s.n_srcs = n_ports; s.dsts = ports; s.n_dsts = n_ports; } else { /* Get ports, dropping ports that don't exist. * The IDL ensures that there are no duplicates. */ mirror_collect_ports(m, cfg->select_src_port, cfg->n_select_src_port, &s.srcs, &s.n_srcs); mirror_collect_ports(m, cfg->select_dst_port, cfg->n_select_dst_port, &s.dsts, &s.n_dsts); } /* Get VLAN selection. */ s.src_vlans = vlan_bitmap_from_array(cfg->select_vlan, cfg->n_select_vlan); /* Configure. */ ofproto_mirror_register(m->bridge->ofproto, m, &s); /* Clean up. */ if (s.srcs != s.dsts) { free(s.dsts); } free(s.srcs); free(s.src_vlans); return true; } /* Linux VLAN device support (e.g. "eth0.10" for VLAN 10.) * * This is deprecated. It is only for compatibility with broken device drivers * in old versions of Linux that do not properly support VLANs when VLAN * devices are not used. When broken device drivers are no longer in * widespread use, we will delete these interfaces. */ static struct ovsrec_port **recs; static size_t n_recs, allocated_recs; /* Adds 'rec' to a list of recs that have to be destroyed when the VLAN * splinters are reconfigured. */ static void register_rec(struct ovsrec_port *rec) { if (n_recs >= allocated_recs) { recs = x2nrealloc(recs, &allocated_recs, sizeof *recs); } recs[n_recs++] = rec; } /* Frees all of the ports registered with register_reg(). */ static void free_registered_recs(void) { size_t i; for (i = 0; i < n_recs; i++) { struct ovsrec_port *port = recs[i]; size_t j; for (j = 0; j < port->n_interfaces; j++) { struct ovsrec_interface *iface = port->interfaces[j]; free(iface->name); free(iface); } smap_destroy(&port->other_config); free(port->interfaces); free(port->name); free(port->tag); free(port); } n_recs = 0; } /* Returns true if VLAN splinters are enabled on 'iface_cfg', false * otherwise. */ static bool vlan_splinters_is_enabled(const struct ovsrec_interface *iface_cfg) { return smap_get_bool(&iface_cfg->other_config, "enable-vlan-splinters", false); } /* Figures out the set of VLANs that are in use for the purpose of VLAN * splinters. * * If VLAN splinters are enabled on at least one interface and any VLANs are in * use, returns a 4096-bit bitmap with a 1-bit for each in-use VLAN (bits 0 and * 4095 will not be set). The caller is responsible for freeing the bitmap, * with free(). * * If VLANs splinters are not enabled on any interface or if no VLANs are in * use, returns NULL. * * Updates 'vlan_splinters_enabled_anywhere'. */ static unsigned long int * collect_splinter_vlans(const struct ovsrec_open_vswitch *ovs_cfg) { unsigned long int *splinter_vlans; struct sset splinter_ifaces; const char *real_dev_name; struct shash *real_devs; struct shash_node *node; struct bridge *br; size_t i; /* Free space allocated for synthesized ports and interfaces, since we're * in the process of reconstructing all of them. */ free_registered_recs(); splinter_vlans = bitmap_allocate(4096); sset_init(&splinter_ifaces); vlan_splinters_enabled_anywhere = false; for (i = 0; i < ovs_cfg->n_bridges; i++) { struct ovsrec_bridge *br_cfg = ovs_cfg->bridges[i]; size_t j; for (j = 0; j < br_cfg->n_ports; j++) { struct ovsrec_port *port_cfg = br_cfg->ports[j]; int k; for (k = 0; k < port_cfg->n_interfaces; k++) { struct ovsrec_interface *iface_cfg = port_cfg->interfaces[k]; if (vlan_splinters_is_enabled(iface_cfg)) { vlan_splinters_enabled_anywhere = true; sset_add(&splinter_ifaces, iface_cfg->name); vlan_bitmap_from_array__(port_cfg->trunks, port_cfg->n_trunks, splinter_vlans); } } if (port_cfg->tag && *port_cfg->tag > 0 && *port_cfg->tag < 4095) { bitmap_set1(splinter_vlans, *port_cfg->tag); } } } if (!vlan_splinters_enabled_anywhere) { free(splinter_vlans); sset_destroy(&splinter_ifaces); return NULL; } HMAP_FOR_EACH (br, node, &all_bridges) { if (br->ofproto) { ofproto_get_vlan_usage(br->ofproto, splinter_vlans); } } /* Don't allow VLANs 0 or 4095 to be splintered. VLAN 0 should appear on * the real device. VLAN 4095 is reserved and Linux doesn't allow a VLAN * device to be created for it. */ bitmap_set0(splinter_vlans, 0); bitmap_set0(splinter_vlans, 4095); /* Delete all VLAN devices that we don't need. */ vlandev_refresh(); real_devs = vlandev_get_real_devs(); SHASH_FOR_EACH (node, real_devs) { const struct vlan_real_dev *real_dev = node->data; const struct vlan_dev *vlan_dev; bool real_dev_has_splinters; real_dev_has_splinters = sset_contains(&splinter_ifaces, real_dev->name); HMAP_FOR_EACH (vlan_dev, hmap_node, &real_dev->vlan_devs) { if (!real_dev_has_splinters || !bitmap_is_set(splinter_vlans, vlan_dev->vid)) { struct netdev *netdev; if (!netdev_open(vlan_dev->name, "system", &netdev)) { if (!netdev_get_in4(netdev, NULL, NULL) || !netdev_get_in6(netdev, NULL)) { /* It has an IP address configured, so we don't own * it. Don't delete it. */ } else { vlandev_del(vlan_dev->name); } netdev_close(netdev); } } } } /* Add all VLAN devices that we need. */ SSET_FOR_EACH (real_dev_name, &splinter_ifaces) { int vid; BITMAP_FOR_EACH_1 (vid, 4096, splinter_vlans) { if (!vlandev_get_name(real_dev_name, vid)) { vlandev_add(real_dev_name, vid); } } } vlandev_refresh(); sset_destroy(&splinter_ifaces); if (bitmap_scan(splinter_vlans, 1, 0, 4096) >= 4096) { free(splinter_vlans); return NULL; } return splinter_vlans; } /* Pushes the configure of VLAN splinter port 'port' (e.g. eth0.9) down to * ofproto. */ static void configure_splinter_port(struct port *port) { struct ofproto *ofproto = port->bridge->ofproto; ofp_port_t realdev_ofp_port; const char *realdev_name; struct iface *vlandev, *realdev; ofproto_bundle_unregister(port->bridge->ofproto, port); vlandev = CONTAINER_OF(list_front(&port->ifaces), struct iface, port_elem); realdev_name = smap_get(&port->cfg->other_config, "realdev"); realdev = iface_lookup(port->bridge, realdev_name); realdev_ofp_port = realdev ? realdev->ofp_port : 0; ofproto_port_set_realdev(ofproto, vlandev->ofp_port, realdev_ofp_port, *port->cfg->tag); } static struct ovsrec_port * synthesize_splinter_port(const char *real_dev_name, const char *vlan_dev_name, int vid) { struct ovsrec_interface *iface; struct ovsrec_port *port; iface = xmalloc(sizeof *iface); ovsrec_interface_init(iface); iface->name = xstrdup(vlan_dev_name); iface->type = "system"; port = xmalloc(sizeof *port); ovsrec_port_init(port); port->interfaces = xmemdup(&iface, sizeof iface); port->n_interfaces = 1; port->name = xstrdup(vlan_dev_name); port->vlan_mode = "splinter"; port->tag = xmalloc(sizeof *port->tag); *port->tag = vid; smap_add(&port->other_config, "realdev", real_dev_name); register_rec(port); return port; } /* For each interface with 'br' that has VLAN splinters enabled, adds a * corresponding ovsrec_port to 'ports' for each splinter VLAN marked with a * 1-bit in the 'splinter_vlans' bitmap. */ static void add_vlan_splinter_ports(struct bridge *br, const unsigned long int *splinter_vlans, struct shash *ports) { size_t i; /* We iterate through 'br->cfg->ports' instead of 'ports' here because * we're modifying 'ports'. */ for (i = 0; i < br->cfg->n_ports; i++) { const char *name = br->cfg->ports[i]->name; struct ovsrec_port *port_cfg = shash_find_data(ports, name); size_t j; for (j = 0; j < port_cfg->n_interfaces; j++) { struct ovsrec_interface *iface_cfg = port_cfg->interfaces[j]; if (vlan_splinters_is_enabled(iface_cfg)) { const char *real_dev_name; uint16_t vid; real_dev_name = iface_cfg->name; BITMAP_FOR_EACH_1 (vid, 4096, splinter_vlans) { const char *vlan_dev_name; vlan_dev_name = vlandev_get_name(real_dev_name, vid); if (vlan_dev_name && !shash_find(ports, vlan_dev_name)) { shash_add(ports, vlan_dev_name, synthesize_splinter_port( real_dev_name, vlan_dev_name, vid)); } } } } } } static void mirror_refresh_stats(struct mirror *m) { struct ofproto *ofproto = m->bridge->ofproto; uint64_t tx_packets, tx_bytes; const char *keys[2]; int64_t values[2]; size_t stat_cnt = 0; if (ofproto_mirror_get_stats(ofproto, m, &tx_packets, &tx_bytes)) { ovsrec_mirror_set_statistics(m->cfg, NULL, NULL, 0); return; } if (tx_packets != UINT64_MAX) { keys[stat_cnt] = "tx_packets"; values[stat_cnt] = tx_packets; stat_cnt++; } if (tx_bytes != UINT64_MAX) { keys[stat_cnt] = "tx_bytes"; values[stat_cnt] = tx_bytes; stat_cnt++; } ovsrec_mirror_set_statistics(m->cfg, keys, values, stat_cnt); } /* * Add registered netdev and dpif types to ovsdb to allow external * applications to query the capabilities of the Open vSwitch instance * running on the node. */ static void discover_types(const struct ovsrec_open_vswitch *cfg) { struct sset types; /* Datapath types. */ sset_init(&types); dp_enumerate_types(&types); const char **datapath_types = sset_array(&types); ovsrec_open_vswitch_set_datapath_types(cfg, datapath_types, sset_count(&types)); free(datapath_types); sset_destroy(&types); /* Port types. */ sset_init(&types); netdev_enumerate_types(&types); const char **iface_types = sset_array(&types); ovsrec_open_vswitch_set_iface_types(cfg, iface_types, sset_count(&types)); free(iface_types); sset_destroy(&types); } openvswitch-2.5.0/vswitchd/PaxHeaders.69223/ovs-vswitchd.c0000644000000000000000000000013112631676263020303 xustar0030 mtime=1449622707.594461255 30 atime=1456592664.478974287 29 ctime=1456594661.10532716 openvswitch-2.5.0/vswitchd/ovs-vswitchd.c0000664000175000017500000001665212631676263022006 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include #ifdef HAVE_MLOCKALL #include #endif #include "bridge.h" #include "command-line.h" #include "compiler.h" #include "daemon.h" #include "dirs.h" #include "dpif.h" #include "dummy.h" #include "fatal-signal.h" #include "memory.h" #include "netdev.h" #include "openflow/openflow.h" #include "ovsdb-idl.h" #include "poll-loop.h" #include "simap.h" #include "stream-ssl.h" #include "stream.h" #include "svec.h" #include "timeval.h" #include "unixctl.h" #include "util.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" #include "lib/vswitch-idl.h" #include "lib/netdev-dpdk.h" VLOG_DEFINE_THIS_MODULE(vswitchd); /* --mlockall: If set, locks all process memory into physical RAM, preventing * the kernel from paging any of its memory to disk. */ static bool want_mlockall; static unixctl_cb_func ovs_vswitchd_exit; static char *parse_options(int argc, char *argv[], char **unixctl_path); OVS_NO_RETURN static void usage(void); int main(int argc, char *argv[]) { char *unixctl_path = NULL; struct unixctl_server *unixctl; char *remote; bool exiting; int retval; set_program_name(argv[0]); retval = dpdk_init(argc,argv); if (retval < 0) { return retval; } argc -= retval; argv += retval; ovs_cmdl_proctitle_init(argc, argv); service_start(&argc, &argv); remote = parse_options(argc, argv, &unixctl_path); fatal_ignore_sigpipe(); ovsrec_init(); daemonize_start(true); if (want_mlockall) { #ifdef HAVE_MLOCKALL if (mlockall(MCL_CURRENT | MCL_FUTURE)) { VLOG_ERR("mlockall failed: %s", ovs_strerror(errno)); } #else VLOG_ERR("mlockall not supported on this system"); #endif } retval = unixctl_server_create(unixctl_path, &unixctl); if (retval) { exit(EXIT_FAILURE); } unixctl_command_register("exit", "", 0, 0, ovs_vswitchd_exit, &exiting); bridge_init(remote); free(remote); exiting = false; while (!exiting) { memory_run(); if (memory_should_report()) { struct simap usage; simap_init(&usage); bridge_get_memory_usage(&usage); memory_report(&usage); simap_destroy(&usage); } bridge_run(); unixctl_server_run(unixctl); netdev_run(); memory_wait(); bridge_wait(); unixctl_server_wait(unixctl); netdev_wait(); if (exiting) { poll_immediate_wake(); } poll_block(); if (should_service_stop()) { exiting = true; } } bridge_exit(); unixctl_server_destroy(unixctl); service_stop(); return 0; } static char * parse_options(int argc, char *argv[], char **unixctl_pathp) { enum { OPT_PEER_CA_CERT = UCHAR_MAX + 1, OPT_MLOCKALL, OPT_UNIXCTL, VLOG_OPTION_ENUMS, OPT_BOOTSTRAP_CA_CERT, OPT_ENABLE_DUMMY, OPT_DISABLE_SYSTEM, DAEMON_OPTION_ENUMS, OPT_DPDK, }; static const struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"version", no_argument, NULL, 'V'}, {"mlockall", no_argument, NULL, OPT_MLOCKALL}, {"unixctl", required_argument, NULL, OPT_UNIXCTL}, DAEMON_LONG_OPTIONS, VLOG_LONG_OPTIONS, STREAM_SSL_LONG_OPTIONS, {"peer-ca-cert", required_argument, NULL, OPT_PEER_CA_CERT}, {"bootstrap-ca-cert", required_argument, NULL, OPT_BOOTSTRAP_CA_CERT}, {"enable-dummy", optional_argument, NULL, OPT_ENABLE_DUMMY}, {"disable-system", no_argument, NULL, OPT_DISABLE_SYSTEM}, {"dpdk", required_argument, NULL, OPT_DPDK}, {NULL, 0, NULL, 0}, }; char *short_options = ovs_cmdl_long_options_to_short_options(long_options); for (;;) { int c; c = getopt_long(argc, argv, short_options, long_options, NULL); if (c == -1) { break; } switch (c) { case 'h': usage(); case 'V': ovs_print_version(0, 0); exit(EXIT_SUCCESS); case OPT_MLOCKALL: want_mlockall = true; break; case OPT_UNIXCTL: *unixctl_pathp = optarg; break; VLOG_OPTION_HANDLERS DAEMON_OPTION_HANDLERS STREAM_SSL_OPTION_HANDLERS case OPT_PEER_CA_CERT: stream_ssl_set_peer_ca_cert_file(optarg); break; case OPT_BOOTSTRAP_CA_CERT: stream_ssl_set_ca_cert_file(optarg, true); break; case OPT_ENABLE_DUMMY: dummy_enable(optarg); break; case OPT_DISABLE_SYSTEM: dp_blacklist_provider("system"); break; case '?': exit(EXIT_FAILURE); case OPT_DPDK: ovs_fatal(0, "--dpdk must be given at beginning of command line."); break; default: abort(); } } free(short_options); argc -= optind; argv += optind; switch (argc) { case 0: return xasprintf("unix:%s/db.sock", ovs_rundir()); case 1: return xstrdup(argv[0]); default: VLOG_FATAL("at most one non-option argument accepted; " "use --help for usage"); } } static void usage(void) { printf("%s: Open vSwitch daemon\n" "usage: %s [OPTIONS] [DATABASE]\n" "where DATABASE is a socket on which ovsdb-server is listening\n" " (default: \"unix:%s/db.sock\").\n", program_name, program_name, ovs_rundir()); stream_usage("DATABASE", true, false, true); daemon_usage(); vlog_usage(); printf("\nDPDK options:\n" " --dpdk [VHOST] [DPDK] Initialize DPDK datapath.\n" " where DPDK are options for initializing DPDK lib and VHOST is\n" #ifdef VHOST_CUSE " option to override default character device name used for\n" " for use with userspace vHost\n" " -cuse_dev_name NAME\n" #else " option to override default directory where vhost-user\n" " sockets are created.\n" " -vhost_sock_dir DIR\n" #endif ); printf("\nOther options:\n" " --unixctl=SOCKET override default control socket name\n" " -h, --help display this help message\n" " -V, --version display version information\n"); exit(EXIT_SUCCESS); } static void ovs_vswitchd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED, const char *argv[] OVS_UNUSED, void *exiting_) { bool *exiting = exiting_; *exiting = true; unixctl_command_reply(conn, NULL); } openvswitch-2.5.0/vswitchd/PaxHeaders.69223/vswitch.ovsschema0000644000000000000000000000013212631676263021101 xustar0030 mtime=1449622707.594461255 30 atime=1456592573.507243433 30 ctime=1456594660.029281925 openvswitch-2.5.0/vswitchd/vswitch.ovsschema0000664000175000017500000005404512631676263022601 0ustar00jpettitjpettit00000000000000{"name": "Open_vSwitch", "version": "7.12.1", "cksum": "2211824403 22535", "tables": { "Open_vSwitch": { "columns": { "bridges": { "type": {"key": {"type": "uuid", "refTable": "Bridge"}, "min": 0, "max": "unlimited"}}, "manager_options": { "type": {"key": {"type": "uuid", "refTable": "Manager"}, "min": 0, "max": "unlimited"}}, "ssl": { "type": {"key": {"type": "uuid", "refTable": "SSL"}, "min": 0, "max": 1}}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "next_cfg": { "type": "integer"}, "cur_cfg": { "type": "integer"}, "statistics": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, "ovs_version": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "db_version": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "system_type": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "system_version": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "datapath_types": { "type": {"key": {"type": "string"}, "min": 0, "max": "unlimited"}}, "iface_types": { "type": {"key": {"type": "string"}, "min": 0, "max": "unlimited"}}}, "isRoot": true, "maxRows": 1}, "Bridge": { "columns": { "name": { "type": "string", "mutable": false}, "datapath_type": { "type": "string"}, "datapath_version": { "type": "string"}, "datapath_id": { "type": {"key": "string", "min": 0, "max": 1}, "ephemeral": true}, "stp_enable": { "type": "boolean"}, "rstp_enable": { "type": "boolean"}, "mcast_snooping_enable": { "type": "boolean"}, "ports": { "type": {"key": {"type": "uuid", "refTable": "Port"}, "min": 0, "max": "unlimited"}}, "mirrors": { "type": {"key": {"type": "uuid", "refTable": "Mirror"}, "min": 0, "max": "unlimited"}}, "netflow": { "type": {"key": {"type": "uuid", "refTable": "NetFlow"}, "min": 0, "max": 1}}, "sflow": { "type": {"key": {"type": "uuid", "refTable": "sFlow"}, "min": 0, "max": 1}}, "ipfix": { "type": {"key": {"type": "uuid", "refTable": "IPFIX"}, "min": 0, "max": 1}}, "controller": { "type": {"key": {"type": "uuid", "refTable": "Controller"}, "min": 0, "max": "unlimited"}}, "protocols": { "type": {"key": {"type": "string", "enum": ["set", ["OpenFlow10", "OpenFlow11", "OpenFlow12", "OpenFlow13", "OpenFlow14", "OpenFlow15"]]}, "min": 0, "max": "unlimited"}}, "fail_mode": { "type": {"key": {"type": "string", "enum": ["set", ["standalone", "secure"]]}, "min": 0, "max": 1}}, "status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, "rstp_status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "flood_vlans": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4095}, "min": 0, "max": 4096}}, "flow_tables": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 254}, "value": {"type": "uuid", "refTable": "Flow_Table"}, "min": 0, "max": "unlimited"}}, "auto_attach": { "type": {"key": {"type": "uuid", "refTable": "AutoAttach"}, "min": 0, "max": 1}}}, "indexes": [["name"]]}, "Port": { "columns": { "name": { "type": "string", "mutable": false}, "interfaces": { "type": {"key": {"type": "uuid", "refTable": "Interface"}, "min": 1, "max": "unlimited"}}, "trunks": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4095}, "min": 0, "max": 4096}}, "tag": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4095}, "min": 0, "max": 1}}, "vlan_mode": { "type": {"key": {"type": "string", "enum": ["set", ["trunk", "access", "native-tagged", "native-untagged"]]}, "min": 0, "max": 1}}, "qos": { "type": {"key": {"type": "uuid", "refTable": "QoS"}, "min": 0, "max": 1}}, "mac": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "bond_mode": { "type": {"key": {"type": "string", "enum": ["set", ["balance-tcp", "balance-slb", "active-backup"]]}, "min": 0, "max": 1}}, "lacp": { "type": {"key": {"type": "string", "enum": ["set", ["active", "passive", "off"]]}, "min": 0, "max": 1}}, "bond_updelay": { "type": "integer"}, "bond_downdelay": { "type": "integer"}, "bond_active_slave": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "bond_fake_iface": { "type": "boolean"}, "fake_bridge": { "type": "boolean"}, "status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, "rstp_status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, "rstp_statistics": { "type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}, "ephemeral": true}, "statistics": { "type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}, "ephemeral": true}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "indexes": [["name"]]}, "Interface": { "columns": { "name": { "type": "string", "mutable": false}, "type": { "type": "string"}, "options": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "ingress_policing_rate": { "type": {"key": {"type": "integer", "minInteger": 0}}}, "ingress_policing_burst": { "type": {"key": {"type": "integer", "minInteger": 0}}}, "mac_in_use": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}, "ephemeral": true}, "mac": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "ifindex": { "type": { "key": {"type": "integer", "minInteger": 0, "maxInteger": 4294967295}, "min": 0, "max": 1}, "ephemeral": true}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "ofport": { "type": {"key": "integer", "min": 0, "max": 1}}, "ofport_request": { "type": { "key": {"type": "integer", "minInteger": 1, "maxInteger": 65279}, "min": 0, "max": 1}}, "bfd": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "bfd_status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "cfm_mpid": { "type": { "key": {"type": "integer"}, "min": 0, "max": 1}}, "cfm_remote_mpids": { "type": { "key": {"type": "integer"}, "min": 0, "max": "unlimited"}, "ephemeral": true}, "cfm_flap_count": { "type": { "key": {"type": "integer"}, "min": 0, "max": 1}}, "cfm_fault": { "type": { "key": { "type": "boolean"}, "min": 0, "max": 1}, "ephemeral": true}, "cfm_fault_status": { "type": { "key": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, "cfm_remote_opstate": { "type": {"key": {"type": "string", "enum": ["set", ["up", "down"]]}, "min": 0, "max": 1}, "ephemeral": true}, "cfm_health": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 100}, "min": 0, "max": 1}, "ephemeral": true}, "lacp_current": { "type": {"key": {"type": "boolean"}, "min": 0, "max": 1}, "ephemeral": true}, "lldp": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "statistics": { "type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}, "ephemeral": true}, "status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}, "admin_state": { "type": {"key": {"type": "string", "enum": ["set", ["up", "down"]]}, "min": 0, "max": 1}, "ephemeral": true}, "link_state": { "type": {"key": {"type": "string", "enum": ["set", ["up", "down"]]}, "min": 0, "max": 1}, "ephemeral": true}, "link_resets": { "type": {"key": {"type": "integer"}, "min": 0, "max": 1}, "ephemeral": true}, "link_speed": { "type": {"key": "integer", "min": 0, "max": 1}, "ephemeral": true}, "duplex": { "type": {"key": {"type": "string", "enum": ["set", ["half", "full"]]}, "min": 0, "max": 1}, "ephemeral": true}, "mtu": { "type": {"key": "integer", "min": 0, "max": 1}, "ephemeral": true}, "error": { "type": {"key": "string", "min": 0, "max": 1}}}, "indexes": [["name"]]}, "Flow_Table": { "columns": { "name": { "type": {"key": "string", "min": 0, "max": 1}}, "flow_limit": { "type": {"key": {"type": "integer", "minInteger": 0}, "min": 0, "max": 1}}, "overflow_policy": { "type": {"key": {"type": "string", "enum": ["set", ["refuse", "evict"]]}, "min": 0, "max": 1}}, "groups": { "type": {"key": "string", "min": 0, "max": "unlimited"}}, "prefixes": { "type": {"key": "string", "min": 0, "max": 3}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}}, "QoS": { "columns": { "type": { "type": "string"}, "queues": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4294967295}, "value": {"type": "uuid", "refTable": "Queue"}, "min": 0, "max": "unlimited"}}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "isRoot": true}, "Queue": { "columns": { "dscp": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 63}, "min": 0, "max": 1}}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "isRoot": true}, "Mirror": { "columns": { "name": { "type": "string"}, "select_all": { "type": "boolean"}, "select_src_port": { "type": {"key": {"type": "uuid", "refTable": "Port", "refType": "weak"}, "min": 0, "max": "unlimited"}}, "select_dst_port": { "type": {"key": {"type": "uuid", "refTable": "Port", "refType": "weak"}, "min": 0, "max": "unlimited"}}, "select_vlan": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4095}, "min": 0, "max": 4096}}, "output_port": { "type": {"key": {"type": "uuid", "refTable": "Port", "refType": "weak"}, "min": 0, "max": 1}}, "output_vlan": { "type": {"key": {"type": "integer", "minInteger": 1, "maxInteger": 4095}, "min": 0, "max": 1}}, "statistics": { "type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}, "ephemeral": true}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}}, "NetFlow": { "columns": { "targets": { "type": {"key": {"type": "string"}, "min": 1, "max": "unlimited"}}, "engine_type": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 255}, "min": 0, "max": 1}}, "engine_id": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 255}, "min": 0, "max": 1}}, "add_id_to_interface": { "type": "boolean"}, "active_timeout": { "type": {"key": {"type": "integer", "minInteger": -1}}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}}, "sFlow": { "columns": { "targets": { "type": {"key": "string", "min": 1, "max": "unlimited"}}, "sampling": { "type": {"key": "integer", "min": 0, "max": 1}}, "polling": { "type": {"key": "integer", "min": 0, "max": 1}}, "header": { "type": {"key": "integer", "min": 0, "max": 1}}, "agent": { "type": {"key": "string", "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}}, "IPFIX": { "columns": { "targets": { "type": {"key": "string", "min": 0, "max": "unlimited"}}, "sampling": { "type": {"key": {"type": "integer", "minInteger": 1, "maxInteger": 4294967295}, "min": 0, "max": 1}}, "obs_domain_id": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4294967295}, "min": 0, "max": 1}}, "obs_point_id": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4294967295}, "min": 0, "max": 1}}, "cache_active_timeout": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4200}, "min": 0, "max": 1}}, "cache_max_flows": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4294967295}, "min": 0, "max": 1}}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}}, "Flow_Sample_Collector_Set": { "columns": { "id": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 4294967295}, "min": 1, "max": 1}}, "bridge": { "type": {"key": {"type": "uuid", "refTable": "Bridge"}, "min": 1, "max": 1}}, "ipfix": { "type": {"key": {"type": "uuid", "refTable": "IPFIX"}, "min": 0, "max": 1}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "isRoot": true, "indexes": [["id", "bridge"]]}, "Controller": { "columns": { "target": { "type": "string"}, "max_backoff": { "type": {"key": {"type": "integer", "minInteger": 1000}, "min": 0, "max": 1}}, "inactivity_probe": { "type": {"key": "integer", "min": 0, "max": 1}}, "connection_mode": { "type": {"key": {"type": "string", "enum": ["set", ["in-band", "out-of-band"]]}, "min": 0, "max": 1}}, "local_ip": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "local_netmask": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "local_gateway": { "type": {"key": {"type": "string"}, "min": 0, "max": 1}}, "enable_async_messages": { "type": {"key": {"type": "boolean"}, "min": 0, "max": 1}}, "controller_rate_limit": { "type": {"key": {"type": "integer", "minInteger": 100}, "min": 0, "max": 1}}, "controller_burst_limit": { "type": {"key": {"type": "integer", "minInteger": 25}, "min": 0, "max": 1}}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "is_connected": { "type": "boolean", "ephemeral": true}, "role": { "type": {"key": {"type": "string", "enum": ["set", ["other", "master", "slave"]]}, "min": 0, "max": 1}, "ephemeral": true}, "status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}}}, "Manager": { "columns": { "target": { "type": "string"}, "max_backoff": { "type": {"key": {"type": "integer", "minInteger": 1000}, "min": 0, "max": 1}}, "inactivity_probe": { "type": {"key": "integer", "min": 0, "max": 1}}, "connection_mode": { "type": {"key": {"type": "string", "enum": ["set", ["in-band", "out-of-band"]]}, "min": 0, "max": 1}}, "other_config": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}, "is_connected": { "type": "boolean", "ephemeral": true}, "status": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}, "ephemeral": true}}, "indexes": [["target"]]}, "SSL": { "columns": { "private_key": { "type": "string"}, "certificate": { "type": "string"}, "ca_cert": { "type": "string"}, "bootstrap_ca_cert": { "type": "boolean"}, "external_ids": { "type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}}}, "maxRows": 1}, "AutoAttach": { "columns": { "system_name": { "type": "string"}, "system_description": { "type": "string"}, "mappings": { "type": {"key": {"type": "integer", "minInteger": 0, "maxInteger": 16777215}, "value": {"type": "integer", "minInteger": 0, "maxInteger": 4095}, "min": 0, "max": "unlimited"}}}}}} openvswitch-2.5.0/vswitchd/PaxHeaders.69223/vswitch.xml0000644000000000000000000000013212664352753017712 xustar0030 mtime=1456592363.502623465 30 atime=1456592368.230817659 30 ctime=1456594660.029281925 openvswitch-2.5.0/vswitchd/vswitch.xml0000664000175000017500000060675112664352753021421 0ustar00jpettitjpettit00000000000000

A database with this schema holds the configuration for one Open vSwitch daemon. The top-level configuration for the daemon is the table, which must have exactly one record. Records in other tables are significant only when they can be reached directly or indirectly from the table. Records that are not reachable from the table are automatically deleted from the database, except for records in a few distinguished ``root set'' tables.

Common Columns

Most tables contain two special columns, named other_config and external_ids. These columns have the same form and purpose each place that they appear, so we describe them here to save space later.

other_config: map of string-string pairs

Key-value pairs for configuring rarely used features. Supported keys, along with the forms taken by their values, are documented individually for each table.

A few tables do not have other_config columns because no key-value pairs have yet been defined for them.

external_ids: map of string-string pairs
Key-value pairs for use by external frameworks that integrate with Open vSwitch, rather than by Open vSwitch itself. System integrators should either use the Open vSwitch development mailing list to coordinate on common key-value definitions, or choose key names that are likely to be unique. In some cases, where key-value pairs have been defined that are likely to be widely useful, they are documented individually for each table.
Configuration for an Open vSwitch daemon. There must be exactly one record in the table. Set of bridges managed by the daemon. SSL used globally by the daemon. A unique identifier for the Open vSwitch's physical host. The form of the identifier depends on the type of the host. On a Citrix XenServer, this will likely be the same as . The Citrix XenServer universally unique identifier for the physical host as displayed by xe host-list.

Interval for updating statistics to the database, in milliseconds. This option will affect the update of the statistics column in the following tables: Port, Interface , Mirror.

Default value is 5000 ms.

Getting statistics more frequently can be achieved via OpenFlow.

When ovs-vswitchd starts up, it has an empty flow table and therefore it handles all arriving packets in its default fashion according to its configuration, by dropping them or sending them to an OpenFlow controller or switching them as a standalone switch. This behavior is ordinarily desirable. However, if ovs-vswitchd is restarting as part of a ``hot-upgrade,'' then this leads to a relatively long period during which packets are mishandled.

This option allows for improvement. When ovs-vswitchd starts with this value set as true, it will neither flush or expire previously set datapath flows nor will it send and receive any packets to or from the datapath. When this value is later set to false, ovs-vswitchd will start receiving packets from the datapath and re-setup the flows.

Thus, with this option, the procedure for a hot-upgrade of ovs-vswitchd becomes roughly the following:

  1. Stop ovs-vswitchd.
  2. Set to true.
  3. Start ovs-vswitchd.
  4. Use ovs-ofctl (or some other program, such as an OpenFlow controller) to restore the OpenFlow flow table to the desired state.
  5. Set to false (or remove it entirely from the database).

The ovs-ctl's ``restart'' and ``force-reload-kmod'' functions use the above config option during hot upgrades.

The maximum number of flows allowed in the datapath flow table. Internally OVS will choose a flow limit which will likely be lower than this number, based on real time network conditions. Tweaking this value is discouraged unless you know exactly what you're doing.

The default is 200000.

The maximum time (in ms) that idle flows will remain cached in the datapath. Internally OVS will check the validity and activity for datapath flows regularly and may expire flows quicker than this number, based on real time network conditions. Tweaking this value is discouraged unless you know exactly what you're doing.

The default is 10000.

Specifies the maximum number of rx queues to be created for each dpdk interface. If not specified or specified to 0, one rx queue will be created for each dpdk interface by default.

Specifies CPU mask for setting the cpu affinity of PMD (Poll Mode Driver) threads. Value should be in the form of hex string, similar to the dpdk EAL '-c COREMASK' option input or the 'taskset' mask input.

The lowest order bit corresponds to the first CPU core. A set bit means the corresponding core is available and a pmd thread will be created and pinned to it. If the input does not cover all cores, those uncovered cores are considered not set.

If not specified, one pmd thread will be created for each numa node and pinned to any available core on the numa node by default.

Specifies the number of threads for software datapaths to use for handling new flows. The default the number of online CPU cores minus the number of revalidators.

This configuration is per datapath. If you have more than one software datapath (e.g. some system bridges and some netdev bridges), then the total number of threads is n-handler-threads times the number of software datapaths.

Specifies the number of threads for software datapaths to use for revalidating flows in the datapath. Typically, there is a direct correlation between the number of revalidator threads, and the number of flows allowed in the datapath. The default is the number of cpu cores divided by four plus one. If n-handler-threads is set, the default changes to the number of cpu cores minus the number of handler threads.

This configuration is per datapath. If you have more than one software datapath (e.g. some system bridges and some netdev bridges), then the total number of threads is n-handler-threads times the number of software datapaths.

Sequence number for client to increment. When a client modifies any part of the database configuration and wishes to wait for Open vSwitch to finish applying the changes, it may increment this sequence number. Sequence number that Open vSwitch sets to the current value of after it finishes applying a set of configuration changes.

The statistics column contains key-value pairs that report statistics about a system running an Open vSwitch. These are updated periodically (currently, every 5 seconds). Key-value pairs that cannot be determined or that do not apply to a platform are omitted.

Statistics are disabled by default to avoid overhead in the common case when statistics gathering is not useful. Set this value to true to enable populating the column or to false to explicitly disable it.

Number of CPU processors, threads, or cores currently online and available to the operating system on which Open vSwitch is running, as an integer. This may be less than the number installed, if some are not online or if they are not available to the operating system.

Open vSwitch userspace processes are not multithreaded, but the Linux kernel-based datapath is.

A comma-separated list of three floating-point numbers, representing the system load average over the last 1, 5, and 15 minutes, respectively.

A comma-separated list of integers, each of which represents a quantity of memory in kilobytes that describes the operating system on which Open vSwitch is running. In respective order, these values are:

  1. Total amount of RAM allocated to the OS.
  2. RAM allocated to the OS that is in use.
  3. RAM that can be flushed out to disk or otherwise discarded if that space is needed for another purpose. This number is necessarily less than or equal to the previous value.
  4. Total disk space allocated for swap.
  5. Swap space currently in use.

On Linux, all five values can be determined and are included. On other operating systems, only the first two values can be determined, so the list will only have two values.

One such key-value pair, with NAME replaced by a process name, will exist for each running Open vSwitch daemon process, with name replaced by the daemon's name (e.g. process_ovs-vswitchd). The value is a comma-separated list of integers. The integers represent the following, with memory measured in kilobytes and durations in milliseconds:

  1. The process's virtual memory size.
  2. The process's resident set size.
  3. The amount of user and system CPU time consumed by the process.
  4. The number of times that the process has crashed and been automatically restarted by the monitor.
  5. The duration since the process was started.
  6. The duration for which the process has been running.

The interpretation of some of these values depends on whether the process was started with the . If it was not, then the crash count will always be 0 and the two durations will always be the same. If was given, then the crash count may be positive; if it is, the latter duration is the amount of time since the most recent crash and restart.

There will be one key-value pair for each file in Open vSwitch's ``run directory'' (usually /var/run/openvswitch) whose name ends in .pid, whose contents are a process ID, and which is locked by a running process. The name is taken from the pidfile's name.

Currently Open vSwitch is only able to obtain all of the above detail on Linux systems. On other systems, the same key-value pairs will be present but the values will always be the empty string.

A space-separated list of information on local, writable file systems. Each item in the list describes one file system and consists in turn of a comma-separated list of the following:

  1. Mount point, e.g. / or /var/log. Any spaces or commas in the mount point are replaced by underscores.
  2. Total size, in kilobytes, as an integer.
  3. Amount of storage in use, in kilobytes, as an integer.

This key-value pair is omitted if there are no local, writable file systems or if Open vSwitch cannot obtain the needed information.

These columns report the types and versions of the hardware and software running Open vSwitch. We recommend in general that software should test whether specific features are supported instead of relying on version number checks. These values are primarily intended for reporting to human administrators.

The Open vSwitch version number, e.g. 1.1.0.

The database schema version number in the form major.minor.tweak, e.g. 1.2.3. Whenever the database schema is changed in a non-backward compatible way (e.g. deleting a column or a table), major is incremented. When the database schema is changed in a backward compatible way (e.g. adding a new column), minor is incremented. When the database schema is changed cosmetically (e.g. reindenting its syntax), tweak is incremented.

The schema version is part of the database schema, so it can also be retrieved by fetching the schema using the Open vSwitch database protocol.

An identifier for the type of system on top of which Open vSwitch runs, e.g. XenServer or KVM.

System integrators are responsible for choosing and setting an appropriate value for this column.

The version of the system identified by , e.g. 5.6.100-39265p on XenServer 5.6.100 build 39265.

System integrators are responsible for choosing and setting an appropriate value for this column.

These columns report capabilities of the Open vSwitch instance.

This column reports the different dpifs registered with the system. These are the values that this instance supports in the column of the table.

This column reports the different netdevs registered with the system. These are the values that this instance supports in the column of the table.

These columns primarily configure the Open vSwitch database (ovsdb-server), not the Open vSwitch switch (ovs-vswitchd). The OVSDB database also uses the settings.

The Open vSwitch switch does read the database configuration to determine remote IP addresses to which in-band control should apply.

Database clients to which the Open vSwitch database server should connect or to which it should listen, along with options for how these connection should be configured. See the table for more information.
The overall purpose of these columns is described under Common Columns at the beginning of this document.

Configuration for a bridge within an .

A record represents an Ethernet switch with one or more ``ports,'' which are the records pointed to by the 's column.

Bridge identifier. Should be alphanumeric and no more than about 8 bytes long. Must be unique among the names of ports, interfaces, and bridges on a host. Ports included in the bridge. Port mirroring configuration. NetFlow configuration. sFlow(R) configuration. IPFIX configuration.

VLAN IDs of VLANs on which MAC address learning should be disabled, so that packets are flooded instead of being sent to specific ports that are believed to contain packets' destination MACs. This should ordinarily be used to disable MAC learning on VLANs used for mirroring (RSPAN VLANs). It may also be useful for debugging.

SLB bonding (see the column in the table) is incompatible with flood_vlans. Consider using another bonding mode or a different type of mirror instead.

Auto Attach configuration.

OpenFlow controller set. If unset, then no OpenFlow controllers will be used.

If there are primary controllers, removing all of them clears the flow table. If there are no primary controllers, adding one also clears the flow table. Other changes to the set of controllers, such as adding or removing a service controller, adding another primary controller to supplement an existing primary controller, or removing only one of two primary controllers, have no effect on the flow table.

Configuration for OpenFlow tables. Each pair maps from an OpenFlow table ID to configuration for that table.

When a controller is configured, it is, ordinarily, responsible for setting up all flows on the switch. Thus, if the connection to the controller fails, no new network connections can be set up. If the connection to the controller stays down long enough, no packets can pass through the switch at all. This setting determines the switch's response to such a situation. It may be set to one of the following:

standalone
If no message is received from the controller for three times the inactivity probe interval (see ), then Open vSwitch will take over responsibility for setting up flows. In this mode, Open vSwitch causes the bridge to act like an ordinary MAC-learning switch. Open vSwitch will continue to retry connecting to the controller in the background and, when the connection succeeds, it will discontinue its standalone behavior.
secure
Open vSwitch will not set up flows on its own when the controller connection fails or when no controllers are defined. The bridge will continue to retry connecting to any defined controllers forever.

The default is standalone if the value is unset, but future versions of Open vSwitch may change the default.

The standalone mode can create forwarding loops on a bridge that has more than one uplink port unless STP is enabled. To avoid loops on such a bridge, configure secure mode or enable STP (see ).

When more than one controller is configured, is considered only when none of the configured controllers can be contacted.

Changing when no primary controllers are configured clears the flow table.

Reports the OpenFlow datapath ID in use. Exactly 16 hex digits. (Setting this column has no useful effect. Set instead.)

Reports the version number of the Open vSwitch datapath in use. This allows management software to detect and report discrepancies between Open vSwitch userspace and datapath versions. (The column in the reports the Open vSwitch userspace version.) The version reported depends on the datapath in use:

  • When the kernel module included in the Open vSwitch source tree is used, this column reports the Open vSwitch version from which the module was taken.
  • When the kernel module that is part of the upstream Linux kernel is used, this column reports <unknown>.
  • When the datapath is built into the ovs-vswitchd binary, this column reports <built-in>. A built-in datapath is by definition the same version as the rest of the Open VSwitch userspace.
  • Other datapaths (such as the Hyper-V kernel datapath) currently report <unknown>.

A version discrepancy between ovs-vswitchd and the datapath in use is not normally cause for alarm. The Open vSwitch kernel datapaths for Linux and Hyper-V, in particular, are designed for maximum inter-version compatibility: any userspace version works with with any kernel version. Some reasons do exist to insist on particular user/kernel pairings. First, newer kernel versions add new features, that can only be used by new-enough userspace, e.g. VXLAN tunneling requires certain minimal userspace and kernel versions. Second, as an extension to the first reason, some newer kernel versions add new features for enhancing performance that only new-enough userspace versions can take advantage of.

Exactly 16 hex digits to set the OpenFlow datapath ID to a specific value. May not be all-zero. Human readable description of datapath. It it a maximum 256 byte-long free-form string to describe the datapath for debugging purposes, e.g. switch3 in room 3120. If set to true, disable in-band control on the bridge regardless of controller and manager settings. A queue ID as a nonnegative integer. This sets the OpenFlow queue ID that will be used by flows set up by in-band control on this bridge. If unset, or if the port used by an in-band control flow does not have QoS configured, or if the port does not have a queue with the specified ID, the default queue is used instead.

List of OpenFlow protocols that may be used when negotiating a connection with a controller. OpenFlow 1.0, 1.1, 1.2, and 1.3 are enabled by default if this column is empty.

OpenFlow 1.4 is not enabled by default because its implementation is missing features.

OpenFlow 1.5 has the same risks as OpenFlow 1.4, but it is even more experimental because the OpenFlow 1.5 specification is still under development and thus subject to change. Pass --enable-of15 to ovs-vswitchd to allow OpenFlow 1.5 to be enabled.

The IEEE 802.1D Spanning Tree Protocol (STP) is a network protocol that ensures loop-free topologies. It allows redundant links to be included in the network to provide automatic backup paths if the active links fails.

These settings configure the slower-to-converge but still widely supported version of Spanning Tree Protocol, sometimes known as 802.1D-1998. Open vSwitch also supports the newer Rapid Spanning Tree Protocol (RSTP), documented later in the section titled Rapid Spanning Tree Configuration.

Enable spanning tree on the bridge. By default, STP is disabled on bridges. Bond, internal, and mirror ports are not supported and will not participate in the spanning tree.

STP and RSTP are mutually exclusive. If both are enabled, RSTP will be used.

The bridge's STP identifier (the lower 48 bits of the bridge-id) in the form xx:xx:xx:xx:xx:xx. By default, the identifier is the MAC address of the bridge. The bridge's relative priority value for determining the root bridge (the upper 16 bits of the bridge-id). A bridge with the lowest bridge-id is elected the root. By default, the priority is 0x8000. The interval between transmissions of hello messages by designated ports, in seconds. By default the hello interval is 2 seconds. The maximum age of the information transmitted by the bridge when it is the root bridge, in seconds. By default, the maximum age is 20 seconds. The delay to wait between transitioning root and designated ports to forwarding, in seconds. By default, the forwarding delay is 15 seconds.

The maximum number of seconds to retain a multicast snooping entry for which no packets have been seen. The default is currently 300 seconds (5 minutes). The value, if specified, is forced into a reasonable range, currently 15 to 3600 seconds.

The maximum number of multicast snooping addresses to learn. The default is currently 2048. The value, if specified, is forced into a reasonable range, currently 10 to 1,000,000.

If set to false, unregistered multicast packets are forwarded to all ports. If set to true, unregistered multicast packets are forwarded to ports connected to multicast routers.

These key-value pairs report the status of 802.1D-1998. They are present only if STP is enabled (via the column).

The bridge ID used in spanning tree advertisements, in the form xxxx.yyyyyyyyyyyy where the xs are the STP priority, the ys are the STP system ID, and each x and y is a hex digit. The designated root for this spanning tree, in the same form as . If this bridge is the root, this will have the same value as , otherwise it will differ. The path cost of reaching the designated bridge. A lower number is better. The value is 0 if this bridge is the root, otherwise it is higher.

Rapid Spanning Tree Protocol (RSTP), like STP, is a network protocol that ensures loop-free topologies. RSTP superseded STP with the publication of 802.1D-2004. Compared to STP, RSTP converges more quickly and recovers more quickly from failures.

Enable Rapid Spanning Tree on the bridge. By default, RSTP is disabled on bridges. Bond, internal, and mirror ports are not supported and will not participate in the spanning tree.

STP and RSTP are mutually exclusive. If both are enabled, RSTP will be used.

The bridge's RSTP address (the lower 48 bits of the bridge-id) in the form xx:xx:xx:xx:xx:xx. By default, the address is the MAC address of the bridge. The bridge's relative priority value for determining the root bridge (the upper 16 bits of the bridge-id). A bridge with the lowest bridge-id is elected the root. By default, the priority is 0x8000 (32768). This value needs to be a multiple of 4096, otherwise it's rounded to the nearest inferior one. The Ageing Time parameter for the Bridge. The default value is 300 seconds. The Force Protocol Version parameter for the Bridge. This can take the value 0 (STP Compatibility mode) or 2 (the default, normal operation). The maximum age of the information transmitted by the Bridge when it is the Root Bridge. The default value is 20. The delay used by STP Bridges to transition Root and Designated Ports to Forwarding. The default value is 15. The Transmit Hold Count used by the Port Transmit state machine to limit transmission rate. The default value is 6.

These key-value pairs report the status of 802.1D-2004. They are present only if RSTP is enabled (via the column).

The bridge ID used in rapid spanning tree advertisements, in the form x.yyy.zzzzzzzzzzzz where x is the RSTP priority, the ys are a locally assigned system ID extension, the zs are the STP system ID, and each x, y, or z is a hex digit. The root of this spanning tree, in the same form as . If this bridge is the root, this will have the same value as , otherwise it will differ. The path cost of reaching the root. A lower number is better. The value is 0 if this bridge is the root, otherwise it is higher. The RSTP designated ID, in the same form as . The RSTP designated port ID, as a 4-digit hex number. The RSTP bridge port ID, as a 4-digit hex number.
Multicast snooping (RFC 4541) monitors the Internet Group Management Protocol (IGMP) and Multicast Listener Discovery traffic between hosts and multicast routers. The switch uses what IGMP and MLD snooping learns to forward multicast traffic only to interfaces that are connected to interested receivers. Currently it supports IGMPv1, IGMPv2, IGMPv3, MLDv1 and MLDv2 protocols. Enable multicast snooping on the bridge. For now, the default is disabled. Name of datapath provider. The kernel datapath has type system. The userspace datapath has type netdev. A manager may refer to the column of the table for a list of the types accepted by this Open vSwitch instance. A unique identifier of the bridge. On Citrix XenServer this will commonly be the same as . Semicolon-delimited set of universally unique identifier(s) for the network with which this bridge is associated on a Citrix XenServer host. The network identifiers are RFC 4122 UUIDs as displayed by, e.g., xe network-list. An Ethernet address in the form xx:xx:xx:xx:xx:xx to set the hardware address of the local port and influence the datapath ID.

Controls forwarding of BPDUs and other network control frames when NORMAL action is invoked. When this option is false or unset, frames with reserved Ethernet addresses (see table below) will not be forwarded. When this option is true, such frames will not be treated specially.

The above general rule has the following exceptions:

  • If STP is enabled on the bridge (see the column in the table), the bridge processes all received STP packets and never passes them to OpenFlow or forwards them. This is true even if STP is disabled on an individual port.
  • If LLDP is enabled on an interface (see the column in the table), the interface processes received LLDP packets and never passes them to OpenFlow or forwards them.

Set this option to true if the Open vSwitch bridge connects different Ethernet networks and is not configured to participate in STP.

This option affects packets with the following destination MAC addresses:

01:80:c2:00:00:00
IEEE 802.1D Spanning Tree Protocol (STP).
01:80:c2:00:00:01
IEEE Pause frame.
01:80:c2:00:00:0x
Other reserved protocols.
00:e0:2b:00:00:00
Extreme Discovery Protocol (EDP).
00:e0:2b:00:00:04 and 00:e0:2b:00:00:06
Ethernet Automatic Protection Switching (EAPS).
01:00:0c:cc:cc:cc
Cisco Discovery Protocol (CDP), VLAN Trunking Protocol (VTP), Dynamic Trunking Protocol (DTP), Port Aggregation Protocol (PAgP), and others.
01:00:0c:cc:cc:cd
Cisco Shared Spanning Tree Protocol PVSTP+.
01:00:0c:cd:cd:cd
Cisco STP Uplink Fast.
01:00:0c:00:00:00
Cisco Inter Switch Link.
01:00:0c:cc:cc:cx
Cisco CFM.

The maximum number of seconds to retain a MAC learning entry for which no packets have been seen. The default is currently 300 seconds (5 minutes). The value, if specified, is forced into a reasonable range, currently 15 to 3600 seconds.

A short MAC aging time allows a network to more quickly detect that a host is no longer connected to a switch port. However, it also makes it more likely that packets will be flooded unnecessarily, when they are addressed to a connected host that rarely transmits packets. To reduce the incidence of unnecessary flooding, use a MAC aging time longer than the maximum interval at which a host will ordinarily transmit packets.

The maximum number of MAC addresses to learn. The default is currently 2048. The value, if specified, is forced into a reasonable range, currently 10 to 1,000,000.

The overall purpose of these columns is described under Common Columns at the beginning of this document.

A port within a .

Most commonly, a port has exactly one ``interface,'' pointed to by its column. Such a port logically corresponds to a port on a physical Ethernet switch. A port with more than one interface is a ``bonded port'' (see ).

Some properties that one might think as belonging to a port are actually part of the port's members.

Port name. Should be alphanumeric and no more than about 8 bytes long. May be the same as the interface name, for non-bonded ports. Must otherwise be unique among the names of ports, interfaces, and bridges on a host. The port's interfaces. If there is more than one, this is a bonded Port.

Bridge ports support the following types of VLAN configuration:

trunk

A trunk port carries packets on one or more specified VLANs specified in the column (often, on every VLAN). A packet that ingresses on a trunk port is in the VLAN specified in its 802.1Q header, or VLAN 0 if the packet has no 802.1Q header. A packet that egresses through a trunk port will have an 802.1Q header if it has a nonzero VLAN ID.

Any packet that ingresses on a trunk port tagged with a VLAN that the port does not trunk is dropped.

access

An access port carries packets on exactly one VLAN specified in the column. Packets egressing on an access port have no 802.1Q header.

Any packet with an 802.1Q header with a nonzero VLAN ID that ingresses on an access port is dropped, regardless of whether the VLAN ID in the header is the access port's VLAN ID.

native-tagged
A native-tagged port resembles a trunk port, with the exception that a packet without an 802.1Q header that ingresses on a native-tagged port is in the ``native VLAN'' (specified in the column).
native-untagged
A native-untagged port resembles a native-tagged port, with the exception that a packet that egresses on a native-untagged port in the native VLAN will not have an 802.1Q header.

A packet will only egress through bridge ports that carry the VLAN of the packet, as described by the rules above.

The VLAN mode of the port, as described above. When this column is empty, a default mode is selected as follows:

  • If contains a value, the port is an access port. The column should be empty.
  • Otherwise, the port is a trunk port. The column value is honored if it is present.

For an access port, the port's implicitly tagged VLAN. For a native-tagged or native-untagged port, the port's native VLAN. Must be empty if this is a trunk port.

For a trunk, native-tagged, or native-untagged port, the 802.1Q VLAN or VLANs that this port trunks; if it is empty, then the port trunks all VLANs. Must be empty if this is an access port.

A native-tagged or native-untagged port always trunks its native VLAN, regardless of whether includes that VLAN.

An 802.1Q header contains two important pieces of information: a VLAN ID and a priority. A frame with a zero VLAN ID, called a ``priority-tagged'' frame, is supposed to be treated the same way as a frame without an 802.1Q header at all (except for the priority).

However, some network elements ignore any frame that has 802.1Q header at all, even when the VLAN ID is zero. Therefore, by default Open vSwitch does not output priority-tagged frames, instead omitting the 802.1Q header entirely if the VLAN ID is zero. Set this key to true to enable priority-tagged frames on a port.

Regardless of this setting, Open vSwitch omits the 802.1Q header on output if both the VLAN ID and priority would be zero.

All frames output to native-tagged ports have a nonzero VLAN ID, so this setting is not meaningful on native-tagged ports.

A port that has more than one interface is a ``bonded port.'' Bonding allows for load balancing and fail-over.

The following types of bonding will work with any kind of upstream switch. On the upstream switch, do not configure the interfaces as a bond:

balance-slb
Balances flows among slaves based on source MAC address and output VLAN, with periodic rebalancing as traffic patterns change.
active-backup
Assigns all flows to one slave, failing over to a backup slave when the active slave is disabled. This is the only bonding mode in which interfaces may be plugged into different upstream switches.

The following modes require the upstream switch to support 802.3ad with successful LACP negotiation. If LACP negotiation fails and other-config:lacp-fallback-ab is true, then active-backup mode is used:

balance-tcp
Balances flows among slaves based on L2, L3, and L4 protocol information such as destination MAC address, IP address, and TCP port.

These columns apply only to bonded ports. Their values are otherwise ignored.

The type of bonding used for a bonded port. Defaults to active-backup if unset.

An integer hashed along with flows when choosing output slaves in load balanced bonds. When changed, all flows will be assigned different hash values possibly causing slave selection decisions to change. Does not affect bonding modes which do not employ load balancing such as active-backup.

An important part of link bonding is detecting that links are down so that they may be disabled. These settings determine how Open vSwitch detects link failure.

The means used to detect link failures. Defaults to carrier which uses each interface's carrier to detect failures. When set to miimon, will check for failures by polling each interface's MII. The interval, in milliseconds, between successive attempts to poll each interface's MII. Relevant only when is miimon.

The number of milliseconds for which the link must stay up on an interface before the interface is considered to be up. Specify 0 to enable the interface immediately.

This setting is honored only when at least one bonded interface is already enabled. When no interfaces are enabled, then the first bond interface to come up is enabled immediately.

The number of milliseconds for which the link must stay down on an interface before the interface is considered to be down. Specify 0 to disable the interface immediately.

LACP, the Link Aggregation Control Protocol, is an IEEE standard that allows switches to automatically detect that they are connected by multiple links and aggregate across those links. These settings control LACP behavior.

Configures LACP on this port. LACP allows directly connected switches to negotiate which links may be bonded. LACP may be enabled on non-bonded ports for the benefit of any switches they may be connected to. active ports are allowed to initiate LACP negotiations. passive ports are allowed to participate in LACP negotiations initiated by a remote switch, but not allowed to initiate such negotiations themselves. If LACP is enabled on a port whose partner switch does not support LACP, the bond will be disabled, unless other-config:lacp-fallback-ab is set to true. Defaults to off if unset. The LACP system ID of this . The system ID of a LACP bond is used to identify itself to its partners. Must be a nonzero MAC address. Defaults to the bridge Ethernet address if unset. The LACP system priority of this . In LACP negotiations, link status decisions are made by the system with the numerically lower priority.

The LACP timing which should be used on this . By default slow is used. When configured to be fast LACP heartbeats are requested at a rate of once per second causing connectivity problems to be detected more quickly. In slow mode, heartbeats are requested at a rate of once every 30 seconds.

Determines the behavior of openvswitch bond in LACP mode. If the partner switch does not support LACP, setting this option to true allows openvswitch to fallback to active-backup. If the option is set to false, the bond will be disabled. In both the cases, once the partner switch is configured to LACP mode, the bond will use LACP.

These settings control behavior when a bond is in balance-slb or balance-tcp mode.

For a load balanced bonded port, the number of milliseconds between successive attempts to rebalance the bond, that is, to move flows from one interface on the bond to another in an attempt to keep usage of each interface roughly equal. If zero, load balancing is disabled on the bond (link failure still cause flows to move). If less than 1000ms, the rebalance interval will be 1000ms.
For a bonded port, whether to create a fake internal interface with the name of the port. Use only for compatibility with legacy software that requires this.

The configuration here is only meaningful, and the status is only populated, when 802.1D-1998 Spanning Tree Protocol is enabled on the port's with its column.

When STP is enabled on a bridge, it is enabled by default on all of the bridge's ports except bond, internal, and mirror ports (which do not work with STP). If this column's value is false, STP is disabled on the port. The port number used for the lower 8 bits of the port-id. By default, the numbers will be assigned automatically. If any port's number is manually configured on a bridge, then they must all be. The port's relative priority value for determining the root port (the upper 8 bits of the port-id). A port with a lower port-id will be chosen as the root port. By default, the priority is 0x80. Spanning tree path cost for the port. A lower number indicates a faster link. By default, the cost is based on the maximum speed of the link. The port ID used in spanning tree advertisements for this port, as 4 hex digits. Configuring the port ID is described in the stp-port-num and stp-port-priority keys of the other_config section earlier. STP state of the port. The amount of time this port has been in the current STP state, in seconds. STP role of the port.

The configuration here is only meaningful, and the status and statistics are only populated, when 802.1D-1998 Spanning Tree Protocol is enabled on the port's with its column.

When RSTP is enabled on a bridge, it is enabled by default on all of the bridge's ports except bond, internal, and mirror ports (which do not work with RSTP). If this column's value is false, RSTP is disabled on the port. The port's relative priority value for determining the root port, in multiples of 16. By default, the port priority is 0x80 (128). Any value in the lower 4 bits is rounded off. The significant upper 4 bits become the upper 4 bits of the port-id. A port with the lowest port-id is elected as the root. The local RSTP port number, used as the lower 12 bits of the port-id. By default the port numbers are assigned automatically, and typically may not correspond to the OpenFlow port numbers. A port with the lowest port-id is elected as the root. The port path cost. The Port's contribution, when it is the Root Port, to the Root Path Cost for the Bridge. By default the cost is automatically calculated from the port's speed. The admin edge port parameter for the Port. Default is false. The auto edge port parameter for the Port. Default is true.

The mcheck port parameter for the Port. Default is false. May be set to force the Port Protocol Migration state machine to transmit RST BPDUs for a MigrateTime period, to test whether all STP Bridges on the attached LAN have been removed and the Port can continue to transmit RSTP BPDUs. Setting mcheck has no effect if the Bridge is operating in STP Compatibility mode.

Changing the value from true to false has no effect, but needs to be done if this behavior is to be triggered again by subsequently changing the value from false to true.

The port ID used in spanning tree advertisements for this port, as 4 hex digits. Configuring the port ID is described in the rstp-port-num and rstp-port-priority keys of the other_config section earlier. RSTP role of the port. RSTP state of the port. The port's RSTP designated bridge ID, in the same form as in the table. The port's RSTP designated port ID, as 4 hex digits. The port's RSTP designated path cost. Lower is better. Number of RSTP BPDUs transmitted through this port. Number of valid RSTP BPDUs received by this port. Number of invalid RSTP BPDUs received by this port. The duration covered by the other RSTP statistics, in seconds.

If set to true, multicast packets (except Reports) are unconditionally forwarded to the specific port.

If set to true, multicast Reports are unconditionally forwarded to the specific port.

Quality of Service configuration for this port. The MAC address to use for this port for the purpose of choosing the bridge's MAC address. This column does not necessarily reflect the port's actual MAC address, nor will setting it change the port's actual MAC address. Does this port represent a sub-bridge for its tagged VLAN within the Bridge? See ovs-vsctl(8) for more information. External IDs for a fake bridge (see the column) are defined by prefixing a key with fake-bridge-, e.g. fake-bridge-xs-network-uuids.

If set to true, the port will be removed when ovs-ctl start --delete-transient-ports is used.

For a bonded port, record the mac address of the current active slave.

Key-value pairs that report port statistics. The update period is controlled by in the Open_vSwitch table.

Number of STP BPDUs sent on this port by the spanning tree library. Number of STP BPDUs received on this port and accepted by the spanning tree library. Number of bad STP BPDUs received on this port. Bad BPDUs include runt packets and those with an unexpected protocol ID.
The overall purpose of these columns is described under Common Columns at the beginning of this document.
An interface within a . Interface name. Should be alphanumeric and no more than about 8 bytes long. May be the same as the port name, for non-bonded ports. Must otherwise be unique among the names of ports, interfaces, and bridges on a host. A positive interface index as defined for SNMP MIB-II in RFCs 1213 and 2863, if the interface has one, otherwise 0. The ifindex is useful for seamless integration with protocols such as SNMP and sFlow. The MAC address in use by this interface.

Ethernet address to set for this interface. If unset then the default MAC address is used:

  • For the local interface, the default is the lowest-numbered MAC address among the other bridge ports, either the value of the in its record, if set, or its actual MAC (for bonded ports, the MAC of its slave whose name is first in alphabetical order). Internal ports and bridge ports that are used as port mirroring destinations (see the table) are ignored.
  • For other internal interfaces, the default MAC is randomly generated.
  • External interfaces typically have a MAC address associated with their hardware.

Some interfaces may not have a software-controllable MAC address.

If the configuration of the port failed, as indicated by -1 in , Open vSwitch sets this column to an error description in human readable form. Otherwise, Open vSwitch clears this column.

When a client adds a new interface, Open vSwitch chooses an OpenFlow port number for the new port. If the client that adds the port fills in , then Open vSwitch tries to use its value as the OpenFlow port number. Otherwise, or if the requested port number is already in use or cannot be used for another reason, Open vSwitch automatically assigns a free port number. Regardless of how the port number was obtained, Open vSwitch then reports in the port number actually assigned.

Open vSwitch limits the port numbers that it automatically assigns to the range 1 through 32,767, inclusive. Controllers therefore have free use of ports 32,768 and up.

OpenFlow port number for this interface. Open vSwitch sets this column's value, so other clients should treat it as read-only.

The OpenFlow ``local'' port (OFPP_LOCAL) is 65,534. The other valid port numbers are in the range 1 to 65,279, inclusive. Value -1 indicates an error adding the interface.

Requested OpenFlow port number for this interface.

A client should ideally set this column's value in the same database transaction that it uses to create the interface. Open vSwitch version 2.1 and later will honor a later request for a specific port number, althuogh it might confuse some controllers: OpenFlow does not have a way to announce a port number change, so Open vSwitch represents it over OpenFlow as a port deletion followed immediately by a port addition.

If is set or changed to some other port's automatically assigned port number, Open vSwitch chooses a new port number for the latter port.

The interface type. The types supported by a particular instance of Open vSwitch are listed in the column in the table. The following types are defined:

system
An ordinary network device, e.g. eth0 on Linux. Sometimes referred to as ``external interfaces'' since they are generally connected to hardware external to that on which the Open vSwitch is running. The empty string is a synonym for system.
internal
A simulated network device that sends and receives traffic. An internal interface whose is the same as its bridge's is called the ``local interface.'' It does not make sense to bond an internal interface, so the terms ``port'' and ``interface'' are often used imprecisely for internal interfaces.
tap
A TUN/TAP device managed by Open vSwitch.
geneve
An Ethernet over Geneve (http://tools.ietf.org/html/draft-ietf-nvo3-geneve-00) IPv4 tunnel. A description of how to match and set Geneve options can be found in the ovs-ofctl manual page.
gre
An Ethernet over RFC 2890 Generic Routing Encapsulation over IPv4 tunnel.
ipsec_gre
An Ethernet over RFC 2890 Generic Routing Encapsulation over IPv4 IPsec tunnel.
vxlan

An Ethernet tunnel over the UDP-based VXLAN protocol described in RFC 7348.

Open vSwitch uses UDP destination port 4789. The source port used for VXLAN traffic varies on a per-flow basis and is in the ephemeral port range.

lisp

A layer 3 tunnel over the experimental, UDP-based Locator/ID Separation Protocol (RFC 6830).

Only IPv4 and IPv6 packets are supported by the protocol, and they are sent and received without an Ethernet header. Traffic to/from LISP ports is expected to be configured explicitly, and the ports are not intended to participate in learning based switching. As such, they are always excluded from packet flooding.

stt
The Stateless TCP Tunnel (STT) is particularly useful when tunnel endpoints are in end-systems, as it utilizes the capabilities of standard network interface cards to improve performance. STT utilizes a TCP-like header inside the IP header. It is stateless, i.e., there is no TCP connection state of any kind associated with the tunnel. The TCP-like header is used to leverage the capabilities of existing network interface cards, but should not be interpreted as implying any sort of connection state between endpoints. Since the STT protocol does not engage in the usual TCP 3-way handshake, so it will have difficulty traversing stateful firewalls. The protocol is documented at http://www.ietf.org/archive/id/draft-davie-stt-06.txt All traffic uses a default destination port of 7471. STT is only available in kernel datapath on kernel 3.5 or newer.
patch
A pair of virtual devices that act as a patch cable.
null
An ignored interface. Deprecated and slated for removal in February 2013.

These options apply to interfaces with of geneve, gre, ipsec_gre, vxlan, lisp and stt.

Each tunnel must be uniquely identified by the combination of , , , and . If two ports are defined that are the same except one has an optional identifier and the other does not, the more specific one is matched first. is considered more specific than if a port defines one and another port defines the other.

Required. The remote tunnel endpoint, one of:

  • An IPv4 address (not a DNS name), e.g. 192.168.0.123. Only unicast endpoints are supported.
  • The word flow. The tunnel accepts packets from any remote tunnel endpoint. To process only packets from a specific remote tunnel endpoint, the flow entries may match on the tun_src field. When sending packets to a remote_ip=flow tunnel, the flow actions must explicitly set the tun_dst field to the IP address of the desired remote tunnel endpoint, e.g. with a set_field action.

The remote tunnel endpoint for any packet received from a tunnel is available in the tun_src field for matching in the flow table.

Optional. The tunnel destination IP that received packets must match. Default is to match all addresses. If specified, may be one of:

  • An IPv4 address (not a DNS name), e.g. 192.168.12.3.
  • The word flow. The tunnel accepts packets sent to any of the local IP addresses of the system running OVS. To process only packets sent to a specific IP address, the flow entries may match on the tun_dst field. When sending packets to a local_ip=flow tunnel, the flow actions may explicitly set the tun_src field to the desired IP address, e.g. with a set_field action. However, while routing the tunneled packet out, the local system may override the specified address with the local IP address configured for the outgoing system interface.

    This option is valid only for tunnels also configured with the remote_ip=flow option.

The tunnel destination IP address for any packet received from a tunnel is available in the tun_dst field for matching in the flow table.

Optional. The key that received packets must contain, one of:

  • 0. The tunnel receives packets with no key or with a key of 0. This is equivalent to specifying no at all.
  • A positive 24-bit (for Geneve, VXLAN, and LISP), 32-bit (for GRE) or 64-bit (for STT) number. The tunnel receives only packets with the specified key.
  • The word flow. The tunnel accepts packets with any key. The key will be placed in the tun_id field for matching in the flow table. The ovs-ofctl manual page contains additional information about matching fields in OpenFlow flows.

Optional. The key to be set on outgoing packets, one of:

  • 0. Packets sent through the tunnel will have no key. This is equivalent to specifying no at all.
  • A positive 24-bit (for Geneve, VXLAN and LISP), 32-bit (for GRE) or 64-bit (for STT) number. Packets sent through the tunnel will have the specified key.
  • The word flow. Packets sent through the tunnel will have the key set using the set_tunnel Nicira OpenFlow vendor extension (0 is used in the absence of an action). The ovs-ofctl manual page contains additional information about the Nicira OpenFlow vendor extensions.
Optional. Shorthand to set in_key and out_key at the same time. Optional. The value of the ToS bits to be set on the encapsulating packet. ToS is interpreted as DSCP and ECN bits, ECN part must be zero. It may also be the word inherit, in which case the ToS will be copied from the inner packet if it is IPv4 or IPv6 (otherwise it will be 0). The ECN fields are always inherited. Default is 0. Optional. The TTL to be set on the encapsulating packet. It may also be the word inherit, in which case the TTL will be copied from the inner packet if it is IPv4 or IPv6 (otherwise it will be the system default, typically 64). Default is the system default TTL. Optional. If enabled, the Don't Fragment bit will be set on tunnel outer headers to allow path MTU discovery. Default is enabled; set to false to disable.

Optional. Comma separated list of optional VXLAN extensions to enable. The following extensions are supported:

  • gbp: VXLAN-GBP allows to transport the group policy context of a packet across the VXLAN tunnel to other network peers. See the field description of tun_gbp_id and tun_gbp_flags in ovs-ofctl(8) for additional information. (https://tools.ietf.org/html/draft-smith-vxlan-group-policy)

gre, ipsec_gre, geneve, and vxlan interfaces support these options.

Optional. Compute encapsulation header (either GRE or UDP) checksums on outgoing packets. Default is disabled, set to true to enable. Checksums present on incoming packets will be validated regardless of this setting.

When using the upstream Linux kernel module, computation of checksums for geneve and vxlan requires Linux kernel version 4.0 or higher. gre supports checksums for all versions of Open vSwitch that support GRE. The out of tree kernel module distributed as part of OVS can compute all tunnel checksums on any kernel version that it is compatible with.

This option is supported for ipsec_gre, but not useful because GRE checksums are weaker than, and redundant with, IPsec payload authentication.

Only ipsec_gre interfaces support these options.

Required for certificate authentication. A string containing the peer's certificate in PEM format. Additionally the host's certificate must be specified with the certificate option. Required for certificate authentication. The name of a PEM file containing a certificate that will be presented to the peer during authentication. Optional for certificate authentication. The name of a PEM file containing the private key associated with certificate. If certificate contains the private key, this option may be omitted. Required for pre-shared key authentication. Specifies a pre-shared key for authentication that must be identical on both sides of the tunnel.

Only patch interfaces support these options.

The of the for the other side of the patch. The named 's own peer option must specify this 's name. That is, the two patch interfaces must have reversed and peer values.

Status information about interfaces attached to bridges, updated every 5 seconds. Not all interfaces have all of these properties; virtual interfaces don't have a link speed, for example. Non-applicable columns will have empty values.

The administrative state of the physical network link.

The observed state of the physical network link. This is ordinarily the link's carrier status. If the interface's is a bond configured for miimon monitoring, it is instead the network link's miimon status.

The number of times Open vSwitch has observed the of this change.

The negotiated speed of the physical network link. Valid values are positive integers greater than 0.

The duplex mode of the physical network link.

The MTU (maximum transmission unit); i.e. the largest amount of data that can fit into a single Ethernet frame. The standard Ethernet MTU is 1500 bytes. Some physical media and many kinds of virtual interfaces can be configured with higher MTUs.

This column will be empty for an interface that does not have an MTU as, for example, some kinds of tunnels do not.

Boolean value indicating LACP status for this interface. If true, this interface has current LACP information about its LACP partner. This information may be used to monitor the health of interfaces in a LACP enabled port. This column will be empty if LACP is not enabled. Key-value pairs that report port status. Supported status values are -dependent; some interfaces may not have a valid , for example. The name of the device driver controlling the network adapter. The version string of the device driver controlling the network adapter. The version string of the network adapter's firmware, if available. The source IP address used for an IPv4 tunnel end-point, such as gre. Egress interface for tunnels. Currently only relevant for tunnels on Linux systems, this column will show the name of the interface which is responsible for routing traffic destined for the configured . This could be an internal interface such as a bridge port. Whether carrier is detected on .

Key-value pairs that report interface statistics. The current implementation updates these counters periodically. The update period is controlled by in the Open_vSwitch table. Future implementations may update them when an interface is created, when they are queried (e.g. using an OVSDB select operation), and just before an interface is deleted due to virtual interface hot-unplug or VM shutdown, and perhaps at other times, but not on any regular periodic basis.

These are the same statistics reported by OpenFlow in its struct ofp_port_stats structure. If an interface does not support a given statistic, then that pair is omitted.

Number of received packets. Number of received bytes. Number of transmitted packets. Number of transmitted bytes. Number of packets dropped by RX. Number of frame alignment errors. Number of packets with RX overrun. Number of CRC errors. Total number of receive errors, greater than or equal to the sum of the above. Number of packets dropped by TX. Number of collisions. Total number of transmit errors, greater than or equal to the sum of the above.

These settings control ingress policing for packets received on this interface. On a physical interface, this limits the rate at which traffic is allowed into the system from the outside; on a virtual interface (one connected to a virtual machine), this limits the rate at which the VM is able to transmit.

Policing is a simple form of quality-of-service that simply drops packets received in excess of the configured rate. Due to its simplicity, policing is usually less accurate and less effective than egress QoS (which is configured using the and tables).

Policing is currently implemented only on Linux. The Linux implementation uses a simple ``token bucket'' approach:

  • The size of the bucket corresponds to . Initially the bucket is full.
  • Whenever a packet is received, its size (converted to tokens) is compared to the number of tokens currently in the bucket. If the required number of tokens are available, they are removed and the packet is forwarded. Otherwise, the packet is dropped.
  • Whenever it is not full, the bucket is refilled with tokens at the rate specified by .

Policing interacts badly with some network protocols, and especially with fragmented IP packets. Suppose that there is enough network activity to keep the bucket nearly empty all the time. Then this token bucket algorithm will forward a single packet every so often, with the period depending on packet size and on the configured rate. All of the fragments of an IP packets are normally transmitted back-to-back, as a group. In such a situation, therefore, only one of these fragments will be forwarded and the rest will be dropped. IP does not provide any way for the intended recipient to ask for only the remaining fragments. In such a case there are two likely possibilities for what will happen next: either all of the fragments will eventually be retransmitted (as TCP will do), in which case the same problem will recur, or the sender will not realize that its packet has been dropped and data will simply be lost (as some UDP-based protocols will do). Either way, it is possible that no forward progress will ever occur.

Maximum rate for data received on this interface, in kbps. Data received faster than this rate is dropped. Set to 0 (the default) to disable policing.

Maximum burst size for data received on this interface, in kb. The default burst size if set to 0 is 1000 kb. This value has no effect if is 0.

Specifying a larger burst size lets the algorithm be more forgiving, which is important for protocols like TCP that react severely to dropped packets. The burst size should be at least the size of the interface's MTU. Specifying a value that is numerically at least as large as 10% of helps TCP come closer to achieving the full rate.

BFD, defined in RFC 5880 and RFC 5881, allows point-to-point detection of connectivity failures by occasional transmission of BFD control messages. Open vSwitch implements BFD to serve as a more popular and standards compliant alternative to CFM.

BFD operates by regularly transmitting BFD control messages at a rate negotiated independently in each direction. Each endpoint specifies the rate at which it expects to receive control messages, and the rate at which it is willing to transmit them. Open vSwitch uses a detection multiplier of three, meaning that an endpoint signals a connectivity fault if three consecutive BFD control messages fail to arrive. In the case of a unidirectional connectivity issue, the system not receiving BFD control messages signals the problem to its peer in the messages it transmits.

The Open vSwitch implementation of BFD aims to comply faithfully with RFC 5880 requirements. Open vSwitch does not implement the optional Authentication or ``Echo Mode'' features.

A controller sets up key-value pairs in the column to enable and configure BFD.

True to enable BFD on this . If not specified, BFD will not be enabled by default. The shortest interval, in milliseconds, at which this BFD session offers to receive BFD control messages. The remote endpoint may choose to send messages at a slower rate. Defaults to 1000. The shortest interval, in milliseconds, at which this BFD session is willing to transmit BFD control messages. Messages will actually be transmitted at a slower rate if the remote endpoint is not willing to receive as quickly as specified. Defaults to 100. An alternate receive interval, in milliseconds, that must be greater than or equal to . The implementation switches from to when there is no obvious incoming data traffic at the interface, to reduce the CPU and bandwidth cost of monitoring an idle interface. This feature may be disabled by setting a value of 0. This feature is reset whenever or changes. When true, traffic received on the is used to indicate the capability of packet I/O. BFD control packets are still transmitted and received. At least one BFD control packet must be received every 100 * amount of time. Otherwise, even if traffic are received, the will be false. Set to true to notify the remote endpoint that traffic should not be forwarded to this system for some reason other than a connectivty failure on the interface being monitored. The typical underlying reason is ``concatenated path down,'' that is, that connectivity beyond the local system is down. Defaults to false. Set to true to make BFD accept only control messages with a tunnel key of zero. By default, BFD accepts control messages with any tunnel key. Set to an Ethernet address in the form xx:xx:xx:xx:xx:xx to set the MAC used as source for transmitted BFD packets. The default is the mac address of the BFD enabled interface. Set to an Ethernet address in the form xx:xx:xx:xx:xx:xx to set the MAC used as destination for transmitted BFD packets. The default is 00:23:20:00:00:01. Set to an Ethernet address in the form xx:xx:xx:xx:xx:xx to set the MAC used for checking the destination of received BFD packets. Packets with different destination MAC will not be considered as BFD packets. If not specified the destination MAC address of received BFD packets are not checked. Set to an IPv4 address to set the IP address used as source for transmitted BFD packets. The default is 169.254.1.1. Set to an IPv4 address to set the IP address used as destination for transmitted BFD packets. The default is 169.254.1.0.

The switch sets key-value pairs in the column to report the status of BFD on this interface. When BFD is not enabled, with , the switch clears all key-value pairs from .

Reports the state of the BFD session. The BFD session is fully healthy and negotiated if UP. Reports whether the BFD session believes this may be used to forward traffic. Typically this means the local session is signaling UP, and the remote system isn't signaling a problem such as concatenated path down. A diagnostic code specifying the local system's reason for the last change in session state. The error messages are defined in section 4.1 of [RFC 5880]. Reports the state of the remote endpoint's BFD session. A diagnostic code specifying the remote system's reason for the last change in session state. The error messages are defined in section 4.1 of [RFC 5880]. Counts the number of flaps since start. A flap is considered as a change of the value.

802.1ag Connectivity Fault Management (CFM) allows a group of Maintenance Points (MPs) called a Maintenance Association (MA) to detect connectivity problems with each other. MPs within a MA should have complete and exclusive interconnectivity. This is verified by occasionally broadcasting Continuity Check Messages (CCMs) at a configurable transmission interval.

According to the 802.1ag specification, each Maintenance Point should be configured out-of-band with a list of Remote Maintenance Points it should have connectivity to. Open vSwitch differs from the specification in this area. It simply assumes the link is faulted if no Remote Maintenance Points are reachable, and considers it not faulted otherwise.

When operating over tunnels which have no in_key, or an in_key of flow. CFM will only accept CCMs with a tunnel key of zero.

A Maintenance Point ID (MPID) uniquely identifies each endpoint within a Maintenance Association. The MPID is used to identify this endpoint to other Maintenance Points in the MA. Each end of a link being monitored should have a different MPID. Must be configured to enable CFM on this .

According to the 802.1ag specification, MPIDs can only range between [1, 8191]. However, extended mode (see ) supports eight byte MPIDs.

Counts the number of cfm fault flapps since boot. A flap is considered to be a change of the value.

Indicates a connectivity fault triggered by an inability to receive heartbeats from any remote endpoint. When a fault is triggered on s participating in bonds, they will be disabled.

Faults can be triggered for several reasons. Most importantly they are triggered when no CCMs are received for a period of 3.5 times the transmission interval. Faults are also triggered when any CCMs indicate that a Remote Maintenance Point is not receiving CCMs but able to send them. Finally, a fault is triggered if a CCM is received which indicates unexpected configuration. Notably, this case arises when a CCM is received which advertises the local MPID.

Indicates a CFM fault was triggered due to a lack of CCMs received on the . Indicates a CFM fault was triggered due to the reception of a CCM with the RDI bit flagged. Endpoints set the RDI bit in their CCMs when they are not receiving CCMs themselves. This typically indicates a unidirectional connectivity failure. Indicates a CFM fault was triggered due to the reception of a CCM with a MAID other than the one Open vSwitch uses. CFM broadcasts are tagged with an identification number in addition to the MPID called the MAID. Open vSwitch only supports receiving CCM broadcasts tagged with the MAID it uses internally. Indicates a CFM fault was triggered due to the reception of a CCM advertising the same MPID configured in the column of this . This may indicate a loop in the network. Indicates a CFM fault was triggered because the CFM module received CCMs from more remote endpoints than it can keep track of. Indicates a CFM fault was manually triggered by an administrator using an ovs-appctl command. Indicates a CFM fault was triggered due to the reception of a CCM frame having an invalid interval.

When in extended mode, indicates the operational state of the remote endpoint as either up or down. See .

Indicates the health of the interface as a percentage of CCM frames received over 21 s. The health of an interface is undefined if it is communicating with more than one . It reduces if healthy heartbeats are not received at the expected rate, and gradually improves as healthy heartbeats are received at the desired rate. Every 21 s, the health of the interface is refreshed.

As mentioned above, the faults can be triggered for several reasons. The link health will deteriorate even if heartbeats are received but they are reported to be unhealthy. An unhealthy heartbeat in this context is a heartbeat for which either some fault is set or is out of sequence. The interface health can be 100 only on receiving healthy heartbeats at the desired rate.

When CFM is properly configured, Open vSwitch will occasionally receive CCM broadcasts. These broadcasts contain the MPID of the sending Maintenance Point. The list of MPIDs from which this is receiving broadcasts from is regularly collected and written to this column.

The interval, in milliseconds, between transmissions of CFM heartbeats. Three missed heartbeat receptions indicate a connectivity fault.

In standard operation only intervals of 3, 10, 100, 1,000, 10,000, 60,000, or 600,000 ms are supported. Other values will be rounded down to the nearest value on the list. Extended mode (see ) supports any interval up to 65,535 ms. In either mode, the default is 1000 ms.

We do not recommend using intervals less than 100 ms.

When true, the CFM module operates in extended mode. This causes it to use a nonstandard destination address to avoid conflicting with compliant implementations which may be running concurrently on the network. Furthermore, extended mode increases the accuracy of the cfm_interval configuration parameter by breaking wire compatibility with 802.1ag compliant implementations. And extended mode allows eight byte MPIDs. Defaults to false.

When true, and is true, the CFM module operates in demand mode. When in demand mode, traffic received on the is used to indicate liveness. CCMs are still transmitted and received. At least one CCM must be received every 100 * amount of time. Otherwise, even if traffic are received, the CFM module will raise the connectivity fault.

Demand mode has a couple of caveats:

  • To ensure that ovs-vswitchd has enough time to pull statistics from the datapath, the fault detection interval is set to 3.5 * MAX(, 500) ms.
  • To avoid ambiguity, demand mode disables itself when there are multiple remote maintenance points.
  • If the is heavily congested, CCMs containing the status may be dropped causing changes in the operational state to be delayed. Similarly, if CCMs containing the RDI bit are not received, unidirectional link failures may not be detected.

When down, the CFM module marks all CCMs it generates as operationally down without triggering a fault. This allows remote maintenance points to choose not to forward traffic to the on which this CFM module is running. Currently, in Open vSwitch, the opdown bit of CCMs affects s participating in bonds, and the bundle OpenFlow action. This setting is ignored when CFM is not in extended mode. Defaults to up. When set, the CFM module will apply a VLAN tag to all CCMs it generates with the given value. May be the string random in which case each CCM will be tagged with a different randomly generated VLAN. When set, the CFM module will apply a VLAN tag to all CCMs it generates with the given PCP value, the VLAN ID of the tag is governed by the value of . If is unset, a VLAN ID of zero is used.
The LACP port ID of this . Port IDs are used in LACP negotiations to identify individual ports participating in a bond. The LACP port priority of this . In LACP negotiations s with numerically lower priorities are preferred for aggregation. The LACP aggregation key of this . s with different aggregation keys may not be active within a given at the same time.

These key-value pairs specifically apply to an interface that represents a virtual Ethernet interface connected to a virtual machine. These key-value pairs should not be present for other types of interfaces. Keys whose names end in -uuid have values that uniquely identify the entity in question. For a Citrix XenServer hypervisor, these values are UUIDs in RFC 4122 format. Other hypervisors may use other formats.

The MAC address programmed into the ``virtual hardware'' for this interface, in the form xx:xx:xx:xx:xx:xx. For Citrix XenServer, this is the value of the MAC field in the VIF record for this interface. A system-unique identifier for the interface. On XenServer, this will commonly be the same as .

Hypervisors may sometimes have more than one interface associated with a given , only one of which is actually in use at a given time. For example, in some circumstances XenServer has both a ``tap'' and a ``vif'' interface for a single , but only uses one of them at a time. A hypervisor that behaves this way must mark the currently in use interface active and the others inactive. A hypervisor that never has more than one interface for a given may mark that interface active or omit entirely.

During VM migration, a given might transiently be marked active on two different hypervisors. That is, active means that this is the active instance within a single hypervisor, not in a broader scope. There is one exception: some hypervisors support ``migration'' from a given hypervisor to itself (most often for test purposes). During such a ``migration,'' two instances of a single might both be briefly marked active on a single hypervisor.

The virtual interface associated with this interface. The virtual network to which this interface is attached. The VM to which this interface belongs. On XenServer, this will be the same as . The VM to which this interface belongs.

The ``VLAN splinters'' feature increases Open vSwitch compatibility with buggy network drivers in old versions of Linux that do not properly support VLANs when VLAN devices are not used, at some cost in memory and performance.

When VLAN splinters are enabled on a particular interface, Open vSwitch creates a VLAN device for each in-use VLAN. For sending traffic tagged with a VLAN on the interface, it substitutes the VLAN device. Traffic received on the VLAN device is treated as if it had been received on the interface on the particular VLAN.

VLAN splinters consider a VLAN to be in use if:

  • The VLAN is the value in any record.
  • The VLAN is listed within the column of the record of an interface on which VLAN splinters are enabled. An empty does not influence the in-use VLANs: creating 4,096 VLAN devices is impractical because it will exceed the current 1,024 port per datapath limit.
  • An OpenFlow flow within any bridge matches the VLAN.

The same set of in-use VLANs applies to every interface on which VLAN splinters are enabled. That is, the set is not chosen separately for each interface but selected once as the union of all in-use VLANs based on the rules above.

It does not make sense to enable VLAN splinters on an interface for an access port, or on an interface that is not a physical port.

VLAN splinters are deprecated. When broken device drivers are no longer in widespread use, we will delete this feature.

Set to true to enable VLAN splinters on this interface. Defaults to false.

VLAN splinters increase kernel and userspace memory overhead, so do not use them unless they are needed.

VLAN splinters do not support 802.1p priority tags. Received priorities will appear to be 0, regardless of their actual values, and priorities on transmitted packets will also be cleared to 0.

Auto Attach configuration for a particular interface.

True to enable LLDP on this . If not specified, LLDP will be disabled by default.
The overall purpose of these columns is described under Common Columns at the beginning of this document.

Configuration for a particular OpenFlow table.

The table's name. Set this column to change the name that controllers will receive when they request table statistics, e.g. ovs-ofctl dump-tables. The name does not affect switch behavior.

Open vSwitch supports limiting the number of flows that may be installed in a flow table, via the column. When adding a flow would exceed this limit, by default Open vSwitch reports an error, but there are two ways to configure Open vSwitch to instead delete (``evict'') a flow to make room for the new one:

  • Set the column to evict.
  • Send an OpenFlow 1.4+ ``table mod request'' to enable eviction for the flow table (e.g. ovs-ofctl -O OpenFlow14 mod-table br0 0 evict to enable eviction on flow table 0 of bridge br0).

When a flow must be evicted due to overflow, the flow to evict is chosen through an approximation of the following algorithm. This algorithm is used regardless of how eviction was enabled:

  1. Divide the flows in the table into groups based on the values of the fields or subfields specified in the column, so that all of the flows in a given group have the same values for those fields. If a flow does not specify a given field, that field's value is treated as 0. If is empty, then all of the flows in the flow table are treated as a single group.
  2. Consider the flows in the largest group, that is, the group that contains the greatest number of flows. If two or more groups all have the same largest number of flows, consider the flows in all of those groups.
  3. If the flows under consideration have different importance values, eliminate from consideration any flows except those with the lowest importance. (``Importance,'' a 16-bit integer value attached to each flow, was introduced in OpenFlow 1.4. Flows inserted with older versions of OpenFlow always have an importance of 0.)
  4. Among the flows under consideration, choose the flow that expires soonest for eviction.

The eviction process only considers flows that have an idle timeout or a hard timeout. That is, eviction never deletes permanent flows. (Permanent flows do count against .)

If set, limits the number of flows that may be added to the table. Open vSwitch may limit the number of flows in a table for other reasons, e.g. due to hardware limitations or for resource availability or performance reasons.

Controls the switch's behavior when an OpenFlow flow table modification request would add flows in excess of . The supported values are:

refuse
Refuse to add the flow or flows. This is also the default policy when is unset.
evict
Delete a flow chosen according to the algorithm described above.

When is evict, this controls how flows are chosen for eviction when the flow table would otherwise exceed flows. Its value is a set of NXM fields or sub-fields, each of which takes one of the forms field[] or field[start..end], e.g. NXM_OF_IN_PORT[]. Please see nicira-ext.h for a complete list of NXM field names.

Open vSwitch ignores any invalid or unknown field specifications.

When eviction is not enabled, via or an OpenFlow 1.4+ ``table mod,'' this column has no effect.

This string set specifies which fields should be used for address prefix tracking. Prefix tracking allows the classifier to skip rules with longer than necessary prefixes, resulting in better wildcarding for datapath flows.

Prefix tracking may be beneficial when a flow table contains matches on IP address fields with different prefix lengths. For example, when a flow table contains IP address matches on both full addresses and proper prefixes, the full address matches will typically cause the datapath flow to un-wildcard the whole address field (depending on flow entry priorities). In this case each packet with a different address gets handed to the userspace for flow processing and generates its own datapath flow. With prefix tracking enabled for the address field in question packets with addresses matching shorter prefixes would generate datapath flows where the irrelevant address bits are wildcarded, allowing the same datapath flow to handle all the packets within the prefix in question. In this case many userspace upcalls can be avoided and the overall performance can be better.

This is a performance optimization only, so packets will receive the same treatment with or without prefix tracking.

The supported fields are: tun_id, tun_src, tun_dst, nw_src, nw_dst (or aliases ip_src and ip_dst), ipv6_src, and ipv6_dst. (Using this feature for tun_id would only make sense if the tunnel IDs have prefix structure similar to IP addresses.)

By default, the prefixes=ip_dst,ip_src are used on each flow table. This instructs the flow classifier to track the IP destination and source addresses used by the rules in this specific flow table.

The keyword none is recognized as an explicit override of the default values, causing no prefix fields to be tracked.

To set the prefix fields, the flow table record needs to exist:

ovs-vsctl set Bridge br0 flow_tables:0=@N1 -- --id=@N1 create Flow_Table name=table0
Creates a flow table record for the OpenFlow table number 0.
ovs-vsctl set Flow_Table table0 prefixes=ip_dst,ip_src
Enables prefix tracking for IP source and destination address fields.

There is a maximum number of fields that can be enabled for any one flow table. Currently this limit is 3.

The overall purpose of these columns is described under Common Columns at the beginning of this document.

Quality of Service (QoS) configuration for each Port that references it.

The type of QoS to implement. The currently defined types are listed below:

linux-htb
Linux ``hierarchy token bucket'' classifier. See tc-htb(8) (also at http://linux.die.net/man/8/tc-htb) and the HTB manual (http://luxik.cdi.cz/~devik/qos/htb/manual/userg.htm) for information on how this classifier works and how to configure it.
linux-hfsc
Linux "Hierarchical Fair Service Curve" classifier. See http://linux-ip.net/articles/hfsc.en/ for information on how this classifier works.
linux-sfq
Linux ``Stochastic Fairness Queueing'' classifier. See tc-sfq(8) (also at http://linux.die.net/man/8/tc-sfq) for information on how this classifier works.
linux-codel
Linux ``Controlled Delay'' classifier. See tc-codel(8) (also at http://man7.org/linux/man-pages/man8/tc-codel.8.html) for information on how this classifier works.
linux-fq_codel
Linux ``Fair Queuing with Controlled Delay'' classifier. See tc-fq_codel(8) (also at http://man7.org/linux/man-pages/man8/tc-fq_codel.8.html) for information on how this classifier works.

A map from queue numbers to records. The supported range of queue numbers depend on . The queue numbers are the same as the queue_id used in OpenFlow in struct ofp_action_enqueue and other structures.

Queue 0 is the ``default queue.'' It is used by OpenFlow output actions when no specific queue has been set. When no configuration for queue 0 is present, it is automatically configured as if a record with empty and columns had been specified. (Before version 1.6, Open vSwitch would leave queue 0 unconfigured in this case. With some queuing disciplines, this dropped all packets destined for the default queue.)

The linux-htb and linux-hfsc classes support the following key-value pair:

Maximum rate shared by all queued traffic, in bit/s. Optional. If not specified, for physical interfaces, the default is the link rate. For other interfaces or if the link rate cannot be determined, the default is currently 100 Mbps.
The overall purpose of these columns is described under Common Columns at the beginning of this document.

A configuration for a port output queue, used in configuring Quality of Service (QoS) features. May be referenced by column in table.

If set, Open vSwitch will mark all traffic egressing this with the given DSCP bits. Traffic egressing the default is only marked if it was explicitly selected as the at the time the packet was output. If unset, the DSCP bits of traffic egressing this will remain unchanged.

linux-htb may use queue_ids less than 61440. It has the following key-value pairs defined.

Minimum guaranteed bandwidth, in bit/s. Maximum allowed bandwidth, in bit/s. Optional. If specified, the queue's rate will not be allowed to exceed the specified value, even if excess bandwidth is available. If unspecified, defaults to no limit. Burst size, in bits. This is the maximum amount of ``credits'' that a queue can accumulate while it is idle. Optional. Details of the linux-htb implementation require a minimum burst size, so a too-small burst will be silently ignored. A queue with a smaller priority will receive all the excess bandwidth that it can use before a queue with a larger value receives any. Specific priority values are unimportant; only relative ordering matters. Defaults to 0 if unspecified.

linux-hfsc may use queue_ids less than 61440. It has the following key-value pairs defined.

Minimum guaranteed bandwidth, in bit/s. Maximum allowed bandwidth, in bit/s. Optional. If specified, the queue's rate will not be allowed to exceed the specified value, even if excess bandwidth is available. If unspecified, defaults to no limit.
The overall purpose of these columns is described under Common Columns at the beginning of this document.

A port mirror within a .

A port mirror configures a bridge to send selected frames to special ``mirrored'' ports, in addition to their normal destinations. Mirroring traffic may also be referred to as SPAN or RSPAN, depending on how the mirrored traffic is sent.

When a packet enters an Open vSwitch bridge, it becomes eligible for mirroring based on its ingress port and VLAN. As the packet travels through the flow tables, each time it is output to a port, it becomes eligible for mirroring based on the egress port and VLAN. In Open vSwitch 2.5 and later, mirroring occurs just after a packet first becomes eligible, using the packet as it exists at that point; in Open vSwitch 2.4 and earlier, mirroring occurs only after a packet has traversed all the flow tables, using the original packet as it entered the bridge. This makes a difference only when the flow table modifies the packet: in Open vSwitch 2.4, the modifications are never visible to mirrors, whereas in Open vSwitch 2.5 and later modifications made before the first output that makes it eligible for mirroring to a particular destination are visible.

A packet that enters an Open vSwitch bridge is mirrored to a particular destination only once, even if it is eligible for multiple reasons. For example, a packet would be mirrored to a particular only once, even if it is selected for mirroring to that port by and in the same or different records.

Arbitrary identifier for the .

To be selected for mirroring, a given packet must enter or leave the bridge through a selected port and it must also be in one of the selected VLANs.

If true, every packet arriving or departing on any port is selected for mirroring. Ports on which departing packets are selected for mirroring. Ports on which arriving packets are selected for mirroring. VLANs on which packets are selected for mirroring. An empty set selects packets on all VLANs.

These columns are mutually exclusive. Exactly one of them must be nonempty.

Output port for selected packets, if nonempty.

Specifying a port for mirror output reserves that port exclusively for mirroring. No frames other than those selected for mirroring via this column will be forwarded to the port, and any frames received on the port will be discarded.

The output port may be any kind of port supported by Open vSwitch. It may be, for example, a physical port (sometimes called SPAN) or a GRE tunnel.

Output VLAN for selected packets, if nonempty.

The frames will be sent out all ports that trunk , as well as any ports with implicit VLAN . When a mirrored frame is sent out a trunk port, the frame's VLAN tag will be set to , replacing any existing tag; when it is sent out an implicit VLAN port, the frame will not be tagged. This type of mirroring is sometimes called RSPAN.

See the documentation for in the table for a list of destination MAC addresses which will not be mirrored to a VLAN to avoid confusing switches that interpret the protocols that they represent.

Please note: Mirroring to a VLAN can disrupt a network that contains unmanaged switches. Consider an unmanaged physical switch with two ports: port 1, connected to an end host, and port 2, connected to an Open vSwitch configured to mirror received packets into VLAN 123 on port 2. Suppose that the end host sends a packet on port 1 that the physical switch forwards to port 2. The Open vSwitch forwards this packet to its destination and then reflects it back on port 2 in VLAN 123. This reflected packet causes the unmanaged physical switch to replace the MAC learning table entry, which correctly pointed to port 1, with one that incorrectly points to port 2. Afterward, the physical switch will direct packets destined for the end host to the Open vSwitch on port 2, instead of to the end host on port 1, disrupting connectivity. If mirroring to a VLAN is desired in this scenario, then the physical switch must be replaced by one that learns Ethernet addresses on a per-VLAN basis. In addition, learning should be disabled on the VLAN containing mirrored traffic. If this is not done then intermediate switches will learn the MAC address of each end host from the mirrored traffic. If packets being sent to that end host are also mirrored, then they will be dropped since the switch will attempt to send them out the input port. Disabling learning for the VLAN will cause the switch to correctly send the packet out all ports configured for that VLAN. If Open vSwitch is being used as an intermediate switch, learning can be disabled by adding the mirrored VLAN to in the appropriate table or tables.

Mirroring to a GRE tunnel has fewer caveats than mirroring to a VLAN and should generally be preferred.

Key-value pairs that report mirror statistics. The update period is controlled by in the Open_vSwitch table.

Number of packets transmitted through this mirror. Number of bytes transmitted through this mirror.
The overall purpose of these columns is described under Common Columns at the beginning of this document.

An OpenFlow controller.

Open vSwitch supports two kinds of OpenFlow controllers:

Primary controllers

This is the kind of controller envisioned by the OpenFlow 1.0 specification. Usually, a primary controller implements a network policy by taking charge of the switch's flow table.

Open vSwitch initiates and maintains persistent connections to primary controllers, retrying the connection each time it fails or drops. The column in the table applies to primary controllers.

Open vSwitch permits a bridge to have any number of primary controllers. When multiple controllers are configured, Open vSwitch connects to all of them simultaneously. Because OpenFlow 1.0 does not specify how multiple controllers coordinate in interacting with a single switch, more than one primary controller should be specified only if the controllers are themselves designed to coordinate with each other. (The Nicira-defined NXT_ROLE OpenFlow vendor extension may be useful for this.)

Service controllers

These kinds of OpenFlow controller connections are intended for occasional support and maintenance use, e.g. with ovs-ofctl. Usually a service controller connects only briefly to inspect or modify some of a switch's state.

Open vSwitch listens for incoming connections from service controllers. The service controllers initiate and, if necessary, maintain the connections from their end. The column in the table does not apply to service controllers.

Open vSwitch supports configuring any number of service controllers.

The determines the type of controller.

Connection method for controller.

The following connection methods are currently supported for primary controllers:

ssl:ip[:port]

The specified SSL port on the host at the given ip, which must be expressed as an IP address (not a DNS name). The column in the table must point to a valid SSL configuration when this form is used.

If port is not specified, it defaults to 6653.

SSL support is an optional feature that is not always built as part of Open vSwitch.

tcp:ip[:port]

The specified TCP port on the host at the given ip, which must be expressed as an IP address (not a DNS name), where ip can be IPv4 or IPv6 address. If ip is an IPv6 address, wrap it in square brackets, e.g. tcp:[::1]:6653.

If port is not specified, it defaults to 6653.

The following connection methods are currently supported for service controllers:

pssl:[port][:ip]

Listens for SSL connections on the specified TCP port. If ip, which must be expressed as an IP address (not a DNS name), is specified, then connections are restricted to the specified local IP address (either IPv4 or IPv6). If ip is an IPv6 address, wrap it in square brackets, e.g. pssl:6653:[::1].

If port is not specified, it defaults to 6653. If ip is not specified then it listens only on IPv4 (but not IPv6) addresses. The column in the table must point to a valid SSL configuration when this form is used.

If port is not specified, it currently to 6653.

SSL support is an optional feature that is not always built as part of Open vSwitch.

ptcp:[port][:ip]

Listens for connections on the specified TCP port. If ip, which must be expressed as an IP address (not a DNS name), is specified, then connections are restricted to the specified local IP address (either IPv4 or IPv6). If ip is an IPv6 address, wrap it in square brackets, e.g. ptcp:6653:[::1]. If ip is not specified then it listens only on IPv4 addresses.

If port is not specified, it defaults to 6653.

When multiple controllers are configured for a single bridge, the values must be unique. Duplicate values yield unspecified results.

If it is specified, this setting must be one of the following strings that describes how Open vSwitch contacts this OpenFlow controller over the network:

in-band
In this mode, this controller's OpenFlow traffic travels over the bridge associated with the controller. With this setting, Open vSwitch allows traffic to and from the controller regardless of the contents of the OpenFlow flow table. (Otherwise, Open vSwitch would never be able to connect to the controller, because it did not have a flow to enable it.) This is the most common connection mode because it is not necessary to maintain two independent networks.
out-of-band
In this mode, OpenFlow traffic uses a control network separate from the bridge associated with this controller, that is, the bridge does not use any of its own network devices to communicate with the controller. The control network must be configured separately, before or after ovs-vswitchd is started.

If not specified, the default is implementation-specific.

Maximum number of milliseconds to wait between connection attempts. Default is implementation-specific. Maximum number of milliseconds of idle time on connection to controller before sending an inactivity probe message. If Open vSwitch does not communicate with the controller for the specified number of seconds, it will send a probe. If a response is not received for the same additional amount of time, Open vSwitch assumes the connection has been broken and attempts to reconnect. Default is implementation-specific. A value of 0 disables inactivity probes.

OpenFlow switches send certain messages to controllers spontanenously, that is, not in response to any request from the controller. These messages are called ``asynchronous messages.'' These columns allow asynchronous messages to be limited or disabled to ensure the best use of network resources.

The OpenFlow protocol enables asynchronous messages at time of connection establishment, which means that a controller can receive asynchronous messages, potentially many of them, even if it turns them off immediately after connecting. Set this column to false to change Open vSwitch behavior to disable, by default, all asynchronous messages. The controller can use the NXT_SET_ASYNC_CONFIG Nicira extension to OpenFlow to turn on any messages that it does want to receive, if any.

A switch can forward packets to a controller over the OpenFlow protocol. Forwarding packets this way at too high a rate can overwhelm a controller, frustrate use of the OpenFlow connection for other purposes, increase the latency of flow setup, and use an unreasonable amount of bandwidth. Therefore, Open vSwitch supports limiting the rate of packet forwarding to a controller.

There are two main reasons in OpenFlow for a packet to be sent to a controller: either the packet ``misses'' in the flow table, that is, there is no matching flow, or a flow table action says to send the packet to the controller. Open vSwitch limits the rate of each kind of packet separately at the configured rate. Therefore, the actual rate that packets are sent to the controller can be up to twice the configured rate, when packets are sent for both reasons.

This feature is specific to forwarding packets over an OpenFlow connection. It is not general-purpose QoS. See the table for quality of service configuration, and in the table for ingress policing configuration.

The maximum rate at which the switch will forward packets to the OpenFlow controller, in packets per second. If no value is specified, rate limiting is disabled.

When a high rate triggers rate-limiting, Open vSwitch queues packets to the controller for each port and transmits them to the controller at the configured rate. This value limits the number of queued packets. Ports on a bridge share the packet queue fairly.

This value has no effect unless is configured. The current default when this value is not specified is one-quarter of , meaning that queuing can delay forwarding a packet to the controller by up to 250 ms.

These values report the effects of rate limiting. Their values are relative to establishment of the most recent OpenFlow connection, or since rate limiting was enabled, whichever happened more recently. Each consists of two values, one with TYPE replaced by miss for rate limiting flow table misses, and the other with TYPE replaced by action for rate limiting packets sent by OpenFlow actions.

These statistics are reported only when controller rate limiting is enabled.

Number of packets sent directly to the controller, without queuing, because the rate did not exceed the configured maximum. Number of packets added to the queue to send later. Number of packets added to the queue that were later dropped due to overflow. This value is less than or equal to . Number of packets currently queued. The other statistics increase monotonically, but this one fluctuates between 0 and the as conditions change.

These values are considered only in in-band control mode (see ).

When multiple controllers are configured on a single bridge, there should be only one set of unique values in these columns. If different values are set for these columns in different controllers, the effect is unspecified.

The IP address to configure on the local port, e.g. 192.168.0.123. If this value is unset, then and are ignored. The IP netmask to configure on the local port, e.g. 255.255.255.0. If is set but this value is unset, then the default is chosen based on whether the IP address is class A, B, or C. The IP address of the gateway to configure on the local port, as a string, e.g. 192.168.0.1. Leave this column unset if this network has no gateway.
true if currently connected to this controller, false otherwise.

The level of authority this controller has on the associated bridge. Possible values are:

other
Allows the controller access to all OpenFlow features.
master
Equivalent to other, except that there may be at most one master controller at a time. When a controller configures itself as master, any existing master is demoted to the slave role.
slave
Allows the controller read-only access to OpenFlow features. Attempts to modify the flow table will be rejected with an error. Slave controllers do not receive OFPT_PACKET_IN or OFPT_FLOW_REMOVED messages, but they do receive OFPT_PORT_STATUS messages.
A human-readable description of the last error on the connection to the controller; i.e. strerror(errno). This key will exist only if an error has occurred.

The state of the connection to the controller:

VOID
Connection is disabled.
BACKOFF
Attempting to reconnect at an increasing period.
CONNECTING
Attempting to connect.
ACTIVE
Connected, remote host responsive.
IDLE
Connection is idle. Waiting for response to keep-alive.

These values may change in the future. They are provided only for human consumption.

The amount of time since this controller last successfully connected to the switch (in seconds). Value is empty if controller has never successfully connected. The amount of time since this controller last disconnected from the switch (in seconds). Value is empty if controller has never disconnected.

Additional configuration for a connection between the controller and the Open vSwitch.

The Differentiated Service Code Point (DSCP) is specified using 6 bits in the Type of Service (TOS) field in the IP header. DSCP provides a mechanism to classify the network traffic and provide Quality of Service (QoS) on IP networks. The DSCP value specified here is used when establishing the connection between the controller and the Open vSwitch. If no value is specified, a default value of 48 is chosen. Valid DSCP values must be in the range 0 to 63.
The overall purpose of these columns is described under Common Columns at the beginning of this document.

Configuration for a database connection to an Open vSwitch database (OVSDB) client.

This table primarily configures the Open vSwitch database (ovsdb-server), not the Open vSwitch switch (ovs-vswitchd). The switch does read the table to determine what connections should be treated as in-band.

The Open vSwitch database server can initiate and maintain active connections to remote clients. It can also listen for database connections.

Connection method for managers.

The following connection methods are currently supported:

ssl:ip[:port]

The specified SSL port on the host at the given ip, which must be expressed as an IP address (not a DNS name). The column in the table must point to a valid SSL configuration when this form is used.

If port is not specified, it defaults to 6640.

SSL support is an optional feature that is not always built as part of Open vSwitch.

tcp:ip[:port]

The specified TCP port on the host at the given ip, which must be expressed as an IP address (not a DNS name), where ip can be IPv4 or IPv6 address. If ip is an IPv6 address, wrap it in square brackets, e.g. tcp:[::1]:6640.

If port is not specified, it defaults to 6640.

pssl:[port][:ip]

Listens for SSL connections on the specified TCP port. Specify 0 for port to have the kernel automatically choose an available port. If ip, which must be expressed as an IP address (not a DNS name), is specified, then connections are restricted to the specified local IP address (either IPv4 or IPv6 address). If ip is an IPv6 address, wrap in square brackets, e.g. pssl:6640:[::1]. If ip is not specified then it listens only on IPv4 (but not IPv6) addresses. The column in the table must point to a valid SSL configuration when this form is used.

If port is not specified, it defaults to 6640.

SSL support is an optional feature that is not always built as part of Open vSwitch.

ptcp:[port][:ip]

Listens for connections on the specified TCP port. Specify 0 for port to have the kernel automatically choose an available port. If ip, which must be expressed as an IP address (not a DNS name), is specified, then connections are restricted to the specified local IP address (either IPv4 or IPv6 address). If ip is an IPv6 address, wrap it in square brackets, e.g. ptcp:6640:[::1]. If ip is not specified then it listens only on IPv4 addresses.

If port is not specified, it defaults to 6640.

When multiple managers are configured, the values must be unique. Duplicate values yield unspecified results.

If it is specified, this setting must be one of the following strings that describes how Open vSwitch contacts this OVSDB client over the network:

in-band
In this mode, this connection's traffic travels over a bridge managed by Open vSwitch. With this setting, Open vSwitch allows traffic to and from the client regardless of the contents of the OpenFlow flow table. (Otherwise, Open vSwitch would never be able to connect to the client, because it did not have a flow to enable it.) This is the most common connection mode because it is not necessary to maintain two independent networks.
out-of-band
In this mode, the client's traffic uses a control network separate from that managed by Open vSwitch, that is, Open vSwitch does not use any of its own network devices to communicate with the client. The control network must be configured separately, before or after ovs-vswitchd is started.

If not specified, the default is implementation-specific.

Maximum number of milliseconds to wait between connection attempts. Default is implementation-specific. Maximum number of milliseconds of idle time on connection to the client before sending an inactivity probe message. If Open vSwitch does not communicate with the client for the specified number of seconds, it will send a probe. If a response is not received for the same additional amount of time, Open vSwitch assumes the connection has been broken and attempts to reconnect. Default is implementation-specific. A value of 0 disables inactivity probes. true if currently connected to this manager, false otherwise. A human-readable description of the last error on the connection to the manager; i.e. strerror(errno). This key will exist only if an error has occurred.

The state of the connection to the manager:

VOID
Connection is disabled.
BACKOFF
Attempting to reconnect at an increasing period.
CONNECTING
Attempting to connect.
ACTIVE
Connected, remote host responsive.
IDLE
Connection is idle. Waiting for response to keep-alive.

These values may change in the future. They are provided only for human consumption.

The amount of time since this manager last successfully connected to the database (in seconds). Value is empty if manager has never successfully connected. The amount of time since this manager last disconnected from the database (in seconds). Value is empty if manager has never disconnected. Space-separated list of the names of OVSDB locks that the connection holds. Omitted if the connection does not hold any locks. Space-separated list of the names of OVSDB locks that the connection is currently waiting to acquire. Omitted if the connection is not waiting for any locks. Space-separated list of the names of OVSDB locks that the connection has had stolen by another OVSDB client. Omitted if no locks have been stolen from this connection.

When specifies a connection method that listens for inbound connections (e.g. ptcp: or pssl:) and more than one connection is actually active, the value is the number of active connections. Otherwise, this key-value pair is omitted.

When multiple connections are active, status columns and key-value pairs (other than this one) report the status of one arbitrarily chosen connection.

When is ptcp: or pssl:, this is the TCP port on which the OVSDB server is listening. (This is is particularly useful when specifies a port of 0, allowing the kernel to choose any available port.)

Additional configuration for a connection between the manager and the Open vSwitch Database.

The Differentiated Service Code Point (DSCP) is specified using 6 bits in the Type of Service (TOS) field in the IP header. DSCP provides a mechanism to classify the network traffic and provide Quality of Service (QoS) on IP networks. The DSCP value specified here is used when establishing the connection between the manager and the Open vSwitch. If no value is specified, a default value of 48 is chosen. Valid DSCP values must be in the range 0 to 63.
The overall purpose of these columns is described under Common Columns at the beginning of this document.
A NetFlow target. NetFlow is a protocol that exports a number of details about terminating IP flows, such as the principals involved and duration. NetFlow targets in the form ip:port. The ip must be specified numerically, not as a DNS name. Engine ID to use in NetFlow messages. Defaults to datapath index if not specified. Engine type to use in NetFlow messages. Defaults to datapath index if not specified.

The interval at which NetFlow records are sent for flows that are still active, in seconds. A value of 0 requests the default timeout (currently 600 seconds); a value of -1 disables active timeouts.

The NetFlow passive timeout, for flows that become inactive, is not configurable. It will vary depending on the Open vSwitch version, the forms and contents of the OpenFlow flow tables, CPU and memory usage, and network activity. A typical passive timeout is about a second.

If this column's value is false, the ingress and egress interface fields of NetFlow flow records are derived from OpenFlow port numbers. When it is true, the 7 most significant bits of these fields will be replaced by the least significant 7 bits of the engine id. This is useful because many NetFlow collectors do not expect multiple switches to be sending messages from the same host, so they do not store the engine information which could be used to disambiguate the traffic.

When this option is enabled, a maximum of 508 ports are supported.

The overall purpose of these columns is described under Common Columns at the beginning of this document.
SSL configuration for an Open_vSwitch. Name of a PEM file containing the private key used as the switch's identity for SSL connections to the controller. Name of a PEM file containing a certificate, signed by the certificate authority (CA) used by the controller and manager, that certifies the switch's private key, identifying a trustworthy switch. Name of a PEM file containing the CA certificate used to verify that the switch is connected to a trustworthy controller. If set to true, then Open vSwitch will attempt to obtain the CA certificate from the controller on its first SSL connection and save it to the named PEM file. If it is successful, it will immediately drop the connection and reconnect, and from then on all SSL connections must be authenticated by a certificate signed by the CA certificate thus obtained. This option exposes the SSL connection to a man-in-the-middle attack obtaining the initial CA certificate. It may still be useful for bootstrapping. The overall purpose of these columns is described under Common Columns at the beginning of this document.

A set of sFlow(R) targets. sFlow is a protocol for remote monitoring of switches.

Name of the network device whose IP address should be reported as the ``agent address'' to collectors. If not specified, the agent device is figured from the first target address and the routing table. If the routing table does not contain a route to the target, the IP address defaults to the in the collector's . If an agent IP address cannot be determined any of these ways, sFlow is disabled. Number of bytes of a sampled packet to send to the collector. If not specified, the default is 128 bytes. Polling rate in seconds to send port statistics to the collector. If not specified, defaults to 30 seconds. Rate at which packets should be sampled and sent to the collector. If not specified, defaults to 400, which means one out of 400 packets, on average, will be sent to the collector. sFlow targets in the form ip:port. The overall purpose of these columns is described under Common Columns at the beginning of this document.

Configuration for sending packets to IPFIX collectors.

IPFIX is a protocol that exports a number of details about flows. The IPFIX implementation in Open vSwitch samples packets at a configurable rate, extracts flow information from those packets, optionally caches and aggregates the flow information, and sends the result to one or more collectors.

IPFIX in Open vSwitch can be configured two different ways:

  • With per-bridge sampling, Open vSwitch performs IPFIX sampling automatically on all packets that pass through a bridge. To configure per-bridge sampling, create an record and point a table's column to it. The table is not used for per-bridge sampling.
  • With flow-based sampling, sample actions in the OpenFlow flow table drive IPFIX sampling. See ovs-ofctl(8) for a description of the sample action.

    Flow-based sampling also requires database configuration: create a record that describes the IPFIX configuration and a record that points to the whose flow table holds the sample actions and to record. The in the table is not used for flow-based sampling.

IPFIX target collectors in the form ip:port. The maximum period in seconds for which an IPFIX flow record is cached and aggregated before being sent. If not specified, defaults to 0. If 0, caching is disabled. The maximum number of IPFIX flow records that can be cached at a time. If not specified, defaults to 0. If 0, caching is disabled.

These values affect only per-bridge sampling. See above for a description of the differences between per-bridge and flow-based sampling.

The rate at which packets should be sampled and sent to each target collector. If not specified, defaults to 400, which means one out of 400 packets, on average, will be sent to each target collector. The IPFIX Observation Domain ID sent in each IPFIX packet. If not specified, defaults to 0. The IPFIX Observation Point ID sent in each IPFIX flow record. If not specified, defaults to 0.

Set to true to enable sampling and reporting tunnel header 7-tuples in IPFIX flow records. Tunnel sampling is disabled by default.

The following enterprise entities report the sampled tunnel info:

tunnelType:

ID: 891, and enterprise ID 6876 (VMware).

type: unsigned 8-bit integer.

data type semantics: identifier.

description: Identifier of the layer 2 network overlay network encapsulation type: 0x01 VxLAN, 0x02 GRE, 0x03 LISP, 0x05 IPsec+GRE, 0x07 GENEVE.

tunnelKey:

ID: 892, and enterprise ID 6876 (VMware).

type: variable-length octetarray.

data type semantics: identifier.

description: Key which is used for identifying an individual traffic flow within a VxLAN (24-bit VNI), GENEVE (24-bit VNI), GRE (32-bit key), or LISP (24-bit instance ID) tunnel. The key is encoded in this octetarray as a 3-, 4-, or 8-byte integer ID in network byte order.

tunnelSourceIPv4Address:

ID: 893, and enterprise ID 6876 (VMware).

type: unsigned 32-bit integer.

data type semantics: identifier.

description: The IPv4 source address in the tunnel IP packet header.

tunnelDestinationIPv4Address:

ID: 894, and enterprise ID 6876 (VMware).

type: unsigned 32-bit integer.

data type semantics: identifier.

description: The IPv4 destination address in the tunnel IP packet header.

tunnelProtocolIdentifier:

ID: 895, and enterprise ID 6876 (VMware).

type: unsigned 8-bit integer.

data type semantics: identifier.

description: The value of the protocol number in the tunnel IP packet header. The protocol number identifies the tunnel IP packet payload type.

tunnelSourceTransportPort:

ID: 896, and enterprise ID 6876 (VMware).

type: unsigned 16-bit integer.

data type semantics: identifier.

description: The source port identifier in the tunnel transport header. For the transport protocols UDP, TCP, and SCTP, this is the source port number given in the respective header.

tunnelDestinationTransportPort:

ID: 897, and enterprise ID 6876 (VMware).

type: unsigned 16-bit integer.

data type semantics: identifier.

description: The destination port identifier in the tunnel transport header. For the transport protocols UDP, TCP, and SCTP, this is the destination port number given in the respective header.

By default, Open vSwitch samples and reports flows at bridge port input in IPFIX flow records. Set this column to false to disable input sampling. By default, Open vSwitch samples and reports flows at bridge port output in IPFIX flow records. Set this column to false to disable output sampling.
The overall purpose of these columns is described under Common Columns at the beginning of this document.

A set of IPFIX collectors of packet samples generated by OpenFlow sample actions. This table is used only for IPFIX flow-based sampling, not for per-bridge sampling (see the table for a description of the two forms).

The ID of this collector set, unique among the bridge's collector sets, to be used as the collector_set_id in OpenFlow sample actions. The bridge into which OpenFlow sample actions can be added to send packet samples to this set of IPFIX collectors. Configuration of the set of IPFIX collectors to send one flow record per sampled packet to. The overall purpose of these columns is described under Common Columns at the beginning of this document.

Auto Attach configuration within a bridge. The IETF Auto-Attach SPBM draft standard describes a compact method of using IEEE 802.1AB Link Layer Discovery Protocol (LLDP) together with a IEEE 802.1aq Shortest Path Bridging (SPB) network to automatically attach network devices to individual services in a SPB network. The intent here is to allow network applications and devices using OVS to be able to easily take advantage of features offered by industry standard SPB networks.

Auto Attach (AA) uses LLDP to communicate between a directly connected Auto Attach Client (AAC) and Auto Attach Server (AAS). The LLDP protocol is extended to add two new Type-Length-Value tuples (TLVs). The first new TLV supports the ongoing discovery of directly connected AA correspondents. Auto Attach operates by regularly transmitting AA discovery TLVs between the AA client and AA server. By exchanging these discovery messages, both the AAC and AAS learn the system name and system description of their peer. In the OVS context, OVS operates as the AA client and the AA server resides on a switch at the edge of the SPB network.

Once AA discovery has been completed the AAC then uses the second new TLV to deliver identifier mappings from the AAC to the AAS. A primary feature of Auto Attach is to facilitate the mapping of VLANs defined outside the SPB network onto service ids (ISIDs) defined within the SPM network. By doing so individual external VLANs can be mapped onto specific SPB network services. These VLAN id to ISID mappings can be configured and managed locally using new options added to the ovs-vsctl command.

The Auto Attach OVS feature does not provide a full implementation of the LLDP protocol. Support for the mandatory TLVs as defined by the LLDP standard and support for the AA TLV extensions is provided. LLDP protocol support in OVS can be enabled or disabled on a port by port basis. LLDP support is disabled by default.

The system_name string is exported in LLDP messages. It should uniquely identify the bridge in the network. The system_description string is exported in LLDP messages. It should describe the type of software and hardware. A mapping from SPB network Individual Service Identifier (ISID) to VLAN id.
openvswitch-2.5.0/vswitchd/PaxHeaders.69223/system-stats.h0000644000000000000000000000013112631270604020315 xustar0030 mtime=1449488772.015992878 30 atime=1456592664.474974123 29 ctime=1456594661.10532716 openvswitch-2.5.0/vswitchd/system-stats.h0000664000175000017500000000150212631270604022004 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2010, 2012 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef VSWITCHD_SYSTEM_STATS #define VSWITCHD_SYSTEM_STATS 1 #include void system_stats_enable(bool enable); struct smap *system_stats_run(void); void system_stats_wait(void); #endif /* vswitchd/system-stats.h */ openvswitch-2.5.0/vswitchd/PaxHeaders.69223/ovs-vswitchd.8.in0000644000000000000000000000013212664352753020637 xustar0030 mtime=1456592363.502623465 30 atime=1456592368.230817659 30 ctime=1456594659.745269986 openvswitch-2.5.0/vswitchd/ovs-vswitchd.8.in0000664000175000017500000003226212664352753022334 0ustar00jpettitjpettit00000000000000.\" -*- nroff -*- .de IQ . br . ns . IP "\\$1" .. .TH ovs\-vswitchd 8 "@VERSION@" "Open vSwitch" "Open vSwitch Manual" .\" This program's name: .ds PN ovs\-vswitchd . .SH NAME ovs\-vswitchd \- Open vSwitch daemon . .SH SYNOPSIS \fBovs\-vswitchd \fR[\fIdatabase\fR] . .SH DESCRIPTION A daemon that manages and controls any number of Open vSwitch switches on the local machine. .PP The \fIdatabase\fR argument specifies how \fBovs\-vswitchd\fR connects to \fBovsdb\-server\fR. The default is \fBunix:@RUNDIR@/db.sock\fR. The following forms are accepted: .so ovsdb/remote-active.man .so ovsdb/remote-passive.man .PP \fBovs\-vswitchd\fR retrieves its configuration from \fIdatabase\fR at startup. It sets up Open vSwitch datapaths and then operates switching across each bridge described in its configuration files. As the database changes, \fBovs\-vswitchd\fR automatically updates its configuration to match. .PP \fBovs\-vswitchd\fR switches may be configured with any of the following features: . .IP \(bu L2 switching with MAC learning. . .IP \(bu NIC bonding with automatic fail-over and source MAC-based TX load balancing ("SLB"). . .IP \(bu 802.1Q VLAN support. . .IP \(bu Port mirroring, with optional VLAN tagging. . .IP \(bu NetFlow v5 flow logging. . .IP \(bu sFlow(R) monitoring. . .IP \(bu Connectivity to an external OpenFlow controller, such as NOX. . .PP Only a single instance of \fBovs\-vswitchd\fR is intended to run at a time. A single \fBovs\-vswitchd\fR can manage any number of switch instances, up to the maximum number of supported Open vSwitch datapaths. .PP \fBovs\-vswitchd\fR does all the necessary management of Open vSwitch datapaths itself. Thus, external tools, such \fBovs\-dpctl\fR(8), are not needed for managing datapaths in conjunction with \fBovs\-vswitchd\fR, and their use to modify datapaths when \fBovs\-vswitchd\fR is running can interfere with its operation. (\fBovs\-dpctl\fR may still be useful for diagnostics.) .PP An Open vSwitch datapath kernel module must be loaded for \fBovs\-vswitchd\fR to be useful. Please refer to the \fBINSTALL.Linux\fR file included in the Open vSwitch distribution for instructions on how to build and load the Open vSwitch kernel module. .PP .SH OPTIONS .IP "\fB\-\-mlockall\fR" Causes \fBovs\-vswitchd\fR to call the \fBmlockall()\fR function, to attempt to lock all of its process memory into physical RAM, preventing the kernel from paging any of its memory to disk. This helps to avoid networking interruptions due to system memory pressure. .IP Some systems do not support \fBmlockall()\fR at all, and other systems only allow privileged users, such as the superuser, to use it. \fBovs\-vswitchd\fR emits a log message if \fBmlockall()\fR is unavailable or unsuccessful. . .SS "DPDK Options" .IP "\fB\-\-dpdk\fR" Initialize \fBovs\-vswitchd\fR DPDK datapath. Refer to INSTALL.DPDK for details. .SS "Daemon Options" .ds DD \ \fBovs\-vswitchd\fR detaches only after it has connected to the \ database, retrieved the initial configuration, and set up that \ configuration. .so lib/daemon.man .SS "Service Options" .so lib/service.man .SS "Public Key Infrastructure Options" .so lib/ssl.man .so lib/ssl-bootstrap.man .SS "Logging Options" .so lib/vlog.man .SS "Other Options" .so lib/unixctl.man .so lib/common.man . .SH "RUNTIME MANAGEMENT COMMANDS" \fBovs\-appctl\fR(8) can send commands to a running \fBovs\-vswitchd\fR process. The currently supported commands are described below. The command descriptions assume an understanding of how to configure Open vSwitch. .SS "GENERAL COMMANDS" .IP "\fBexit\fR" Causes \fBovs\-vswitchd\fR to gracefully terminate. .IP "\fBqos/show\fR \fIinterface\fR" Queries the kernel for Quality of Service configuration and statistics associated with the given \fIinterface\fR. .IP "\fBbfd/show\fR [\fIinterface\fR]" Displays detailed information about Bidirectional Forwarding Detection configured on \fIinterface\fR. If \fIinterface\fR is not specified, then displays detailed information about all interfaces with BFD enabled. .IP "\fBbfd/set-forwarding\fR [\fIinterface\fR] \fIstatus\fR" Force the fault status of the BFD module on \fIinterface\fR (or all interfaces if none is given) to be \fIstatus\fR. \fIstatus\fR can be "true", "false", or "normal" which reverts to the standard behavior. .IP "\fBcfm/show\fR [\fIinterface\fR]" Displays detailed information about Connectivity Fault Management configured on \fIinterface\fR. If \fIinterface\fR is not specified, then displays detailed information about all interfaces with CFM enabled. .IP "\fBcfm/set-fault\fR [\fIinterface\fR] \fIstatus\fR" Force the fault status of the CFM module on \fIinterface\fR (or all interfaces if none is given) to be \fIstatus\fR. \fIstatus\fR can be "true", "false", or "normal" which reverts to the standard behavior. .IP "\fBstp/tcn\fR [\fIbridge\fR]" Forces a topology change event on \fIbridge\fR if it's running STP. This may cause it to send Topology Change Notifications to its peers and flush its MAC table.. If no \fIbridge\fR is given, forces a topology change event on all bridges. .SS "BRIDGE COMMANDS" These commands manage bridges. .IP "\fBfdb/flush\fR [\fIbridge\fR]" Flushes \fIbridge\fR MAC address learning table, or all learning tables if no \fIbridge\fR is given. .IP "\fBfdb/show\fR \fIbridge\fR" Lists each MAC address/VLAN pair learned by the specified \fIbridge\fR, along with the port on which it was learned and the age of the entry, in seconds. .IP "\fBmdb/flush\fR [\fIbridge\fR]" Flushes \fIbridge\fR multicast snooping table, or all snooping tables if no \fIbridge\fR is given. .IP "\fBmdb/show\fR \fIbridge\fR" Lists each multicast group/VLAN pair learned by the specified \fIbridge\fR, along with the port on which it was learned and the age of the entry, in seconds. .IP "\fBbridge/reconnect\fR [\fIbridge\fR]" Makes \fIbridge\fR drop all of its OpenFlow controller connections and reconnect. If \fIbridge\fR is not specified, then all bridges drop their controller connections and reconnect. .IP This command might be useful for debugging OpenFlow controller issues. . .IP "\fBbridge/dump\-flows\fR \fIbridge\fR" Lists all flows in \fIbridge\fR, including those normally hidden to commands such as \fBovs\-ofctl dump\-flows\fR. Flows set up by mechanisms such as in-band control and fail-open are hidden from the controller since it is not allowed to modify or override them. .SS "BOND COMMANDS" These commands manage bonded ports on an Open vSwitch's bridges. To understand some of these commands, it is important to understand a detail of the bonding implementation called ``source load balancing'' (SLB). Instead of directly assigning Ethernet source addresses to slaves, the bonding implementation computes a function that maps an 48-bit Ethernet source addresses into an 8-bit value (a ``MAC hash'' value). All of the Ethernet addresses that map to a single 8-bit value are then assigned to a single slave. .IP "\fBbond/list\fR" Lists all of the bonds, and their slaves, on each bridge. . .IP "\fBbond/show\fR [\fIport\fR]" Lists all of the bond-specific information (updelay, downdelay, time until the next rebalance) about the given bonded \fIport\fR, or all bonded ports if no \fIport\fR is given. Also lists information about each slave: whether it is enabled or disabled, the time to completion of an updelay or downdelay if one is in progress, whether it is the active slave, the hashes assigned to the slave. Any LACP information related to this bond may be found using the \fBlacp/show\fR command. . .IP "\fBbond/migrate\fR \fIport\fR \fIhash\fR \fIslave\fR" Only valid for SLB bonds. Assigns a given MAC hash to a new slave. \fIport\fR specifies the bond port, \fIhash\fR the MAC hash to be migrated (as a decimal number between 0 and 255), and \fIslave\fR the new slave to be assigned. .IP The reassignment is not permanent: rebalancing or fail-over will cause the MAC hash to be shifted to a new slave in the usual manner. .IP A MAC hash cannot be migrated to a disabled slave. .IP "\fBbond/set\-active\-slave\fR \fIport\fR \fIslave\fR" Sets \fIslave\fR as the active slave on \fIport\fR. \fIslave\fR must currently be enabled. .IP The setting is not permanent: a new active slave will be selected if \fIslave\fR becomes disabled. .IP "\fBbond/enable\-slave\fR \fIport\fR \fIslave\fR" .IQ "\fBbond/disable\-slave\fR \fIport\fR \fIslave\fR" Enables (or disables) \fIslave\fR on the given bond \fIport\fR, skipping any updelay (or downdelay). .IP This setting is not permanent: it persists only until the carrier status of \fIslave\fR changes. .IP "\fBbond/hash\fR \fImac\fR [\fIvlan\fR] [\fIbasis\fR]" Returns the hash value which would be used for \fImac\fR with \fIvlan\fR and \fIbasis\fR if specified. . .IP "\fBlacp/show\fR [\fIport\fR]" Lists all of the LACP related information about the given \fIport\fR: active or passive, aggregation key, system id, and system priority. Also lists information about each slave: whether it is enabled or disabled, whether it is attached or detached, port id and priority, actor information, and partner information. If \fIport\fR is not specified, then displays detailed information about all interfaces with CFM enabled. .SS "DPCTL DATAPATH DEBUGGING COMMANDS" The primary way to configure \fBovs\-vswitchd\fR is through the Open vSwitch database, e.g. using \fBovs\-vsctl\fR(8). These commands provide a debugging interface for managing datapaths. They implement the same features (and syntax) as \fBovs\-dpctl\fR(8). Unlike \fBovs\-dpctl\fR(8), these commands work with datapaths that are integrated into \fBovs\-vswitchd\fR (e.g. the \fBnetdev\fR datapath type). .PP . .ds DX \fBdpctl/\fR .de DO \\$2 \\$1 \\$3 .. .so lib/dpctl.man . .SS "DPIF-NETDEV COMMANDS" These commands are used to expose internal information (mostly statistics) about the ``dpif-netdev'' userspace datapath. If there is only one datapath (as is often the case, unless \fBdpctl/\fR commands are used), the \fIdp\fR argument can be omitted. .IP "\fBdpif-netdev/pmd-stats-show\fR [\fIdp\fR]" Shows performance statistics for each pmd thread of the datapath \fIdp\fR. The special thread ``main'' sums up the statistics of every non pmd thread. The sum of ``emc hits'', ``masked hits'' and ``miss'' is the number of packets received by the datapath. Cycles are counted using the TSC or similar facilities (when available on the platform). To reset these counters use \fBdpif-netdev/pmd-stats-clear\fR. The duration of one cycle depends on the measuring infrastructure. .IP "\fBdpif-netdev/pmd-stats-clear\fR [\fIdp\fR]" Resets to zero the per pmd thread performance numbers shown by the \fBdpif-netdev/pmd-stats-show\fR command. It will NOT reset datapath or bridge statistics, only the values shown by the above command. . .so ofproto/ofproto-dpif-unixctl.man .so ofproto/ofproto-unixctl.man .so lib/vlog-unixctl.man .so lib/memory-unixctl.man .so lib/coverage-unixctl.man .so ofproto/ofproto-tnl-unixctl.man . .SH "OPENFLOW IMPLEMENTATION" . .PP This section documents aspects of OpenFlow for which the OpenFlow specification requires documentation. . .SS "Packet buffering." The OpenFlow specification, version 1.2, says: . .IP Switches that implement buffering are expected to expose, through documentation, both the amount of available buffering, and the length of time before buffers may be reused. . .PP Open vSwitch maintains a separate set of 256 packet buffers for each OpenFlow connection. Any given packet buffer is preserved until it is referenced by an \fBOFPT_FLOW_MOD\fR or \fBOFPT_PACKET_OUT\fR request or for 5 seconds, whichever comes first. . .SH "LIMITS" . .PP We believe these limits to be accurate as of this writing. These limits assume the use of the Linux kernel datapath. . .IP \(bu \fBovs\-vswitchd\fR started through \fBovs\-ctl\fR(8) provides a limit of 65535 file descriptors. The limits on the number of bridges and ports is decided by the availability of file descriptors. With the Linux kernel datapath, creation of a single bridge consumes three file descriptors and adding a port consumes "n-handler-threads" file descriptors per bridge port. Performance will degrade beyond 1,024 ports per bridge due to fixed hash table sizing. Other platforms may have different limitations. . .IP \(bu 2,048 MAC learning entries per bridge, by default. (This is configurable via \fBother\-config:mac\-table\-size\fR in the \fBBridge\fR table. See \fBovs\-vswitchd.conf.db\fR(5) for details.) . .IP \(bu Kernel flows are limited only by memory available to the kernel. Performance will degrade beyond 1,048,576 kernel flows per bridge with a 32-bit kernel, beyond 262,144 with a 64-bit kernel. (\fBovs\-vswitchd\fR should never install anywhere near that many flows.) . .IP \(bu OpenFlow flows are limited only by available memory. Performance is linear in the number of unique wildcard patterns. That is, an OpenFlow table that contains many flows that all match on the same fields in the same way has a constant-time lookup, but a table that contains many flows that match on different fields requires lookup time linear in the number of flows. . .IP \(bu 255 ports per bridge participating in 802.1D Spanning Tree Protocol. . .IP \(bu 32 mirrors per bridge. . .IP \(bu 15 bytes for the name of a port. (This is a Linux kernel limitation.) . .SH "SEE ALSO" .BR ovs\-appctl (8), .BR ovsdb\-server (1), \fBINSTALL.Linux\fR in the Open vSwitch distribution. openvswitch-2.5.0/vswitchd/PaxHeaders.69223/xenserver.h0000644000000000000000000000013212130751561017657 xustar0030 mtime=1365496689.542878595 30 atime=1456592664.514975763 30 ctime=1456594661.109327329 openvswitch-2.5.0/vswitchd/xenserver.h0000664000175000017500000000133112130751561021345 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2009 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef VSWITCHD_XENSERVER_H #define VSWITCHD_XENSERVER_H 1 const char *xenserver_get_host_uuid(void); #endif /* xenserver.h */ openvswitch-2.5.0/vswitchd/PaxHeaders.69223/bridge.h0000644000000000000000000000013212631676263017105 xustar0030 mtime=1449622707.590461115 30 atime=1456592664.266965594 30 ctime=1456594661.101326991 openvswitch-2.5.0/vswitchd/bridge.h0000664000175000017500000000156412631676263020603 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2008, 2009, 2010, 2011, 2012, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef VSWITCHD_BRIDGE_H #define VSWITCHD_BRIDGE_H 1 struct simap; void bridge_init(const char *remote); void bridge_exit(void); void bridge_run(void); void bridge_wait(void); void bridge_get_memory_usage(struct simap *usage); #endif /* bridge.h */ openvswitch-2.5.0/vswitchd/PaxHeaders.69223/system-stats.c0000644000000000000000000000013112631676263020323 xustar0030 mtime=1449622707.594461255 30 atime=1456592664.506975435 29 ctime=1456594661.10532716 openvswitch-2.5.0/vswitchd/system-stats.c0000664000175000017500000004337512631676263022030 0ustar00jpettitjpettit00000000000000/* Copyright (c) 2010, 2012, 2013, 2014 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include "system-stats.h" #include #include #include #if HAVE_MNTENT_H #include #endif #include #include #include #if HAVE_SYS_STATVFS_H #include #endif #include #include "daemon.h" #include "dirs.h" #include "dynamic-string.h" #include "json.h" #include "latch.h" #include "ofpbuf.h" #include "ovs-thread.h" #include "poll-loop.h" #include "shash.h" #include "smap.h" #include "timeval.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(system_stats); /* #ifdefs make it a pain to maintain code: you have to try to build both ways. * Thus, this file tries to compile as much of the code as possible regardless * of the target, by writing "if (LINUX)" instead of "#ifdef __linux__" where * this is possible. */ #ifdef __linux__ #define LINUX 1 #include #else #define LINUX 0 #endif static void get_cpu_cores(struct smap *stats) { long int n_cores = count_cpu_cores(); if (n_cores > 0) { smap_add_format(stats, "cpu", "%ld", n_cores); } } static void get_load_average(struct smap *stats OVS_UNUSED) { #if HAVE_GETLOADAVG double loadavg[3]; if (getloadavg(loadavg, 3) == 3) { smap_add_format(stats, "load_average", "%.2f,%.2f,%.2f", loadavg[0], loadavg[1], loadavg[2]); } #endif } static unsigned int get_page_size(void) { static unsigned int cached; if (!cached) { #ifndef _WIN32 long int value = sysconf(_SC_PAGESIZE); #else long int value; SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); value = sysinfo.dwPageSize; #endif if (value >= 0) { cached = value; } } return cached; } static void get_memory_stats(struct smap *stats) { if (!LINUX) { unsigned int pagesize = get_page_size(); #ifdef _SC_PHYS_PAGES long int phys_pages = sysconf(_SC_PHYS_PAGES); #else long int phys_pages = 0; #endif #ifdef _SC_AVPHYS_PAGES long int avphys_pages = sysconf(_SC_AVPHYS_PAGES); #else long int avphys_pages = 0; #endif int mem_total, mem_used; #ifndef _WIN32 if (pagesize <= 0 || phys_pages <= 0 || avphys_pages <= 0) { return; } mem_total = phys_pages * (pagesize / 1024); mem_used = (phys_pages - avphys_pages) * (pagesize / 1024); #else MEMORYSTATUS memory_status; GlobalMemoryStatus(&memory_status); mem_total = memory_status.dwTotalPhys; mem_used = memory_status.dwTotalPhys - memory_status.dwAvailPhys; #endif smap_add_format(stats, "memory", "%d,%d", mem_total, mem_used); } else { static const char file_name[] = "/proc/meminfo"; int mem_used, mem_cache, swap_used; int mem_free = 0; int buffers = 0; int cached = 0; int swap_free = 0; int mem_total = 0; int swap_total = 0; struct shash dict; char line[128]; FILE *stream; stream = fopen(file_name, "r"); if (!stream) { VLOG_WARN_ONCE("%s: open failed (%s)", file_name, ovs_strerror(errno)); return; } shash_init(&dict); shash_add(&dict, "MemTotal", &mem_total); shash_add(&dict, "MemFree", &mem_free); shash_add(&dict, "Buffers", &buffers); shash_add(&dict, "Cached", &cached); shash_add(&dict, "SwapTotal", &swap_total); shash_add(&dict, "SwapFree", &swap_free); while (fgets(line, sizeof line, stream)) { char key[16]; int value; if (ovs_scan(line, "%15[^:]: %u", key, &value)) { int *valuep = shash_find_data(&dict, key); if (valuep) { *valuep = value; } } } fclose(stream); shash_destroy(&dict); mem_used = mem_total - mem_free; mem_cache = buffers + cached; swap_used = swap_total - swap_free; smap_add_format(stats, "memory", "%d,%d,%d,%d,%d", mem_total, mem_used, mem_cache, swap_total, swap_used); } } /* Returns the time at which the system booted, as the number of milliseconds * since the epoch, or 0 if the time of boot cannot be determined. */ static long long int get_boot_time(void) { static long long int cache_expiration = LLONG_MIN; static long long int boot_time; ovs_assert(LINUX); if (time_msec() >= cache_expiration) { static const char stat_file[] = "/proc/stat"; char line[128]; FILE *stream; cache_expiration = time_msec() + 5 * 1000; stream = fopen(stat_file, "r"); if (!stream) { VLOG_ERR_ONCE("%s: open failed (%s)", stat_file, ovs_strerror(errno)); return boot_time; } while (fgets(line, sizeof line, stream)) { long long int btime; if (ovs_scan(line, "btime %lld", &btime)) { boot_time = btime * 1000; goto done; } } VLOG_ERR_ONCE("%s: btime not found", stat_file); done: fclose(stream); } return boot_time; } static unsigned long long int ticks_to_ms(unsigned long long int ticks) { ovs_assert(LINUX); #ifndef USER_HZ #define USER_HZ 100 #endif #if USER_HZ == 100 /* Common case. */ return ticks * (1000 / USER_HZ); #else /* Alpha and some other architectures. */ double factor = 1000.0 / USER_HZ; return ticks * factor + 0.5; #endif } struct raw_process_info { unsigned long int vsz; /* Virtual size, in kB. */ unsigned long int rss; /* Resident set size, in kB. */ long long int uptime; /* ms since started. */ long long int cputime; /* ms of CPU used during 'uptime'. */ pid_t ppid; /* Parent. */ char name[18]; /* Name (surrounded by parentheses). */ }; static bool get_raw_process_info(pid_t pid, struct raw_process_info *raw) { unsigned long long int vsize, rss, start_time, utime, stime; long long int start_msec; unsigned long ppid; char file_name[128]; FILE *stream; int n; ovs_assert(LINUX); sprintf(file_name, "/proc/%lu/stat", (unsigned long int) pid); stream = fopen(file_name, "r"); if (!stream) { VLOG_ERR_ONCE("%s: open failed (%s)", file_name, ovs_strerror(errno)); return false; } n = fscanf(stream, "%*d " /* (1. pid) */ "%17s " /* 2. process name */ "%*c " /* (3. state) */ "%lu " /* 4. ppid */ "%*d " /* (5. pgid) */ "%*d " /* (6. sid) */ "%*d " /* (7. tty_nr) */ "%*d " /* (8. tty_pgrp) */ "%*u " /* (9. flags) */ "%*u " /* (10. min_flt) */ "%*u " /* (11. cmin_flt) */ "%*u " /* (12. maj_flt) */ "%*u " /* (13. cmaj_flt) */ "%llu " /* 14. utime */ "%llu " /* 15. stime */ "%*d " /* (16. cutime) */ "%*d " /* (17. cstime) */ "%*d " /* (18. priority) */ "%*d " /* (19. nice) */ "%*d " /* (20. num_threads) */ "%*d " /* (21. always 0) */ "%llu " /* 22. start_time */ "%llu " /* 23. vsize */ "%llu " /* 24. rss */ #if 0 /* These are here for documentation but #if'd out to save * actually parsing them from the stream for no benefit. */ "%*lu " /* (25. rsslim) */ "%*lu " /* (26. start_code) */ "%*lu " /* (27. end_code) */ "%*lu " /* (28. start_stack) */ "%*lu " /* (29. esp) */ "%*lu " /* (30. eip) */ "%*lu " /* (31. pending signals) */ "%*lu " /* (32. blocked signals) */ "%*lu " /* (33. ignored signals) */ "%*lu " /* (34. caught signals) */ "%*lu " /* (35. whcan) */ "%*lu " /* (36. always 0) */ "%*lu " /* (37. always 0) */ "%*d " /* (38. exit_signal) */ "%*d " /* (39. task_cpu) */ "%*u " /* (40. rt_priority) */ "%*u " /* (41. policy) */ "%*llu " /* (42. blkio_ticks) */ "%*lu " /* (43. gtime) */ "%*ld" /* (44. cgtime) */ #endif , raw->name, &ppid, &utime, &stime, &start_time, &vsize, &rss); fclose(stream); if (n != 7) { VLOG_ERR_ONCE("%s: fscanf failed", file_name); return false; } start_msec = get_boot_time() + ticks_to_ms(start_time); raw->vsz = vsize / 1024; raw->rss = rss * (getpagesize() / 1024); raw->uptime = time_wall_msec() - start_msec; raw->cputime = ticks_to_ms(utime + stime); raw->ppid = ppid; return true; } static int count_crashes(pid_t pid) { char file_name[128]; const char *paren; char line[128]; int crashes = 0; FILE *stream; ovs_assert(LINUX); sprintf(file_name, "/proc/%lu/cmdline", (unsigned long int) pid); stream = fopen(file_name, "r"); if (!stream) { VLOG_WARN_ONCE("%s: open failed (%s)", file_name, ovs_strerror(errno)); goto exit; } if (!fgets(line, sizeof line, stream)) { VLOG_WARN_ONCE("%s: read failed (%s)", file_name, feof(stream) ? "end of file" : ovs_strerror(errno)); goto exit_close; } paren = strchr(line, '('); if (paren) { int x; if (ovs_scan(paren + 1, "%d", &x)) { crashes = x; } } exit_close: fclose(stream); exit: return crashes; } struct process_info { unsigned long int vsz; /* Virtual size, in kB. */ unsigned long int rss; /* Resident set size, in kB. */ long long int booted; /* ms since monitor started. */ int crashes; /* # of crashes (usually 0). */ long long int uptime; /* ms since last (re)started by monitor. */ long long int cputime; /* ms of CPU used during 'uptime'. */ }; static bool get_process_info(pid_t pid, struct process_info *pinfo) { struct raw_process_info child; ovs_assert(LINUX); if (!get_raw_process_info(pid, &child)) { return false; } pinfo->vsz = child.vsz; pinfo->rss = child.rss; pinfo->booted = child.uptime; pinfo->crashes = 0; pinfo->uptime = child.uptime; pinfo->cputime = child.cputime; if (child.ppid) { struct raw_process_info parent; get_raw_process_info(child.ppid, &parent); if (!strcmp(child.name, parent.name)) { pinfo->booted = parent.uptime; pinfo->crashes = count_crashes(child.ppid); } } return true; } static void get_process_stats(struct smap *stats) { #ifndef _WIN32 struct dirent *de; DIR *dir; dir = opendir(ovs_rundir()); if (!dir) { VLOG_ERR_ONCE("%s: open failed (%s)", ovs_rundir(), ovs_strerror(errno)); return; } while ((de = readdir(dir)) != NULL) { struct process_info pinfo; char *file_name; char *extension; char *key; pid_t pid; #ifdef _DIRENT_HAVE_D_TYPE if (de->d_type != DT_UNKNOWN && de->d_type != DT_REG) { continue; } #endif extension = strrchr(de->d_name, '.'); if (!extension || strcmp(extension, ".pid")) { continue; } file_name = xasprintf("%s/%s", ovs_rundir(), de->d_name); pid = read_pidfile(file_name); free(file_name); if (pid < 0) { continue; } key = xasprintf("process_%.*s", (int) (extension - de->d_name), de->d_name); if (!smap_get(stats, key)) { if (LINUX && get_process_info(pid, &pinfo)) { smap_add_format(stats, key, "%lu,%lu,%lld,%d,%lld,%lld", pinfo.vsz, pinfo.rss, pinfo.cputime, pinfo.crashes, pinfo.booted, pinfo.uptime); } else { smap_add(stats, key, ""); } } free(key); } closedir(dir); #endif /* _WIN32 */ } static void get_filesys_stats(struct smap *stats OVS_UNUSED) { #if HAVE_GETMNTENT_R && HAVE_STATVFS static const char file_name[] = "/etc/mtab"; struct mntent mntent; struct mntent *me; char buf[4096]; FILE *stream; struct ds s; stream = setmntent(file_name, "r"); if (!stream) { VLOG_ERR_ONCE("%s: open failed (%s)", file_name, ovs_strerror(errno)); return; } ds_init(&s); while ((me = getmntent_r(stream, &mntent, buf, sizeof buf)) != NULL) { unsigned long long int total, free; struct statvfs vfs; char *p; /* Skip non-local and read-only filesystems. */ if (strncmp(me->mnt_fsname, "/dev", 4) || !strstr(me->mnt_opts, "rw")) { continue; } /* Given the mount point we can stat the file system. */ if (statvfs(me->mnt_dir, &vfs) && vfs.f_flag & ST_RDONLY) { /* That's odd... */ continue; } /* Now format the data. */ if (s.length) { ds_put_char(&s, ' '); } for (p = me->mnt_dir; *p != '\0'; p++) { ds_put_char(&s, *p == ' ' || *p == ',' ? '_' : *p); } total = (unsigned long long int) vfs.f_frsize * vfs.f_blocks / 1024; free = (unsigned long long int) vfs.f_frsize * vfs.f_bfree / 1024; ds_put_format(&s, ",%llu,%llu", total, total - free); } endmntent(stream); if (s.length) { smap_add(stats, "file_systems", ds_cstr(&s)); } ds_destroy(&s); #endif /* HAVE_GETMNTENT_R && HAVE_STATVFS */ } #define SYSTEM_STATS_INTERVAL (5 * 1000) /* In milliseconds. */ static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; static struct latch latch OVS_GUARDED_BY(mutex); static bool enabled; static bool started OVS_GUARDED_BY(mutex); static struct smap *system_stats OVS_GUARDED_BY(mutex); OVS_NO_RETURN static void *system_stats_thread_func(void *); static void discard_stats(void); /* Enables or disables system stats collection, according to 'enable'. */ void system_stats_enable(bool enable) { if (enabled != enable) { ovs_mutex_lock(&mutex); if (enable) { if (!started) { ovs_thread_create("system_stats", system_stats_thread_func, NULL); latch_init(&latch); started = true; } discard_stats(); xpthread_cond_signal(&cond); } enabled = enable; ovs_mutex_unlock(&mutex); } } /* Tries to obtain a new snapshot of system stats every SYSTEM_STATS_INTERVAL * milliseconds. * * When a new snapshot is available (which only occurs if system stats are * enabled), returns it as an smap owned by the caller. The caller must use * both smap_destroy() and free() to completely free the returned data. * * When no new snapshot is available, returns NULL. */ struct smap * system_stats_run(void) { struct smap *stats = NULL; ovs_mutex_lock(&mutex); if (system_stats) { latch_poll(&latch); if (enabled) { stats = system_stats; system_stats = NULL; } else { discard_stats(); } } ovs_mutex_unlock(&mutex); return stats; } /* Causes poll_block() to wake up when system_stats_run() needs to be * called. */ void system_stats_wait(void) { if (enabled) { latch_wait(&latch); } } static void discard_stats(void) OVS_REQUIRES(mutex) { if (system_stats) { smap_destroy(system_stats); free(system_stats); system_stats = NULL; } } static void * system_stats_thread_func(void *arg OVS_UNUSED) { pthread_detach(pthread_self()); for (;;) { long long int next_refresh; struct smap *stats; ovs_mutex_lock(&mutex); while (!enabled) { ovs_mutex_cond_wait(&cond, &mutex); } ovs_mutex_unlock(&mutex); stats = xmalloc(sizeof *stats); smap_init(stats); get_cpu_cores(stats); get_load_average(stats); get_memory_stats(stats); get_process_stats(stats); get_filesys_stats(stats); ovs_mutex_lock(&mutex); discard_stats(); system_stats = stats; latch_set(&latch); ovs_mutex_unlock(&mutex); next_refresh = time_msec() + SYSTEM_STATS_INTERVAL; do { poll_timer_wait_until(next_refresh); poll_block(); } while (time_msec() < next_refresh); } } openvswitch-2.5.0/vswitchd/PaxHeaders.69223/INTERNALS0000644000000000000000000000013212631676263016762 xustar0030 mtime=1449622707.590461115 30 atime=1456592667.487097621 30 ctime=1456594660.025281758 openvswitch-2.5.0/vswitchd/INTERNALS0000664000175000017500000002677612631676263020474 0ustar00jpettitjpettit00000000000000 ======================== ovs-vswitchd Internals ======================== This document describes some of the internals of the ovs-vswitchd process. It is not complete. It tends to be updated on demand, so if you have questions about the vswitchd implementation, ask them and perhaps we'll add some appropriate documentation here. Most of the ovs-vswitchd implementation is in vswitchd/bridge.c, so code references below should be assumed to refer to that file except as otherwise specified. Bonding ======= Bonding allows two or more interfaces (the "slaves") to share network traffic. From a high-level point of view, bonded interfaces act like a single port, but they have the bandwidth of multiple network devices, e.g. two 1 GB physical interfaces act like a single 2 GB interface. Bonds also increase robustness: the bonded port does not go down as long as at least one of its slaves is up. In vswitchd, a bond always has at least two slaves (and may have more). If a configuration error, etc. would cause a bond to have only one slave, the port becomes an ordinary port, not a bonded port, and none of the special features of bonded ports described in this section apply. There are many forms of bonding of which ovs-vswitchd implements only a few. The most complex bond ovs-vswitchd implements is called "source load balancing" or SLB bonding. SLB bonding divides traffic among the slaves based on the Ethernet source address. This is useful only if the traffic over the bond has multiple Ethernet source addresses, for example if network traffic from multiple VMs are multiplexed over the bond. Enabling and Disabling Slaves ----------------------------- When a bond is created, a slave is initially enabled or disabled based on whether carrier is detected on the NIC (see iface_create()). After that, a slave is disabled if its carrier goes down for a period of time longer than the downdelay, and it is enabled if carrier comes up for longer than the updelay (see bond_link_status_update()). There is one exception where the updelay is skipped: if no slaves at all are currently enabled, then the first slave on which carrier comes up is enabled immediately. The updelay should be set to a time longer than the STP forwarding delay of the physical switch to which the bond port is connected (if STP is enabled on that switch). Otherwise, the slave will be enabled, and load may be shifted to it, before the physical switch starts forwarding packets on that port, which can cause some data to be "blackholed" for a time. The exception for a single enabled slave does not cause any problem in this regard because when no slaves are enabled all output packets are blackholed anyway. When a slave becomes disabled, the vswitch immediately chooses a new output port for traffic that was destined for that slave (see bond_enable_slave()). It also sends a "gratuitous learning packet", specifically a RARP, on the bond port (on the newly chosen slave) for each MAC address that the vswitch has learned on a port other than the bond (see bond_send_learning_packets()), to teach the physical switch that the new slave should be used in place of the one that is now disabled. (This behavior probably makes sense only for a vswitch that has only one port (the bond) connected to a physical switch; vswitchd should probably provide a way to disable or configure it in other scenarios.) Bond Packet Input ----------------- Bonding accepts unicast packets on any bond slave. This can occasionally cause packet duplication for the first few packets sent to a given MAC, if the physical switch attached to the bond is flooding packets to that MAC because it has not yet learned the correct slave for that MAC. Bonding only accepts multicast (and broadcast) packets on a single bond slave (the "active slave") at any given time. Multicast packets received on other slaves are dropped. Otherwise, every multicast packet would be duplicated, once for every bond slave, because the physical switch attached to the bond will flood those packets. Bonding also drops received packets when the vswitch has learned that the packet's MAC is on a port other than the bond port itself. This is because it is likely that the vswitch itself sent the packet out the bond port on a different slave and is now receiving the packet back. This occurs when the packet is multicast or the physical switch has not yet learned the MAC and is flooding it. However, the vswitch makes an exception to this rule for broadcast ARP replies, which indicate that the MAC has moved to another switch, probably due to VM migration. (ARP replies are normally unicast, so this exception does not match normal ARP replies. It will match the learning packets sent on bond fail-over.) The active slave is simply the first slave to be enabled after the bond is created (see bond_choose_active_iface()). If the active slave is disabled, then a new active slave is chosen among the slaves that remain active. Currently due to the way that configuration works, this tends to be the remaining slave whose interface name is first alphabetically, but this is by no means guaranteed. Bond Packet Output ------------------ When a packet is sent out a bond port, the bond slave actually used is selected based on the packet's source MAC and VLAN tag (see choose_output_iface()). In particular, the source MAC and VLAN tag are hashed into one of 256 values, and that value is looked up in a hash table (the "bond hash") kept in the "bond_hash" member of struct port. The hash table entry identifies a bond slave. If no bond slave has yet been chosen for that hash table entry, vswitchd chooses one arbitrarily. Every 10 seconds, vswitchd rebalances the bond slaves (see bond_rebalance_port()). To rebalance, vswitchd examines the statistics for the number of bytes transmitted by each slave over approximately the past minute, with data sent more recently weighted more heavily than data sent less recently. It considers each of the slaves in order from most-loaded to least-loaded. If highly loaded slave H is significantly more heavily loaded than the least-loaded slave L, and slave H carries at least two hashes, then vswitchd shifts one of H's hashes to L. However, vswitchd will only shift a hash from H to L if it will decrease the ratio of the load between H and L by at least 0.1. Currently, "significantly more loaded" means that H must carry at least 1 Mbps more traffic, and that traffic must be at least 3% greater than L's. Bond Balance Modes ------------------ Each bond balancing mode has different considerations, described below. LACP Bonding ------------ LACP bonding requires the remote switch to implement LACP, but it is otherwise very simple in that, after LACP negotiation is complete, there is no need for special handling of received packets. Several of the physical switches that support LACP block all traffic for ports that are configured to use LACP, until LACP is negotiated with the host. When configuring a LACP bond on a OVS host (eg: XenServer), this means that there will be an interruption of the network connectivity between the time the ports on the physical switch and the bond on the OVS host are configured. The interruption may be relatively long, if different people are responsible for managing the switches and the OVS host. Such network connectivity failure can be avoided if LACP can be configured on the OVS host before configuring the physical switch, and having the OVS host fall back to a bond mode (active-backup) till the physical switch LACP configuration is complete. An option "lacp-fallback-ab" exists to provide such behavior on openvswitch. Active Backup Bonding --------------------- Active Backup bonds send all traffic out one "active" slave until that slave becomes unavailable. Since they are significantly less complicated than SLB bonds, they are preferred when LACP is not an option. Additionally, they are the only bond mode which supports attaching each slave to a different upstream switch. SLB Bonding ----------- SLB bonding allows a limited form of load balancing without the remote switch's knowledge or cooperation. The basics of SLB are simple. SLB assigns each source MAC+VLAN pair to a link and transmits all packets from that MAC+VLAN through that link. Learning in the remote switch causes it to send packets to that MAC+VLAN through the same link. SLB bonding has the following complications: 0. When the remote switch has not learned the MAC for the destination of a unicast packet and hence floods the packet to all of the links on the SLB bond, Open vSwitch will forward duplicate packets, one per link, to each other switch port. Open vSwitch does not solve this problem. 1. When the remote switch receives a multicast or broadcast packet from a port not on the SLB bond, it will forward it to all of the links in the SLB bond. This would cause packet duplication if not handled specially. Open vSwitch avoids packet duplication by accepting multicast and broadcast packets on only the active slave, and dropping multicast and broadcast packets on all other slaves. 2. When Open vSwitch forwards a multicast or broadcast packet to a link in the SLB bond other than the active slave, the remote switch will forward it to all of the other links in the SLB bond, including the active slave. Without special handling, this would mean that Open vSwitch would forward a second copy of the packet to each switch port (other than the bond), including the port that originated the packet. Open vSwitch deals with this case by dropping packets received on any SLB bonded link that have a source MAC+VLAN that has been learned on any other port. (This means that SLB as implemented in Open vSwitch relies critically on MAC learning. Notably, SLB is incompatible with the "flood_vlans" feature.) 3. Suppose that a MAC+VLAN moves to an SLB bond from another port (e.g. when a VM is migrated from this hypervisor to a different one). Without additional special handling, Open vSwitch will not notice until the MAC learning entry expires, up to 60 seconds later as a consequence of rule #2. Open vSwitch avoids a 60-second delay by listening for gratuitous ARPs, which VMs commonly emit upon migration. As an exception to rule #2, a gratuitous ARP received on an SLB bond is not dropped and updates the MAC learning table in the usual way. (If a move does not trigger a gratuitous ARP, or if the gratuitous ARP is lost in the network, then a 60-second delay still occurs.) 4. Suppose that a MAC+VLAN moves from an SLB bond to another port (e.g. when a VM is migrated from a different hypervisor to this one), that the MAC+VLAN emits a gratuitous ARP, and that Open vSwitch forwards that gratuitous ARP to a link in the SLB bond other than the active slave. The remote switch will forward the gratuitous ARP to all of the other links in the SLB bond, including the active slave. Without additional special handling, this would mean that Open vSwitch would learn that the MAC+VLAN was located on the SLB bond, as a consequence of rule #3. Open vSwitch avoids this problem by "locking" the MAC learning table entry for a MAC+VLAN from which a gratuitous ARP was received from a non-SLB bond port. For 5 seconds, a locked MAC learning table entry will not be updated based on a gratuitous ARP received on a SLB bond. openvswitch-2.5.0/vswitchd/PaxHeaders.69223/automake.mk0000644000000000000000000000013112631676263017636 xustar0030 mtime=1449622707.590461115 29 atime=1456592426.46120881 30 ctime=1456594659.581263092 openvswitch-2.5.0/vswitchd/automake.mk0000664000175000017500000000424512631676263021334 0ustar00jpettitjpettit00000000000000sbin_PROGRAMS += vswitchd/ovs-vswitchd man_MANS += vswitchd/ovs-vswitchd.8 DISTCLEANFILES += \ vswitchd/ovs-vswitchd.8 vswitchd_ovs_vswitchd_SOURCES = \ vswitchd/bridge.c \ vswitchd/bridge.h \ vswitchd/ovs-vswitchd.c \ vswitchd/system-stats.c \ vswitchd/system-stats.h \ vswitchd/xenserver.c \ vswitchd/xenserver.h vswitchd_ovs_vswitchd_LDADD = \ ofproto/libofproto.la \ lib/libsflow.la \ lib/libopenvswitch.la vswitchd_ovs_vswitchd_LDFLAGS = $(AM_LDFLAGS) $(DPDK_vswitchd_LDFLAGS) EXTRA_DIST += vswitchd/INTERNALS MAN_ROOTS += vswitchd/ovs-vswitchd.8.in # vswitch schema and IDL EXTRA_DIST += vswitchd/vswitch.ovsschema pkgdata_DATA += vswitchd/vswitch.ovsschema # vswitch E-R diagram # # If "python" or "dot" is not available, then we do not add graphical diagram # to the documentation. if HAVE_PYTHON if HAVE_DOT vswitchd/vswitch.gv: ovsdb/ovsdb-dot.in vswitchd/vswitch.ovsschema $(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/vswitchd/vswitch.ovsschema > $@ vswitchd/vswitch.pic: vswitchd/vswitch.gv ovsdb/dot2pic $(AM_V_GEN)(dot -T plain < vswitchd/vswitch.gv | $(PERL) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \ mv $@.tmp $@ VSWITCH_PIC = vswitchd/vswitch.pic VSWITCH_DOT_DIAGRAM_ARG = --er-diagram=$(VSWITCH_PIC) DISTCLEANFILES += vswitchd/vswitch.gv vswitchd/vswitch.pic endif endif # vswitch schema documentation EXTRA_DIST += vswitchd/vswitch.xml DISTCLEANFILES += vswitchd/ovs-vswitchd.conf.db.5 man_MANS += vswitchd/ovs-vswitchd.conf.db.5 vswitchd/ovs-vswitchd.conf.db.5: \ ovsdb/ovsdb-doc vswitchd/vswitch.xml vswitchd/vswitch.ovsschema \ $(VSWITCH_PIC) $(AM_V_GEN)$(OVSDB_DOC) \ $(VSWITCH_DOT_DIAGRAM_ARG) \ --version=$(VERSION) \ $(srcdir)/vswitchd/vswitch.ovsschema \ $(srcdir)/vswitchd/vswitch.xml > $@.tmp && \ mv $@.tmp $@ # Version checking for vswitch.ovsschema. ALL_LOCAL += vswitchd/vswitch.ovsschema.stamp vswitchd/vswitch.ovsschema.stamp: vswitchd/vswitch.ovsschema $(srcdir)/build-aux/cksum-schema-check $? $@ CLEANFILES += vswitchd/vswitch.ovsschema.stamp # Clean up generated files from older OVS versions. (This is important so that # #include "vswitch-idl.h" doesn't get the wrong copy.) CLEANFILES += vswitchd/vswitch-idl.c vswitchd/vswitch-idl.h openvswitch-2.5.0/PaxHeaders.69223/Makefile.in0000644000000000000000000000013212664357152015711 xustar0030 mtime=1456594538.384165896 30 atime=1456594549.320626037 30 ctime=1456594659.601263932 openvswitch-2.5.0/Makefile.in0000664000175000017500000113554212664357152017414 0ustar00jpettitjpettit00000000000000# Makefile.in generated by automake 1.14.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2013 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # Copyright (C) 2007-2016 Nicira, Inc. # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. # Generated automatically -- do not modify! -*- buffer-read-only: t -*- # Copyright (C) 2013 Nicira, Inc. # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. # Copyright (C) 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. # Copyright (C) 2009, 2010, 2011, 2012, 2014 Nicira, Inc. # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. # Copyright (C) 2013 Nicira, Inc. # # Copying and distribution of this file, with or without modification # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. # Copyright (C) 2009, 2010, 2011, 2012, 2014 Nicira, Inc. # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. # Copyright (C) 2009, 2010, 2011, 2012, 2014 Nicira, Inc. # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. # Copyright 2015 Cloudbase Solutions Srl # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License.You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the # License for the specific language governing permissions and limitations # under the License. # Copyright (C) 2016 Nicira, Inc. # # Copying and distribution of this file, with or without modification, # are permitted in any medium without royalty provided the copyright # notice and this notice are preserved. This file is offered as-is, # without warranty of any kind. VPATH = @srcdir@ am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)' am__make_running_with_option = \ case $${target_option-} in \ ?) ;; \ *) echo "am__make_running_with_option: internal error: invalid" \ "target option '$${target_option-}' specified" >&2; \ exit 1;; \ esac; \ has_opt=no; \ sane_makeflags=$$MAKEFLAGS; \ if $(am__is_gnu_make); then \ sane_makeflags=$$MFLAGS; \ else \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ bs=\\; \ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \ esac; \ fi; \ skip_next=no; \ strip_trailopt () \ { \ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \ }; \ for flg in $$sane_makeflags; do \ test $$skip_next = yes && { skip_next=no; continue; }; \ case $$flg in \ *=*|--*) continue;; \ -*I) strip_trailopt 'I'; skip_next=yes;; \ -*I?*) strip_trailopt 'I';; \ -*O) strip_trailopt 'O'; skip_next=yes;; \ -*O?*) strip_trailopt 'O';; \ -*l) strip_trailopt 'l'; skip_next=yes;; \ -*l?*) strip_trailopt 'l';; \ -[dEDm]) skip_next=yes;; \ -[JT]) skip_next=yes;; \ esac; \ case $$flg in \ *$$target_option*) has_opt=yes; break;; \ esac; \ done; \ test $$has_opt = yes am__make_dryrun = (target_option=n; $(am__make_running_with_option)) am__make_keepgoing = (target_option=k; $(am__make_running_with_option)) pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ @WIN32_TRUE@am__append_1 = -I $(top_srcdir)/include/windows -I \ @WIN32_TRUE@ $(top_srcdir)/datapath-windows/include \ @WIN32_TRUE@ $(PTHREAD_INCLUDES) $(MSVC_CFLAGS) @WIN32_TRUE@am__append_2 = $(PTHREAD_LDFLAGS) $(MSVC64_LDFLAGS) @DPDK_NETDEV_TRUE@am__append_3 = -D_FILE_OFFSET_BITS=64 @NDEBUG_TRUE@am__append_4 = -DNDEBUG @NDEBUG_TRUE@am__append_5 = -fomit-frame-pointer bin_PROGRAMS = utilities/ovs-appctl$(EXEEXT) \ utilities/ovs-testcontroller$(EXEEXT) \ utilities/ovs-dpctl$(EXEEXT) utilities/ovs-ofctl$(EXEEXT) \ utilities/ovs-vsctl$(EXEEXT) utilities/ovs-benchmark$(EXEEXT) \ ovsdb/ovsdb-tool$(EXEEXT) ovsdb/ovsdb-client$(EXEEXT) \ vtep/vtep-ctl$(EXEEXT) ovn/controller/ovn-controller$(EXEEXT) \ ovn/controller-vtep/ovn-controller-vtep$(EXEEXT) \ ovn/northd/ovn-northd$(EXEEXT) \ ovn/utilities/ovn-nbctl$(EXEEXT) \ ovn/utilities/ovn-sbctl$(EXEEXT) sbin_PROGRAMS = $(am__EXEEXT_3) vswitchd/ovs-vswitchd$(EXEEXT) \ ovsdb/ovsdb-server$(EXEEXT) noinst_PROGRAMS = $(am__EXEEXT_1) tests/test-ovsdb$(EXEEXT) \ tests/test-lib$(EXEEXT) $(am__EXEEXT_2) tests/ovstest$(EXEEXT) \ tests/test-strtok_r$(EXEEXT) tests/test-type-props$(EXEEXT) # If we're checked out from a Git repository, make sure that every # file that is in Git is distributed. # # We only enable this check when GNU make is in use because the # Makefile in datapath/linux, needed to get the list of files to # distribute, requires GNU make extensions. @GNU_MAKE_TRUE@am__append_6 = dist-hook-git @GNU_MAKE_TRUE@am__append_7 = all-distfiles all-gitfiles \ @GNU_MAKE_TRUE@ missing-distfiles distfiles @HAVE_GROFF_TRUE@am__append_8 = manpage-check @HAVE_GROFF_TRUE@am__append_9 = manpage-check DIST_COMMON = $(srcdir)/manpages.mk \ $(srcdir)/Documentation/automake.mk $(srcdir)/m4/automake.mk \ $(srcdir)/lib/automake.mk $(srcdir)/ofproto/automake.mk \ $(srcdir)/utilities/automake.mk \ $(srcdir)/utilities/bugtool/automake.mk \ $(srcdir)/tests/automake.mk $(srcdir)/include/automake.mk \ $(srcdir)/include/openflow/automake.mk \ $(srcdir)/include/openvswitch/automake.mk \ $(srcdir)/include/sparse/automake.mk \ $(srcdir)/include/windows/automake.mk \ $(srcdir)/third-party/automake.mk $(srcdir)/debian/automake.mk \ $(srcdir)/vswitchd/automake.mk $(srcdir)/ovsdb/automake.mk \ $(srcdir)/rhel/automake.mk $(srcdir)/xenserver/automake.mk \ $(srcdir)/python/automake.mk $(srcdir)/tutorial/automake.mk \ $(srcdir)/vtep/automake.mk \ $(srcdir)/datapath-windows/automake.mk \ $(srcdir)/datapath-windows/include/automake.mk \ $(srcdir)/windows/automake.mk $(srcdir)/ovn/automake.mk \ $(srcdir)/ovn/controller/automake.mk \ $(srcdir)/ovn/controller-vtep/automake.mk \ $(srcdir)/ovn/lib/automake.mk $(srcdir)/ovn/northd/automake.mk \ $(srcdir)/ovn/utilities/automake.mk \ $(srcdir)/selinux/automake.mk $(srcdir)/Makefile.in \ $(srcdir)/Makefile.am $(top_srcdir)/configure \ $(am__configure_deps) $(srcdir)/config.h.in \ $(top_srcdir)/lib/stdio.h.in $(top_srcdir)/lib/string.h.in \ $(top_srcdir)/ovsdb/libovsdb.sym.in \ $(top_srcdir)/ofproto/libofproto.sym.in \ $(top_srcdir)/lib/libsflow.sym.in \ $(top_srcdir)/lib/libopenvswitch.sym.in \ $(top_srcdir)/ovn/lib/libovn.sym.in \ $(top_srcdir)/vtep/libvtep.sym.in \ $(top_srcdir)/datapath/linux/Kbuild.in \ $(top_srcdir)/datapath/linux/Makefile.in \ $(top_srcdir)/datapath/linux/Makefile.main.in \ $(top_srcdir)/tests/atlocal.in \ $(top_srcdir)/lib/libopenvswitch.pc.in \ $(top_srcdir)/lib/libsflow.pc.in \ $(top_srcdir)/ofproto/libofproto.pc.in \ $(top_srcdir)/ovsdb/libovsdb.pc.in \ $(top_srcdir)/include/openvswitch/version.h.in \ $(dist_check_SCRIPTS) $(dist_noinst_SCRIPTS) \ $(dist_pkgdata_SCRIPTS) $(dist_sbin_SCRIPTS) \ $(dist_scripts_SCRIPTS) $(top_srcdir)/build-aux/depcomp \ $(dist_man_MANS) $(dist_pkgdata_DATA) $(dist_scripts_DATA) \ $(am__noinst_HEADERS_DIST) $(openflowinclude_HEADERS) \ $(openvswitchinclude_HEADERS) AUTHORS COPYING NEWS \ build-aux/compile build-aux/config.guess build-aux/config.sub \ build-aux/depcomp build-aux/install-sh build-aux/missing \ build-aux/ltmain.sh $(top_srcdir)/build-aux/compile \ $(top_srcdir)/build-aux/config.guess \ $(top_srcdir)/build-aux/config.sub \ $(top_srcdir)/build-aux/install-sh \ $(top_srcdir)/build-aux/ltmain.sh \ $(top_srcdir)/build-aux/missing @VSTUDIO_DDK_TRUE@am__append_10 = ovsext_make @VSTUDIO_DDK_TRUE@am__append_11 = ovsext_clean @WIN32_TRUE@am__append_12 = ${PTHREAD_LIBS} @WIN32_TRUE@am__append_13 = \ @WIN32_TRUE@ lib/daemon-windows.c \ @WIN32_TRUE@ lib/getopt_long.c \ @WIN32_TRUE@ lib/getrusage-windows.c \ @WIN32_TRUE@ lib/latch-windows.c \ @WIN32_TRUE@ lib/route-table-stub.c \ @WIN32_TRUE@ lib/if-notifier-stub.c \ @WIN32_TRUE@ lib/strsep.c @WIN32_FALSE@am__append_14 = \ @WIN32_FALSE@ lib/daemon-unix.c \ @WIN32_FALSE@ lib/latch-unix.c \ @WIN32_FALSE@ lib/signals.c \ @WIN32_FALSE@ lib/signals.h \ @WIN32_FALSE@ lib/socket-util-unix.c \ @WIN32_FALSE@ lib/stream-unix.c @HAVE_WNO_UNUSED_TRUE@am__append_15 = -Wno-unused @HAVE_WNO_UNUSED_PARAMETER_TRUE@am__append_16 = -Wno-unused-parameter @LINUX_TRUE@am__append_17 = \ @LINUX_TRUE@ lib/dpif-netlink.c \ @LINUX_TRUE@ lib/dpif-netlink.h \ @LINUX_TRUE@ lib/if-notifier.c \ @LINUX_TRUE@ lib/if-notifier.h \ @LINUX_TRUE@ lib/netdev-linux.c \ @LINUX_TRUE@ lib/netdev-linux.h \ @LINUX_TRUE@ lib/netlink-conntrack.c \ @LINUX_TRUE@ lib/netlink-conntrack.h \ @LINUX_TRUE@ lib/netlink-notifier.c \ @LINUX_TRUE@ lib/netlink-notifier.h \ @LINUX_TRUE@ lib/netlink-protocol.h \ @LINUX_TRUE@ lib/netlink-socket.c \ @LINUX_TRUE@ lib/netlink-socket.h \ @LINUX_TRUE@ lib/ovs-numa.c \ @LINUX_TRUE@ lib/ovs-numa.h \ @LINUX_TRUE@ lib/rtnetlink.c \ @LINUX_TRUE@ lib/rtnetlink.h \ @LINUX_TRUE@ lib/route-table.c \ @LINUX_TRUE@ lib/route-table.h @DPDK_NETDEV_TRUE@am__append_18 = \ @DPDK_NETDEV_TRUE@ lib/netdev-dpdk.c \ @DPDK_NETDEV_TRUE@ lib/netdev-dpdk.h @WIN32_TRUE@am__append_19 = \ @WIN32_TRUE@ lib/dpif-netlink.c \ @WIN32_TRUE@ lib/dpif-netlink.h \ @WIN32_TRUE@ lib/netdev-windows.c \ @WIN32_TRUE@ lib/netlink-notifier.c \ @WIN32_TRUE@ lib/netlink-notifier.h \ @WIN32_TRUE@ lib/netlink-protocol.h \ @WIN32_TRUE@ lib/netlink-socket.c \ @WIN32_TRUE@ lib/netlink-socket.h @HAVE_POSIX_AIO_TRUE@am__append_20 = lib/async-append-aio.c @HAVE_POSIX_AIO_FALSE@am__append_21 = lib/async-append-null.c @ESX_TRUE@am__append_22 = \ @ESX_TRUE@ lib/route-table-stub.c \ @ESX_TRUE@ lib/if-notifier-stub.c @HAVE_IF_DL_TRUE@am__append_23 = \ @HAVE_IF_DL_TRUE@ lib/if-notifier-bsd.c \ @HAVE_IF_DL_TRUE@ lib/netdev-bsd.c \ @HAVE_IF_DL_TRUE@ lib/rtbsd.c \ @HAVE_IF_DL_TRUE@ lib/rtbsd.h \ @HAVE_IF_DL_TRUE@ lib/route-table-bsd.c @HAVE_OPENSSL_TRUE@am__append_24 = lib/stream-ssl.c @HAVE_OPENSSL_TRUE@am__append_25 = lib/dhparams.c @HAVE_OPENSSL_FALSE@am__append_26 = lib/stream-nossl.c @WIN32_TRUE@am__append_27 = ${PTHREAD_LIBS} @HAVE_PYTHON_TRUE@am__append_28 = \ @HAVE_PYTHON_TRUE@ utilities/ovs-dpctl-top \ @HAVE_PYTHON_TRUE@ utilities/ovs-l3ping \ @HAVE_PYTHON_TRUE@ utilities/ovs-parse-backtrace \ @HAVE_PYTHON_TRUE@ utilities/ovs-pcap \ @HAVE_PYTHON_TRUE@ utilities/ovs-tcpundump \ @HAVE_PYTHON_TRUE@ utilities/ovs-test \ @HAVE_PYTHON_TRUE@ utilities/ovs-vlan-test @LINUX_TRUE@am__append_29 = utilities/ovs-vlan-bug-workaround @LINUX_TRUE@am__append_30 = utilities/nlmon @HAVE_PYTHON_TRUE@am__append_31 = utilities/bugtool/ovs-bugtool @HAVE_PYTHON_TRUE@am__append_32 = utilities/bugtool/ovs-bugtool @HAVE_PYTHON_TRUE@am__append_33 = utilities/bugtool/ovs-bugtool.8 @HAVE_PYTHON_TRUE@am__append_34 = utilities/bugtool/ovs-bugtool.8.in @HAVE_PYTHON_TRUE@am__append_35 = utilities/bugtool/ovs-bugtool.8 @HAVE_PYTHON_TRUE@am__append_36 = $(bugtool_scripts) @HAVE_PYTHON_TRUE@am__append_37 = bugtool-install-data-local @HAVE_PYTHON_TRUE@am__append_38 = bugtool-uninstall-local @DPDK_NETDEV_TRUE@am__append_39 = tests/test-dpdkr @WIN32_FALSE@am__append_40 = \ @WIN32_FALSE@ tests/test-unix-socket.c @LINUX_TRUE@am__append_41 = \ @LINUX_TRUE@ tests/test-netlink-conntrack.c @HAVE_OPENSSL_TRUE@am__append_42 = $(TESTPKI_FILES) @HAVE_OPENSSL_TRUE@am__append_43 = $(TESTPKI_FILES) tests/ovs-pki.log @HAVE_OPENSSL_TRUE@am__append_44 = clean-pki @HAVE_PYTHON_TRUE@am__append_45 = .h .hstamp @HAVE_PYTHON_TRUE@am__append_46 = $(HSTAMP_FILES) @HAVE_PYTHON_TRUE@am__append_47 = $(HSTAMP_FILES) @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@am__append_48 = vswitchd/vswitch.gv vswitchd/vswitch.pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@am__append_49 = vtep/vtep.gv vtep/vtep.pic @WIN32_TRUE@am__append_50 = $(srcdir)/datapath-windows/include/OvsDpInterface.h @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@am__append_51 = ovn/ovn-sb.gv ovn/ovn-sb.pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@am__append_52 = ovn/ovn-nb.gv ovn/ovn-nb.pic subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/absolute-header.m4 \ $(top_srcdir)/m4/ax_check_openssl.m4 \ $(top_srcdir)/m4/ax_func_posix_memalign.m4 \ $(top_srcdir)/m4/include_next.m4 $(top_srcdir)/m4/libtool.m4 \ $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \ $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/openvswitch.m4 $(top_srcdir)/m4/compat.at \ $(top_srcdir)/acinclude.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ configure.lineno config.status.lineno mkinstalldirs = $(install_sh) -d CONFIG_HEADER = config.h CONFIG_CLEAN_FILES = lib/stdio.h lib/string.h ovsdb/libovsdb.sym \ ofproto/libofproto.sym lib/libsflow.sym lib/libopenvswitch.sym \ ovn/lib/libovn.sym vtep/libvtep.sym datapath/linux/Kbuild \ datapath/linux/Makefile datapath/linux/Makefile.main \ tests/atlocal lib/libopenvswitch.pc lib/libsflow.pc \ ofproto/libofproto.pc ovsdb/libovsdb.pc \ include/openvswitch/version.h CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(completiondir)" "$(DESTDIR)$(pkgdatadir)" \ "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(scriptsdir)" \ "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(scriptsdir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \ "$(DESTDIR)$(man7dir)" "$(DESTDIR)$(man8dir)" \ "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(scriptsdir)" \ "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(pkgconfigdir)" \ "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(scriptsdir)" \ "$(DESTDIR)$(openflowincludedir)" \ "$(DESTDIR)$(openvswitchincludedir)" LTLIBRARIES = $(lib_LTLIBRARIES) am__DEPENDENCIES_1 = @WIN32_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1) lib_libopenvswitch_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) am__lib_libopenvswitch_la_SOURCES_DIST = lib/aes128.c lib/aes128.h \ lib/async-append.h lib/backtrace.c lib/backtrace.h lib/bfd.c \ lib/bfd.h lib/bitmap.h lib/bundle.c lib/bundle.h \ lib/byte-order.h lib/byteq.c lib/byteq.h lib/cfm.c lib/cfm.h \ lib/classifier.c lib/classifier.h lib/classifier-private.h \ lib/cmap.c lib/cmap.h lib/command-line.c lib/command-line.h \ lib/compiler.h lib/connectivity.c lib/connectivity.h \ lib/coverage.c lib/coverage.h lib/crc32c.c lib/crc32c.h \ lib/csum.c lib/csum.h lib/ct-dpif.c lib/ct-dpif.h lib/daemon.c \ lib/daemon.h lib/daemon-private.h lib/db-ctl-base.c \ lib/db-ctl-base.h lib/dhcp.h lib/dummy.c lib/dummy.h \ lib/dhparams.h lib/dirs.h lib/dpctl.c lib/dpctl.h \ lib/dp-packet.h lib/dp-packet.c lib/dpif-netdev.c \ lib/dpif-netdev.h lib/dpif-provider.h lib/dpif.c lib/dpif.h \ lib/heap.c lib/heap.h lib/dynamic-string.c \ lib/dynamic-string.h lib/entropy.c lib/entropy.h \ lib/fat-rwlock.c lib/fat-rwlock.h lib/fatal-signal.c \ lib/fatal-signal.h lib/flow.c lib/flow.h lib/geneve.h \ lib/guarded-list.c lib/guarded-list.h lib/hash.c lib/hash.h \ lib/hindex.c lib/hindex.h lib/hmap.c lib/hmap.h lib/hmapx.c \ lib/hmapx.h lib/id-pool.c lib/id-pool.h lib/jhash.c \ lib/jhash.h lib/json.c lib/json.h lib/jsonrpc.c lib/jsonrpc.h \ lib/lacp.c lib/lacp.h lib/latch.h lib/learn.c lib/learn.h \ lib/learning-switch.c lib/learning-switch.h lib/list.h \ lib/lockfile.c lib/lockfile.h lib/mac-learning.c \ lib/mac-learning.h lib/match.c lib/match.h \ lib/mcast-snooping.c lib/mcast-snooping.h lib/memory.c \ lib/memory.h lib/meta-flow.c lib/meta-flow.h lib/multipath.c \ lib/multipath.h lib/netdev-dummy.c lib/netdev-provider.h \ lib/netdev-vport.c lib/netdev-vport.h lib/netdev.c \ lib/netdev.h lib/netflow.h lib/netlink.c lib/netlink.h \ lib/nx-match.c lib/nx-match.h lib/odp-execute.c \ lib/odp-execute.h lib/odp-util.c lib/odp-util.h \ lib/ofp-actions.c lib/ofp-actions.h lib/ofp-errors.c \ lib/ofp-errors.h lib/ofp-msgs.c lib/ofp-msgs.h lib/ofp-parse.c \ lib/ofp-parse.h lib/ofp-print.c lib/ofp-print.h lib/ofp-util.c \ lib/ofp-util.h lib/ofp-version-opt.h lib/ofp-version-opt.c \ lib/ofpbuf.c lib/ofpbuf.h lib/ovs-atomic-c11.h \ lib/ovs-atomic-clang.h lib/ovs-atomic-flag-gcc4.7+.h \ lib/ovs-atomic-gcc4+.h lib/ovs-atomic-gcc4.7+.h \ lib/ovs-atomic-i586.h lib/ovs-atomic-locked.c \ lib/ovs-atomic-locked.h lib/ovs-atomic-msvc.h \ lib/ovs-atomic-pthreads.h lib/ovs-atomic-x86_64.h \ lib/ovs-atomic.h lib/ovs-lldp.c lib/ovs-lldp.h lib/ovs-rcu.c \ lib/ovs-rcu.h lib/ovs-router.h lib/ovs-router.c \ lib/ovs-thread.c lib/ovs-thread.h lib/ovsdb-data.c \ lib/ovsdb-data.h lib/ovsdb-error.c lib/ovsdb-error.h \ lib/ovsdb-idl-provider.h lib/ovsdb-idl.c lib/ovsdb-idl.h \ lib/ovsdb-parser.c lib/ovsdb-parser.h lib/ovsdb-types.c \ lib/ovsdb-types.h lib/packets.c lib/packets.h lib/pcap-file.c \ lib/pcap-file.h lib/perf-counter.h lib/perf-counter.c \ lib/poll-loop.c lib/poll-loop.h lib/process.c lib/process.h \ lib/pvector.c lib/pvector.h lib/random.c lib/random.h \ lib/rconn.c lib/rconn.h lib/rculist.h lib/reconnect.c \ lib/reconnect.h lib/rstp.c lib/rstp.h lib/rstp-common.h \ lib/rstp-state-machines.c lib/rstp-state-machines.h \ lib/sat-math.h lib/seq.c lib/seq.h lib/sha1.c lib/sha1.h \ lib/shash.c lib/shash.h lib/simap.c lib/simap.h lib/smap.c \ lib/smap.h lib/socket-util.c lib/socket-util.h lib/sort.c \ lib/sort.h lib/sset.c lib/sset.h lib/stp.c lib/stp.h \ lib/stream-fd.c lib/stream-fd.h lib/stream-provider.h \ lib/stream-ssl.h lib/stream-tcp.c lib/stream.c lib/stream.h \ lib/stdio.c lib/string.c lib/svec.c lib/svec.h \ lib/syslog-direct.c lib/syslog-direct.h lib/syslog-libc.c \ lib/syslog-libc.h lib/syslog-provider.h lib/table.c \ lib/table.h lib/timer.c lib/timer.h lib/timeval.c \ lib/timeval.h lib/tnl-neigh-cache.c lib/tnl-neigh-cache.h \ lib/tnl-ports.c lib/tnl-ports.h lib/token-bucket.c \ lib/tun-metadata.c lib/tun-metadata.h lib/type-props.h \ lib/unaligned.h lib/unicode.c lib/unicode.h lib/unixctl.c \ lib/unixctl.h lib/util.c lib/util.h lib/uuid.c lib/uuid.h \ lib/valgrind.h lib/vconn-provider.h lib/vconn-stream.c \ lib/vconn.c lib/vlan-bitmap.c lib/vlan-bitmap.h lib/vlandev.c \ lib/vlandev.h lib/vlog.c lib/lldp/aa-structs.h lib/lldp/lldp.c \ lib/lldp/lldp-const.h lib/lldp/lldp-tlv.h lib/lldp/lldpd.c \ lib/lldp/lldpd.h lib/lldp/lldpd-structs.c \ lib/lldp/lldpd-structs.h lib/daemon-windows.c \ lib/getopt_long.c lib/getrusage-windows.c lib/latch-windows.c \ lib/route-table-stub.c lib/if-notifier-stub.c lib/strsep.c \ lib/daemon-unix.c lib/latch-unix.c lib/signals.c lib/signals.h \ lib/socket-util-unix.c lib/stream-unix.c lib/dpif-netlink.c \ lib/dpif-netlink.h lib/if-notifier.c lib/if-notifier.h \ lib/netdev-linux.c lib/netdev-linux.h lib/netlink-conntrack.c \ lib/netlink-conntrack.h lib/netlink-notifier.c \ lib/netlink-notifier.h lib/netlink-protocol.h \ lib/netlink-socket.c lib/netlink-socket.h lib/ovs-numa.c \ lib/ovs-numa.h lib/rtnetlink.c lib/rtnetlink.h \ lib/route-table.c lib/route-table.h lib/netdev-dpdk.c \ lib/netdev-dpdk.h lib/netdev-windows.c lib/async-append-aio.c \ lib/async-append-null.c lib/if-notifier-bsd.c lib/netdev-bsd.c \ lib/rtbsd.c lib/rtbsd.h lib/route-table-bsd.c lib/stream-ssl.c \ lib/stream-nossl.c am__dirstamp = $(am__leading_dot)dirstamp @WIN32_TRUE@am__objects_1 = lib/daemon-windows.lo lib/getopt_long.lo \ @WIN32_TRUE@ lib/getrusage-windows.lo lib/latch-windows.lo \ @WIN32_TRUE@ lib/route-table-stub.lo lib/if-notifier-stub.lo \ @WIN32_TRUE@ lib/strsep.lo @WIN32_FALSE@am__objects_2 = lib/daemon-unix.lo lib/latch-unix.lo \ @WIN32_FALSE@ lib/signals.lo lib/socket-util-unix.lo \ @WIN32_FALSE@ lib/stream-unix.lo @LINUX_TRUE@am__objects_3 = lib/dpif-netlink.lo lib/if-notifier.lo \ @LINUX_TRUE@ lib/netdev-linux.lo lib/netlink-conntrack.lo \ @LINUX_TRUE@ lib/netlink-notifier.lo lib/netlink-socket.lo \ @LINUX_TRUE@ lib/ovs-numa.lo lib/rtnetlink.lo \ @LINUX_TRUE@ lib/route-table.lo @DPDK_NETDEV_TRUE@am__objects_4 = lib/netdev-dpdk.lo @WIN32_TRUE@am__objects_5 = lib/dpif-netlink.lo lib/netdev-windows.lo \ @WIN32_TRUE@ lib/netlink-notifier.lo lib/netlink-socket.lo @HAVE_POSIX_AIO_TRUE@am__objects_6 = lib/async-append-aio.lo @HAVE_POSIX_AIO_FALSE@am__objects_7 = lib/async-append-null.lo @ESX_TRUE@am__objects_8 = lib/route-table-stub.lo \ @ESX_TRUE@ lib/if-notifier-stub.lo @HAVE_IF_DL_TRUE@am__objects_9 = lib/if-notifier-bsd.lo \ @HAVE_IF_DL_TRUE@ lib/netdev-bsd.lo lib/rtbsd.lo \ @HAVE_IF_DL_TRUE@ lib/route-table-bsd.lo @HAVE_OPENSSL_TRUE@am__objects_10 = lib/stream-ssl.lo @HAVE_OPENSSL_FALSE@am__objects_11 = lib/stream-nossl.lo am_lib_libopenvswitch_la_OBJECTS = lib/aes128.lo lib/backtrace.lo \ lib/bfd.lo lib/bundle.lo lib/byteq.lo lib/cfm.lo \ lib/classifier.lo lib/cmap.lo lib/command-line.lo \ lib/connectivity.lo lib/coverage.lo lib/crc32c.lo lib/csum.lo \ lib/ct-dpif.lo lib/daemon.lo lib/db-ctl-base.lo lib/dummy.lo \ lib/dpctl.lo lib/dp-packet.lo lib/dpif-netdev.lo lib/dpif.lo \ lib/heap.lo lib/dynamic-string.lo lib/entropy.lo \ lib/fat-rwlock.lo lib/fatal-signal.lo lib/flow.lo \ lib/guarded-list.lo lib/hash.lo lib/hindex.lo lib/hmap.lo \ lib/hmapx.lo lib/id-pool.lo lib/jhash.lo lib/json.lo \ lib/jsonrpc.lo lib/lacp.lo lib/learn.lo lib/learning-switch.lo \ lib/lockfile.lo lib/mac-learning.lo lib/match.lo \ lib/mcast-snooping.lo lib/memory.lo lib/meta-flow.lo \ lib/multipath.lo lib/netdev-dummy.lo lib/netdev-vport.lo \ lib/netdev.lo lib/netlink.lo lib/nx-match.lo \ lib/odp-execute.lo lib/odp-util.lo lib/ofp-actions.lo \ lib/ofp-errors.lo lib/ofp-msgs.lo lib/ofp-parse.lo \ lib/ofp-print.lo lib/ofp-util.lo lib/ofp-version-opt.lo \ lib/ofpbuf.lo lib/ovs-atomic-locked.lo lib/ovs-lldp.lo \ lib/ovs-rcu.lo lib/ovs-router.lo lib/ovs-thread.lo \ lib/ovsdb-data.lo lib/ovsdb-error.lo lib/ovsdb-idl.lo \ lib/ovsdb-parser.lo lib/ovsdb-types.lo lib/packets.lo \ lib/pcap-file.lo lib/perf-counter.lo lib/poll-loop.lo \ lib/process.lo lib/pvector.lo lib/random.lo lib/rconn.lo \ lib/reconnect.lo lib/rstp.lo lib/rstp-state-machines.lo \ lib/seq.lo lib/sha1.lo lib/shash.lo lib/simap.lo lib/smap.lo \ lib/socket-util.lo lib/sort.lo lib/sset.lo lib/stp.lo \ lib/stream-fd.lo lib/stream-tcp.lo lib/stream.lo lib/stdio.lo \ lib/string.lo lib/svec.lo lib/syslog-direct.lo \ lib/syslog-libc.lo lib/table.lo lib/timer.lo lib/timeval.lo \ lib/tnl-neigh-cache.lo lib/tnl-ports.lo lib/token-bucket.lo \ lib/tun-metadata.lo lib/unicode.lo lib/unixctl.lo lib/util.lo \ lib/uuid.lo lib/vconn-stream.lo lib/vconn.lo \ lib/vlan-bitmap.lo lib/vlandev.lo lib/vlog.lo lib/lldp/lldp.lo \ lib/lldp/lldpd.lo lib/lldp/lldpd-structs.lo $(am__objects_1) \ $(am__objects_2) $(am__objects_3) $(am__objects_4) \ $(am__objects_5) $(am__objects_6) $(am__objects_7) \ $(am__objects_8) $(am__objects_9) $(am__objects_10) \ $(am__objects_11) @HAVE_OPENSSL_TRUE@am__objects_12 = lib/dhparams.lo nodist_lib_libopenvswitch_la_OBJECTS = lib/dirs.lo lib/vswitch-idl.lo \ $(am__objects_12) lib_libopenvswitch_la_OBJECTS = $(am_lib_libopenvswitch_la_OBJECTS) \ $(nodist_lib_libopenvswitch_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = lib_libopenvswitch_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(lib_libopenvswitch_la_LDFLAGS) \ $(LDFLAGS) -o $@ lib_libsflow_la_LIBADD = am_lib_libsflow_la_OBJECTS = lib/lib_libsflow_la-sflow_agent.lo \ lib/lib_libsflow_la-sflow_sampler.lo \ lib/lib_libsflow_la-sflow_poller.lo \ lib/lib_libsflow_la-sflow_receiver.lo lib_libsflow_la_OBJECTS = $(am_lib_libsflow_la_OBJECTS) lib_libsflow_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(lib_libsflow_la_CFLAGS) $(CFLAGS) $(lib_libsflow_la_LDFLAGS) \ $(LDFLAGS) -o $@ ofproto_libofproto_la_DEPENDENCIES = lib/libsflow.la \ $(am__DEPENDENCIES_2) am_ofproto_libofproto_la_OBJECTS = \ ofproto/ofproto_libofproto_la-bond.lo \ ofproto/ofproto_libofproto_la-collectors.lo \ ofproto/ofproto_libofproto_la-connmgr.lo \ ofproto/ofproto_libofproto_la-fail-open.lo \ ofproto/ofproto_libofproto_la-in-band.lo \ ofproto/ofproto_libofproto_la-names.lo \ ofproto/ofproto_libofproto_la-netflow.lo \ ofproto/ofproto_libofproto_la-ofproto.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif-ipfix.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif-mirror.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif-monitor.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif-rid.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif-sflow.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif-upcall.lo \ ofproto/ofproto_libofproto_la-ofproto-dpif-xlate.lo \ ofproto/ofproto_libofproto_la-pktbuf.lo \ ofproto/ofproto_libofproto_la-pinsched.lo \ ofproto/ofproto_libofproto_la-tunnel.lo \ ofproto/ofproto_libofproto_la-bundles.lo ofproto_libofproto_la_OBJECTS = $(am_ofproto_libofproto_la_OBJECTS) ofproto_libofproto_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) \ $(ofproto_libofproto_la_LDFLAGS) $(LDFLAGS) -o $@ ovn_lib_libovn_la_LIBADD = am_ovn_lib_libovn_la_OBJECTS = ovn/lib/actions.lo ovn/lib/expr.lo \ ovn/lib/lex.lo nodist_ovn_lib_libovn_la_OBJECTS = ovn/lib/ovn-nb-idl.lo \ ovn/lib/ovn-sb-idl.lo ovn_lib_libovn_la_OBJECTS = $(am_ovn_lib_libovn_la_OBJECTS) \ $(nodist_ovn_lib_libovn_la_OBJECTS) ovn_lib_libovn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(ovn_lib_libovn_la_LDFLAGS) $(LDFLAGS) \ -o $@ ovsdb_libovsdb_la_LIBADD = am_ovsdb_libovsdb_la_OBJECTS = ovsdb/ovsdb_libovsdb_la-column.lo \ ovsdb/ovsdb_libovsdb_la-condition.lo \ ovsdb/ovsdb_libovsdb_la-execution.lo \ ovsdb/ovsdb_libovsdb_la-file.lo \ ovsdb/ovsdb_libovsdb_la-jsonrpc-server.lo \ ovsdb/ovsdb_libovsdb_la-log.lo \ ovsdb/ovsdb_libovsdb_la-mutation.lo \ ovsdb/ovsdb_libovsdb_la-ovsdb.lo \ ovsdb/ovsdb_libovsdb_la-monitor.lo \ ovsdb/ovsdb_libovsdb_la-query.lo \ ovsdb/ovsdb_libovsdb_la-row.lo \ ovsdb/ovsdb_libovsdb_la-server.lo \ ovsdb/ovsdb_libovsdb_la-table.lo \ ovsdb/ovsdb_libovsdb_la-trigger.lo \ ovsdb/ovsdb_libovsdb_la-transaction.lo ovsdb_libovsdb_la_OBJECTS = $(am_ovsdb_libovsdb_la_OBJECTS) ovsdb_libovsdb_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) \ $(ovsdb_libovsdb_la_LDFLAGS) $(LDFLAGS) -o $@ vtep_libvtep_la_LIBADD = nodist_vtep_libvtep_la_OBJECTS = vtep/vtep-idl.lo vtep_libvtep_la_OBJECTS = $(nodist_vtep_libvtep_la_OBJECTS) vtep_libvtep_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(vtep_libvtep_la_LDFLAGS) $(LDFLAGS) \ -o $@ @LINUX_TRUE@am__EXEEXT_1 = utilities/nlmon$(EXEEXT) @DPDK_NETDEV_TRUE@am__EXEEXT_2 = tests/test-dpdkr$(EXEEXT) @LINUX_TRUE@am__EXEEXT_3 = utilities/ovs-vlan-bug-workaround$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) $(sbin_PROGRAMS) am_ovn_controller_vtep_ovn_controller_vtep_OBJECTS = \ ovn/controller-vtep/binding.$(OBJEXT) \ ovn/controller-vtep/gateway.$(OBJEXT) \ ovn/controller-vtep/ovn-controller-vtep.$(OBJEXT) \ ovn/controller-vtep/vtep.$(OBJEXT) ovn_controller_vtep_ovn_controller_vtep_OBJECTS = \ $(am_ovn_controller_vtep_ovn_controller_vtep_OBJECTS) ovn_controller_vtep_ovn_controller_vtep_DEPENDENCIES = \ ovn/lib/libovn.la lib/libopenvswitch.la vtep/libvtep.la am_ovn_controller_ovn_controller_OBJECTS = \ ovn/controller/binding.$(OBJEXT) \ ovn/controller/chassis.$(OBJEXT) \ ovn/controller/encaps.$(OBJEXT) ovn/controller/lflow.$(OBJEXT) \ ovn/controller/ofctrl.$(OBJEXT) \ ovn/controller/pinctrl.$(OBJEXT) \ ovn/controller/patch.$(OBJEXT) \ ovn/controller/ovn-controller.$(OBJEXT) \ ovn/controller/physical.$(OBJEXT) ovn_controller_ovn_controller_OBJECTS = \ $(am_ovn_controller_ovn_controller_OBJECTS) ovn_controller_ovn_controller_DEPENDENCIES = ovn/lib/libovn.la \ lib/libopenvswitch.la am_ovn_northd_ovn_northd_OBJECTS = ovn/northd/ovn-northd.$(OBJEXT) ovn_northd_ovn_northd_OBJECTS = $(am_ovn_northd_ovn_northd_OBJECTS) ovn_northd_ovn_northd_DEPENDENCIES = ovn/lib/libovn.la \ ovsdb/libovsdb.la lib/libopenvswitch.la am_ovn_utilities_ovn_nbctl_OBJECTS = \ ovn/utilities/ovn-nbctl.$(OBJEXT) ovn_utilities_ovn_nbctl_OBJECTS = \ $(am_ovn_utilities_ovn_nbctl_OBJECTS) ovn_utilities_ovn_nbctl_DEPENDENCIES = ovn/lib/libovn.la \ ovsdb/libovsdb.la lib/libopenvswitch.la am_ovn_utilities_ovn_sbctl_OBJECTS = \ ovn/utilities/ovn-sbctl.$(OBJEXT) ovn_utilities_ovn_sbctl_OBJECTS = \ $(am_ovn_utilities_ovn_sbctl_OBJECTS) ovn_utilities_ovn_sbctl_DEPENDENCIES = ovn/lib/libovn.la \ ovsdb/libovsdb.la lib/libopenvswitch.la am_ovsdb_ovsdb_client_OBJECTS = ovsdb/ovsdb-client.$(OBJEXT) ovsdb_ovsdb_client_OBJECTS = $(am_ovsdb_ovsdb_client_OBJECTS) ovsdb_ovsdb_client_DEPENDENCIES = ovsdb/libovsdb.la \ lib/libopenvswitch.la am_ovsdb_ovsdb_server_OBJECTS = ovsdb/ovsdb-server.$(OBJEXT) ovsdb_ovsdb_server_OBJECTS = $(am_ovsdb_ovsdb_server_OBJECTS) ovsdb_ovsdb_server_DEPENDENCIES = ovsdb/libovsdb.la \ lib/libopenvswitch.la am_ovsdb_ovsdb_tool_OBJECTS = ovsdb/ovsdb-tool.$(OBJEXT) ovsdb_ovsdb_tool_OBJECTS = $(am_ovsdb_ovsdb_tool_OBJECTS) ovsdb_ovsdb_tool_DEPENDENCIES = ovsdb/libovsdb.la \ lib/libopenvswitch.la am__tests_ovstest_SOURCES_DIST = tests/ovstest.c tests/ovstest.h \ tests/test-aes128.c tests/test-atomic.c tests/test-bundle.c \ tests/test-byte-order.c tests/test-classifier.c \ tests/test-cmap.c tests/test-csum.c tests/test-flows.c \ tests/test-hash.c tests/test-heap.c tests/test-hindex.c \ tests/test-hmap.c tests/test-json.c tests/test-jsonrpc.c \ tests/test-list.c tests/test-lockfile.c tests/test-multipath.c \ tests/test-netflow.c tests/test-odp.c tests/test-ofpbuf.c \ tests/test-ovn.c tests/test-packets.c tests/test-random.c \ tests/test-reconnect.c tests/test-rstp.c tests/test-sflow.c \ tests/test-sha1.c tests/test-stp.c tests/test-util.c \ tests/test-uuid.c tests/test-bitmap.c tests/test-vconn.c \ tests/test-aa.c tests/test-unix-socket.c \ tests/test-netlink-conntrack.c @WIN32_FALSE@am__objects_13 = tests/test-unix-socket.$(OBJEXT) @LINUX_TRUE@am__objects_14 = tests/test-netlink-conntrack.$(OBJEXT) am_tests_ovstest_OBJECTS = tests/ovstest.$(OBJEXT) \ tests/test-aes128.$(OBJEXT) tests/test-atomic.$(OBJEXT) \ tests/test-bundle.$(OBJEXT) tests/test-byte-order.$(OBJEXT) \ tests/test-classifier.$(OBJEXT) tests/test-cmap.$(OBJEXT) \ tests/test-csum.$(OBJEXT) tests/test-flows.$(OBJEXT) \ tests/test-hash.$(OBJEXT) tests/test-heap.$(OBJEXT) \ tests/test-hindex.$(OBJEXT) tests/test-hmap.$(OBJEXT) \ tests/test-json.$(OBJEXT) tests/test-jsonrpc.$(OBJEXT) \ tests/test-list.$(OBJEXT) tests/test-lockfile.$(OBJEXT) \ tests/test-multipath.$(OBJEXT) tests/test-netflow.$(OBJEXT) \ tests/test-odp.$(OBJEXT) tests/test-ofpbuf.$(OBJEXT) \ tests/test-ovn.$(OBJEXT) tests/test-packets.$(OBJEXT) \ tests/test-random.$(OBJEXT) tests/test-reconnect.$(OBJEXT) \ tests/test-rstp.$(OBJEXT) tests/test-sflow.$(OBJEXT) \ tests/test-sha1.$(OBJEXT) tests/test-stp.$(OBJEXT) \ tests/test-util.$(OBJEXT) tests/test-uuid.$(OBJEXT) \ tests/test-bitmap.$(OBJEXT) tests/test-vconn.$(OBJEXT) \ tests/test-aa.$(OBJEXT) $(am__objects_13) $(am__objects_14) tests_ovstest_OBJECTS = $(am_tests_ovstest_OBJECTS) tests_ovstest_DEPENDENCIES = lib/libopenvswitch.la ovn/lib/libovn.la am__tests_test_dpdkr_SOURCES_DIST = tests/dpdk/ring_client.c @DPDK_NETDEV_TRUE@am_tests_test_dpdkr_OBJECTS = \ @DPDK_NETDEV_TRUE@ tests/dpdk/ring_client.$(OBJEXT) tests_test_dpdkr_OBJECTS = $(am_tests_test_dpdkr_OBJECTS) @DPDK_NETDEV_TRUE@tests_test_dpdkr_DEPENDENCIES = \ @DPDK_NETDEV_TRUE@ lib/libopenvswitch.la $(am__DEPENDENCIES_1) am_tests_test_lib_OBJECTS = tests/test-lib.$(OBJEXT) tests_test_lib_OBJECTS = $(am_tests_test_lib_OBJECTS) tests_test_lib_DEPENDENCIES = lib/libopenvswitch.la am_tests_test_ovsdb_OBJECTS = tests/test-ovsdb.$(OBJEXT) nodist_tests_test_ovsdb_OBJECTS = tests/idltest.$(OBJEXT) tests_test_ovsdb_OBJECTS = $(am_tests_test_ovsdb_OBJECTS) \ $(nodist_tests_test_ovsdb_OBJECTS) tests_test_ovsdb_DEPENDENCIES = ovsdb/libovsdb.la \ lib/libopenvswitch.la am_tests_test_strtok_r_OBJECTS = tests/test-strtok_r.$(OBJEXT) tests_test_strtok_r_OBJECTS = $(am_tests_test_strtok_r_OBJECTS) tests_test_strtok_r_LDADD = $(LDADD) am_tests_test_type_props_OBJECTS = tests/test-type-props.$(OBJEXT) tests_test_type_props_OBJECTS = $(am_tests_test_type_props_OBJECTS) tests_test_type_props_LDADD = $(LDADD) am__utilities_nlmon_SOURCES_DIST = utilities/nlmon.c @LINUX_TRUE@am_utilities_nlmon_OBJECTS = utilities/nlmon.$(OBJEXT) utilities_nlmon_OBJECTS = $(am_utilities_nlmon_OBJECTS) @LINUX_TRUE@utilities_nlmon_DEPENDENCIES = lib/libopenvswitch.la am_utilities_ovs_appctl_OBJECTS = utilities/ovs-appctl.$(OBJEXT) utilities_ovs_appctl_OBJECTS = $(am_utilities_ovs_appctl_OBJECTS) utilities_ovs_appctl_DEPENDENCIES = lib/libopenvswitch.la am_utilities_ovs_benchmark_OBJECTS = \ utilities/ovs-benchmark.$(OBJEXT) utilities_ovs_benchmark_OBJECTS = \ $(am_utilities_ovs_benchmark_OBJECTS) utilities_ovs_benchmark_DEPENDENCIES = lib/libopenvswitch.la am_utilities_ovs_dpctl_OBJECTS = utilities/ovs-dpctl.$(OBJEXT) utilities_ovs_dpctl_OBJECTS = $(am_utilities_ovs_dpctl_OBJECTS) utilities_ovs_dpctl_DEPENDENCIES = lib/libopenvswitch.la am_utilities_ovs_ofctl_OBJECTS = utilities/ovs-ofctl.$(OBJEXT) utilities_ovs_ofctl_OBJECTS = $(am_utilities_ovs_ofctl_OBJECTS) utilities_ovs_ofctl_DEPENDENCIES = ofproto/libofproto.la \ lib/libopenvswitch.la am_utilities_ovs_testcontroller_OBJECTS = \ utilities/ovs-testcontroller.$(OBJEXT) utilities_ovs_testcontroller_OBJECTS = \ $(am_utilities_ovs_testcontroller_OBJECTS) utilities_ovs_testcontroller_DEPENDENCIES = lib/libopenvswitch.la \ $(am__DEPENDENCIES_1) am__utilities_ovs_vlan_bug_workaround_SOURCES_DIST = \ utilities/ovs-vlan-bug-workaround.c @LINUX_TRUE@am_utilities_ovs_vlan_bug_workaround_OBJECTS = \ @LINUX_TRUE@ utilities/ovs-vlan-bug-workaround.$(OBJEXT) utilities_ovs_vlan_bug_workaround_OBJECTS = \ $(am_utilities_ovs_vlan_bug_workaround_OBJECTS) @LINUX_TRUE@utilities_ovs_vlan_bug_workaround_DEPENDENCIES = \ @LINUX_TRUE@ lib/libopenvswitch.la am_utilities_ovs_vsctl_OBJECTS = utilities/ovs-vsctl.$(OBJEXT) utilities_ovs_vsctl_OBJECTS = $(am_utilities_ovs_vsctl_OBJECTS) utilities_ovs_vsctl_DEPENDENCIES = lib/libopenvswitch.la am_vswitchd_ovs_vswitchd_OBJECTS = vswitchd/bridge.$(OBJEXT) \ vswitchd/ovs-vswitchd.$(OBJEXT) \ vswitchd/system-stats.$(OBJEXT) vswitchd/xenserver.$(OBJEXT) vswitchd_ovs_vswitchd_OBJECTS = $(am_vswitchd_ovs_vswitchd_OBJECTS) vswitchd_ovs_vswitchd_DEPENDENCIES = ofproto/libofproto.la \ lib/libsflow.la lib/libopenvswitch.la vswitchd_ovs_vswitchd_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \ $(AM_CFLAGS) $(CFLAGS) $(vswitchd_ovs_vswitchd_LDFLAGS) \ $(LDFLAGS) -o $@ am_vtep_vtep_ctl_OBJECTS = vtep/vtep-ctl.$(OBJEXT) vtep_vtep_ctl_OBJECTS = $(am_vtep_vtep_ctl_OBJECTS) vtep_vtep_ctl_DEPENDENCIES = vtep/libvtep.la lib/libopenvswitch.la SCRIPTS = $(bin_SCRIPTS) $(completion_SCRIPTS) $(dist_noinst_SCRIPTS) \ $(dist_pkgdata_SCRIPTS) $(dist_sbin_SCRIPTS) \ $(dist_scripts_SCRIPTS) $(noinst_SCRIPTS) $(sbin_SCRIPTS) \ $(scripts_SCRIPTS) AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/build-aux/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(lib_libopenvswitch_la_SOURCES) \ $(nodist_lib_libopenvswitch_la_SOURCES) \ $(lib_libsflow_la_SOURCES) $(ofproto_libofproto_la_SOURCES) \ $(ovn_lib_libovn_la_SOURCES) \ $(nodist_ovn_lib_libovn_la_SOURCES) \ $(ovsdb_libovsdb_la_SOURCES) $(nodist_vtep_libvtep_la_SOURCES) \ $(ovn_controller_vtep_ovn_controller_vtep_SOURCES) \ $(ovn_controller_ovn_controller_SOURCES) \ $(ovn_northd_ovn_northd_SOURCES) \ $(ovn_utilities_ovn_nbctl_SOURCES) \ $(ovn_utilities_ovn_sbctl_SOURCES) \ $(ovsdb_ovsdb_client_SOURCES) $(ovsdb_ovsdb_server_SOURCES) \ $(ovsdb_ovsdb_tool_SOURCES) $(tests_ovstest_SOURCES) \ $(tests_test_dpdkr_SOURCES) $(tests_test_lib_SOURCES) \ $(tests_test_ovsdb_SOURCES) $(nodist_tests_test_ovsdb_SOURCES) \ $(tests_test_strtok_r_SOURCES) \ $(tests_test_type_props_SOURCES) $(utilities_nlmon_SOURCES) \ $(utilities_ovs_appctl_SOURCES) \ $(utilities_ovs_benchmark_SOURCES) \ $(utilities_ovs_dpctl_SOURCES) $(utilities_ovs_ofctl_SOURCES) \ $(utilities_ovs_testcontroller_SOURCES) \ $(utilities_ovs_vlan_bug_workaround_SOURCES) \ $(utilities_ovs_vsctl_SOURCES) \ $(vswitchd_ovs_vswitchd_SOURCES) $(vtep_vtep_ctl_SOURCES) DIST_SOURCES = $(am__lib_libopenvswitch_la_SOURCES_DIST) \ $(lib_libsflow_la_SOURCES) $(ofproto_libofproto_la_SOURCES) \ $(ovn_lib_libovn_la_SOURCES) $(ovsdb_libovsdb_la_SOURCES) \ $(ovn_controller_vtep_ovn_controller_vtep_SOURCES) \ $(ovn_controller_ovn_controller_SOURCES) \ $(ovn_northd_ovn_northd_SOURCES) \ $(ovn_utilities_ovn_nbctl_SOURCES) \ $(ovn_utilities_ovn_sbctl_SOURCES) \ $(ovsdb_ovsdb_client_SOURCES) $(ovsdb_ovsdb_server_SOURCES) \ $(ovsdb_ovsdb_tool_SOURCES) $(am__tests_ovstest_SOURCES_DIST) \ $(am__tests_test_dpdkr_SOURCES_DIST) $(tests_test_lib_SOURCES) \ $(tests_test_ovsdb_SOURCES) $(tests_test_strtok_r_SOURCES) \ $(tests_test_type_props_SOURCES) \ $(am__utilities_nlmon_SOURCES_DIST) \ $(utilities_ovs_appctl_SOURCES) \ $(utilities_ovs_benchmark_SOURCES) \ $(utilities_ovs_dpctl_SOURCES) $(utilities_ovs_ofctl_SOURCES) \ $(utilities_ovs_testcontroller_SOURCES) \ $(am__utilities_ovs_vlan_bug_workaround_SOURCES_DIST) \ $(utilities_ovs_vsctl_SOURCES) \ $(vswitchd_ovs_vswitchd_SOURCES) $(vtep_vtep_ctl_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ install-exec-recursive install-html-recursive \ install-info-recursive install-pdf-recursive \ install-ps-recursive install-recursive installcheck-recursive \ installdirs-recursive pdf-recursive ps-recursive \ tags-recursive uninstall-recursive am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 man7dir = $(mandir)/man7 man8dir = $(mandir)/man8 NROFF = nroff MANS = $(dist_man_MANS) $(man_MANS) DATA = $(dist_pkgdata_DATA) $(dist_scripts_DATA) \ $(nobase_pkgdata_DATA) $(noinst_DATA) $(pkgconfig_DATA) \ $(pkgdata_DATA) $(scripts_DATA) am__noinst_HEADERS_DIST = CONTRIBUTING.md CodingStyle.md DESIGN.md \ FAQ.md INSTALL.md INSTALL.Debian.md INSTALL.Docker.md \ INSTALL.DPDK.md INSTALL.Fedora.md INSTALL.KVM.md \ INSTALL.Libvirt.md INSTALL.NetBSD.md INSTALL.RHEL.md \ INSTALL.SELinux.md INSTALL.SSL.md INSTALL.XenServer.md \ INSTALL.userspace.md INSTALL.Windows.md IntegrationGuide.md \ OPENFLOW-1.1+.md PORTING.md README.md README-lisp.md \ README-native-tunneling.md REPORTING-BUGS.md SECURITY.md \ TODO.md WHY-OVS.md utilities/ovs-command-bashcomp.INSTALL.md \ third-party/README.md tutorial/Tutorial.md \ tutorial/OVN-Tutorial.md vtep/README.ovs-vtep.md NOTICE \ .travis.yml .travis/build.sh .travis/prepare.sh appveyor.yml \ boot.sh build-aux/cccl build-aux/cksum-schema-check \ build-aux/dist-docs build-aux/sodepends.pl \ build-aux/soexpand.pl build-aux/xml2nroff lib/common.man \ lib/common-syn.man lib/coverage-unixctl.man lib/daemon.man \ lib/daemon-syn.man lib/db-ctl-base.man lib/dpctl.man \ lib/memory-unixctl.man lib/ofp-version.man lib/ovs.tmac \ lib/service.man lib/service-syn.man lib/ssl-bootstrap.man \ lib/ssl-bootstrap-syn.man lib/ssl-peer-ca-cert.man \ lib/ssl-peer-ca-cert-syn.man lib/ssl.man lib/ssl-syn.man \ lib/table.man lib/unixctl.man lib/unixctl-syn.man \ lib/vconn-active.man lib/vconn-passive.man \ lib/vlog-unixctl.man lib/vlog-syn.man lib/vlog.man \ ofproto/ofproto-unixctl.man ofproto/ofproto-dpif-unixctl.man \ ofproto/ofproto-tnl-unixctl.man utilities/ovs-vlan-bugs.man \ ovsdb/remote-active.man ovsdb/remote-passive.man \ utilities/ovs-appctl.8.in utilities/ovs-benchmark.1.in \ utilities/ovs-testcontroller.8.in utilities/ovs-ctl.8 \ utilities/ovs-dpctl.8.in utilities/ovs-dpctl-top.8.in \ utilities/ovs-l3ping.8.in utilities/ovs-ofctl.8.in \ utilities/ovs-parse-backtrace.8 utilities/ovs-pcap.1.in \ utilities/ovs-pki.8.in utilities/ovs-tcpundump.1.in \ utilities/ovs-vlan-bug-workaround.8.in utilities/ovs-test.8.in \ utilities/ovs-vlan-test.8.in utilities/ovs-vsctl.8.in \ utilities/bugtool/ovs-bugtool.8.in vswitchd/ovs-vswitchd.8.in \ ovsdb/ovsdb-tool.1.in ovsdb/ovsdb-client.1.in \ ovsdb/ovsdb-server.1.in ovsdb/ovsdb-idlc.1 vtep/vtep-ctl.8.in \ ovn/utilities/ovn-sbctl.8.in Vagrantfile \ build-aux/thread-safety-blacklist \ Documentation/group-selection-method-property.txt \ m4/absolute-header.m4 m4/include_next.m4 lib/stdio.h.in \ lib/string.h.in lib/dh1024.pem lib/dh2048.pem lib/dh4096.pem \ lib/dirs.c.in lib/vswitch-idl.ann build-aux/extract-ofp-fields \ build-aux/extract-ofp-actions build-aux/extract-ofp-errors \ build-aux/extract-ofp-msgs ofproto/ipfix.xml \ ofproto/ipfix-enterprise-entities.def utilities/ovs-sim.in \ utilities/ovs-sim.1.xml utilities/ovs-appctl-bashcomp.bash \ utilities/ovs-check-dead-ifs.in utilities/ovs-ctl.in \ utilities/ovs-dev.py utilities/ovs-docker \ utilities/ovs-dpctl-top.in utilities/ovs-l3ping.in \ utilities/ovs-lib.in utilities/ovs-parse-backtrace.in \ utilities/ovs-pcap.in utilities/ovs-pipegen.py \ utilities/ovs-pki.in utilities/ovs-save \ utilities/ovs-tcpundump.in utilities/ovs-test.in \ utilities/ovs-vlan-test.in utilities/ovs-vsctl-bashcomp.bash \ utilities/qemu-wrap.py \ utilities/bugtool/plugins/kernel-info/openvswitch.xml \ utilities/bugtool/plugins/network-status/openvswitch.xml \ utilities/bugtool/plugins/system-configuration.xml \ utilities/bugtool/plugins/system-logs/openvswitch.xml \ utilities/bugtool/plugins/system-configuration/openvswitch.xml \ utilities/bugtool/ovs-bugtool-bfd-show \ utilities/bugtool/ovs-bugtool-cfm-show \ utilities/bugtool/ovs-bugtool-coverage-show \ utilities/bugtool/ovs-bugtool-fdb-show \ utilities/bugtool/ovs-bugtool-lacp-show \ utilities/bugtool/ovs-bugtool-list-dbs \ utilities/bugtool/ovs-bugtool-memory-show \ utilities/bugtool/ovs-bugtool-tc-class-show \ utilities/bugtool/ovs-bugtool-vsctl-show \ utilities/bugtool/ovs-bugtool-ovsdb-dump \ utilities/bugtool/ovs-bugtool-daemons-ver \ utilities/bugtool/ovs-bugtool-ovs-ofctl-show \ utilities/bugtool/ovs-bugtool-ovs-ofctl-dump-flows \ utilities/bugtool/ovs-bugtool-ovs-appctl-dpif \ utilities/bugtool/ovs-bugtool-bond-show \ utilities/bugtool/ovs-bugtool-conntrack-dump \ utilities/bugtool/ovs-bugtool.in tests/ovsdb-macros.at \ tests/ovs-macros.at tests/ofproto-macros.at tests/testsuite.at \ tests/completion.at tests/library.at tests/heap.at \ tests/bundle.at tests/classifier.at tests/check-structs.at \ tests/daemon.at tests/daemon-py.at tests/ofp-actions.at \ tests/ofp-print.at tests/ofp-util.at tests/ofp-errors.at \ tests/ovs-ofctl.at tests/odp.at tests/mpls-xlate.at \ tests/multipath.at tests/bfd.at tests/cfm.at tests/lacp.at \ tests/lib.at tests/learn.at tests/vconn.at tests/file_name.at \ tests/aes128.at tests/unixctl-py.at tests/uuid.at \ tests/json.at tests/jsonrpc.at tests/jsonrpc-py.at \ tests/tunnel.at tests/tunnel-push-pop.at \ tests/tunnel-push-pop-ipv6.at tests/lockfile.at \ tests/reconnect.at tests/ovs-vswitchd.at tests/dpif-netdev.at \ tests/dpctl.at tests/ofproto-dpif.at tests/bridge.at \ tests/vlan-splinters.at tests/ofproto.at tests/ovsdb.at \ tests/ovsdb-log.at tests/ovsdb-types.at tests/ovsdb-data.at \ tests/ovsdb-column.at tests/ovsdb-table.at tests/ovsdb-row.at \ tests/ovsdb-schema.at tests/ovsdb-condition.at \ tests/ovsdb-mutation.at tests/ovsdb-query.at \ tests/ovsdb-transaction.at tests/ovsdb-execution.at \ tests/ovsdb-trigger.at tests/ovsdb-tool.at \ tests/ovsdb-server.at tests/ovsdb-monitor.at \ tests/ovsdb-idl.at tests/ovs-vsctl.at \ tests/ovs-monitor-ipsec.at tests/ovs-xapi-sync.at tests/stp.at \ tests/rstp.at tests/interface-reconfigure.at tests/vlog.at \ tests/vtep-ctl.at tests/auto-attach.at tests/ovn.at \ tests/ovn-nbctl.at tests/ovn-sbctl.at tests/ovn-controller.at \ tests/ovn-controller-vtep.at tests/system-common-macros.at \ tests/system-traffic.at tests/system-kmod-testsuite.at \ tests/system-kmod-macros.at \ tests/system-userspace-testsuite.at \ tests/system-userspace-macros.at $(srcdir)/tests/testsuite \ $(srcdir)/tests/system-kmod-testsuite \ $(srcdir)/tests/system-userspace-testsuite tests/atlocal.in \ $(srcdir)/package.m4 $(srcdir)/tests/testsuite.patch \ tests/valgrind-wrapper.in tests/glibc.supp tests/openssl.supp \ tests/run-oftest tests/run-ryu tests/uuidfilt.pl \ tests/ovsdb-monitor-sort.pl tests/idltest.ovsschema \ tests/idltest.ann tests/idltest2.ovsschema tests/appctl.py \ tests/test-daemon.py tests/test-json.py tests/test-jsonrpc.py \ tests/test-l7.py tests/test-ovsdb.py tests/test-reconnect.py \ tests/MockXenAPI.py tests/test-unix-socket.py \ tests/test-unixctl.py tests/test-vlog.py \ build-aux/extract-odp-netlink-h build-aux/check-structs \ third-party/ofp-tcpdump.patch debian/changelog debian/compat \ debian/control debian/control.modules.in debian/copyright \ debian/copyright.in debian/dkms.conf.in debian/dirs \ debian/openvswitch-common.dirs debian/openvswitch-common.docs \ debian/openvswitch-common.install \ debian/openvswitch-common.manpages \ debian/openvswitch-datapath-module-_KVERS_.postinst.modules.in \ debian/openvswitch-datapath-dkms.postinst \ debian/openvswitch-datapath-dkms.prerm \ debian/openvswitch-datapath-source.README.Debian \ debian/openvswitch-datapath-source.copyright \ debian/openvswitch-datapath-source.dirs \ debian/openvswitch-datapath-source.install \ debian/openvswitch-ipsec.dirs debian/openvswitch-ipsec.init \ debian/openvswitch-ipsec.install debian/openvswitch-pki.dirs \ debian/openvswitch-pki.postinst debian/openvswitch-pki.postrm \ debian/openvswitch-switch.README.Debian \ debian/openvswitch-switch.dirs debian/openvswitch-switch.init \ debian/openvswitch-switch.install \ debian/openvswitch-switch.logrotate \ debian/openvswitch-switch.manpages \ debian/openvswitch-switch.postinst \ debian/openvswitch-switch.postrm \ debian/openvswitch-switch.template \ debian/openvswitch-switch.links debian/openvswitch-test.dirs \ debian/openvswitch-test.install \ debian/openvswitch-test.manpages \ debian/openvswitch-testcontroller.README.Debian \ debian/openvswitch-testcontroller.default \ debian/openvswitch-testcontroller.dirs \ debian/openvswitch-testcontroller.init \ debian/openvswitch-testcontroller.install \ debian/openvswitch-testcontroller.manpages \ debian/openvswitch-testcontroller.postinst \ debian/openvswitch-testcontroller.postrm \ debian/openvswitch-vtep.default debian/openvswitch-vtep.dirs \ debian/openvswitch-vtep.init debian/openvswitch-vtep.install \ debian/openvswitch-vtep.manpages debian/ovs-monitor-ipsec \ debian/python-openvswitch.dirs \ debian/python-openvswitch.install debian/rules \ debian/rules.modules debian/ifupdown.sh debian/source/format \ vswitchd/INTERNALS vswitchd/vswitch.ovsschema \ vswitchd/vswitch.xml ovsdb/ovsdb-idlc.in ovsdb/ovsdb-doc \ ovsdb/ovsdb-dot.in ovsdb/dot2pic rhel/README.RHEL \ rhel/automake.mk rhel/etc_init.d_openvswitch \ rhel/etc_logrotate.d_openvswitch \ rhel/etc_sysconfig_network-scripts_ifdown-ovs \ rhel/etc_sysconfig_network-scripts_ifup-ovs \ rhel/openvswitch-dkms.spec rhel/openvswitch-dkms.spec.in \ rhel/openvswitch-kmod-rhel6.spec \ rhel/openvswitch-kmod-rhel6.spec.in \ rhel/openvswitch-kmod.files rhel/openvswitch-kmod-fedora.spec \ rhel/openvswitch-kmod-fedora.spec.in rhel/openvswitch.spec \ rhel/openvswitch.spec.in rhel/openvswitch-fedora.spec \ rhel/openvswitch-fedora.spec.in \ rhel/usr_share_openvswitch_scripts_sysconfig.template \ rhel/usr_share_openvswitch_scripts_systemd_sysconfig.template \ rhel/usr_lib_systemd_system_openvswitch.service \ rhel/usr_lib_systemd_system_openvswitch-nonetwork.service \ rhel/usr_lib_systemd_system_ovn-controller.service \ rhel/usr_lib_systemd_system_ovn-controller-vtep.service \ rhel/usr_lib_systemd_system_ovn-northd.service xenserver/GPLv2 \ xenserver/LICENSE xenserver/README xenserver/automake.mk \ xenserver/etc_init.d_openvswitch \ xenserver/etc_init.d_openvswitch-xapi-update \ xenserver/etc_logrotate.d_openvswitch \ xenserver/etc_profile.d_openvswitch.sh \ xenserver/etc_xapi.d_plugins_openvswitch-cfg-update \ xenserver/etc_xensource_scripts_vif \ xenserver/openvswitch-xen.spec \ xenserver/openvswitch-xen.spec.in \ xenserver/opt_xensource_libexec_InterfaceReconfigure.py \ xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py \ xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py \ xenserver/opt_xensource_libexec_interface-reconfigure \ xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py \ xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync \ xenserver/usr_share_openvswitch_scripts_sysconfig.template \ python/build/__init__.py python/build/nroff.py \ python/README.rst python/setup.py python/ovs/__init__.py \ python/ovs/daemon.py python/ovs/db/__init__.py \ python/ovs/db/data.py python/ovs/db/error.py \ python/ovs/db/idl.py python/ovs/db/parser.py \ python/ovs/db/schema.py python/ovs/db/types.py \ python/ovs/fatal_signal.py python/ovs/json.py \ python/ovs/jsonrpc.py python/ovs/ovsuuid.py \ python/ovs/poller.py python/ovs/process.py \ python/ovs/reconnect.py python/ovs/socket_util.py \ python/ovs/stream.py python/ovs/timeval.py \ python/ovs/unixctl/__init__.py python/ovs/unixctl/client.py \ python/ovs/unixctl/server.py python/ovs/util.py \ python/ovs/version.py python/ovs/vlog.py python/ovs/dirs.py \ python/ovstest/__init__.py python/ovstest/args.py \ python/ovstest/rpcserver.py python/ovstest/tcp.py \ python/ovstest/tests.py python/ovstest/udp.py \ python/ovstest/util.py python/ovstest/vswitch.py \ python/ovs/dirs.py.template tutorial/ovs-sandbox \ tutorial/t-setup tutorial/t-stage0 tutorial/t-stage1 \ tutorial/t-stage2 tutorial/t-stage3 tutorial/t-stage4 \ tutorial/ovn/env1/setup.sh tutorial/ovn/env1/packet1.sh \ tutorial/ovn/env1/packet2.sh \ tutorial/ovn/env1/add-third-port.sh tutorial/ovn/env2/setup.sh \ tutorial/ovn/env2/packet1.sh tutorial/ovn/env2/packet2.sh \ tutorial/ovn/env3/setup.sh tutorial/ovn/env3/packet1.sh \ tutorial/ovn/env3/packet2.sh tutorial/ovn/env4/setup1.sh \ tutorial/ovn/env4/setup2.sh tutorial/ovn/env4/packet1.sh \ tutorial/ovn/env4/packet2.sh tutorial/ovn/env4/packet3.sh \ tutorial/ovn/env4/packet4.sh tutorial/ovn/env4/packet5.sh \ tutorial/ovn/env5/setup.sh tutorial/ovn/env5/packet1.sh \ tutorial/ovn/env5/packet2.sh tutorial/ovn/env6/setup.sh \ tutorial/ovn/env6/add-acls.sh vtep/vtep-idl.ann vtep/ovs-vtep \ vtep/vtep.ovsschema vtep/vtep.xml datapath-windows/CodingStyle \ datapath-windows/DESIGN \ datapath-windows/Package/package.VcxProj \ datapath-windows/Package/package.VcxProj.user \ datapath-windows/include/OvsDpInterfaceExt.h \ datapath-windows/misc/OVS.psm1 \ datapath-windows/misc/install.cmd \ datapath-windows/misc/uninstall.cmd \ datapath-windows/ovsext.sln datapath-windows/ovsext/Actions.c \ datapath-windows/ovsext/Atomic.h \ datapath-windows/ovsext/BufferMgmt.c \ datapath-windows/ovsext/BufferMgmt.h \ datapath-windows/ovsext/Checksum.c \ datapath-windows/ovsext/Checksum.h \ datapath-windows/ovsext/Datapath.c \ datapath-windows/ovsext/Datapath.h \ datapath-windows/ovsext/Debug.c \ datapath-windows/ovsext/Debug.h \ datapath-windows/ovsext/DpInternal.h \ datapath-windows/ovsext/Driver.c \ datapath-windows/ovsext/Ethernet.h \ datapath-windows/ovsext/Event.c \ datapath-windows/ovsext/Event.h datapath-windows/ovsext/Flow.c \ datapath-windows/ovsext/Flow.h datapath-windows/ovsext/Gre.h \ datapath-windows/ovsext/Gre.c \ datapath-windows/ovsext/IpHelper.c \ datapath-windows/ovsext/IpHelper.h \ datapath-windows/ovsext/Jhash.c \ datapath-windows/ovsext/Jhash.h \ datapath-windows/ovsext/NetProto.h \ datapath-windows/ovsext/Netlink/Netlink.c \ datapath-windows/ovsext/Netlink/Netlink.h \ datapath-windows/ovsext/Netlink/NetlinkBuf.c \ datapath-windows/ovsext/Netlink/NetlinkBuf.h \ datapath-windows/ovsext/Netlink/NetlinkError.h \ datapath-windows/ovsext/Netlink/NetlinkProto.h \ datapath-windows/ovsext/Oid.c datapath-windows/ovsext/Oid.h \ datapath-windows/ovsext/PacketIO.c \ datapath-windows/ovsext/PacketIO.h \ datapath-windows/ovsext/PacketParser.c \ datapath-windows/ovsext/PacketParser.h \ datapath-windows/ovsext/Stt.c datapath-windows/ovsext/Stt.h \ datapath-windows/ovsext/Switch.c \ datapath-windows/ovsext/Switch.h \ datapath-windows/ovsext/Tunnel.c \ datapath-windows/ovsext/Tunnel.h \ datapath-windows/ovsext/TunnelFilter.c \ datapath-windows/ovsext/TunnelIntf.h \ datapath-windows/ovsext/Types.h datapath-windows/ovsext/User.c \ datapath-windows/ovsext/User.h datapath-windows/ovsext/Util.c \ datapath-windows/ovsext/Util.h datapath-windows/ovsext/Vport.c \ datapath-windows/ovsext/Vport.h \ datapath-windows/ovsext/Vxlan.c \ datapath-windows/ovsext/Vxlan.h \ datapath-windows/ovsext/ovsext.inf \ datapath-windows/ovsext/ovsext.rc \ datapath-windows/ovsext/ovsext.vcxproj \ datapath-windows/ovsext/ovsext.vcxproj.user \ datapath-windows/ovsext/precomp.h \ datapath-windows/ovsext/precompsrc.c \ datapath-windows/ovsext/resource.h \ $(srcdir)/build-aux/extract-odp-netlink-windows-dp-h \ windows/.gitignore windows/automake.mk windows/README.rst \ windows/ovs-windows-installer.sln \ windows/ovs-windows-installer/Actions/OVSActions.js \ windows/ovs-windows-installer/CustomActions.wxs \ windows/ovs-windows-installer/Dialogs/BeginningDialog.wxs \ windows/ovs-windows-installer/Dialogs/MyEndDialog.wxs \ windows/ovs-windows-installer/Dialogs/MyTroubleshootDialog.wxs \ windows/ovs-windows-installer/Dialogs/UserFinishDialog.wxs \ windows/ovs-windows-installer/License.rtf \ windows/ovs-windows-installer/Product.wxs \ windows/ovs-windows-installer/UI.wxs \ windows/ovs-windows-installer/images/bannrbmp.bmp \ windows/ovs-windows-installer/images/dlgbmp.bmp \ windows/ovs-windows-installer/ovs-windows-installer.wixproj \ ovn/ovn-sb.ovsschema ovn/ovn-sb.xml ovn/ovn-nb.ovsschema \ ovn/ovn-nb.xml ovn/ovn-architecture.7.xml ovn/TODO \ ovn/CONTAINERS.OpenStack.md ovn/OVN-GW-HA.md \ ovn/controller/ovn-controller.8.xml \ ovn/controller-vtep/ovn-controller-vtep.8.xml \ ovn/lib/ovn-sb-idl.ann ovn/lib/ovn-nb-idl.ann \ ovn/northd/ovn-northd.8.xml ovn/utilities/ovn-ctl \ ovn/utilities/ovn-ctl.8.xml \ ovn/utilities/ovn-docker-overlay-driver \ ovn/utilities/ovn-docker-underlay-driver \ ovn/utilities/ovn-nbctl.8.xml selinux/openvswitch-custom.te \ include/sparse/arpa/inet.h include/sparse/assert.h \ include/sparse/bmi2intrin.h include/sparse/emmintrin.h \ include/sparse/math.h include/sparse/netinet/in.h \ include/sparse/netinet/ip6.h include/sparse/netpacket/packet.h \ include/sparse/pthread.h include/sparse/rte_atomic.h \ include/sparse/rte_lcore.h include/sparse/rte_vect.h \ include/sparse/sys/socket.h include/sparse/sys/wait.h \ include/windows/arpa/inet.h include/windows/dirent.h \ include/windows/getopt.h include/windows/linux/pkt_sched.h \ include/windows/linux/types.h include/windows/net/if.h \ include/windows/netdb.h include/windows/netpacket/packet.h \ include/windows/netinet/icmp6.h include/windows/netinet/in.h \ include/windows/netinet/in_systm.h \ include/windows/netinet/ip.h include/windows/netinet/ip6.h \ include/windows/netinet/tcp.h include/windows/poll.h \ include/windows/strings.h include/windows/syslog.h \ include/windows/sys/epoll.h include/windows/sys/ioctl.h \ include/windows/sys/resource.h include/windows/sys/socket.h \ include/windows/sys/time.h include/windows/sys/uio.h \ include/windows/sys/un.h include/windows/sys/wait.h \ include/windows/unistd.h include/windows/windefs.h HEADERS = $(noinst_HEADERS) $(openflowinclude_HEADERS) \ $(openvswitchinclude_HEADERS) RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \ distclean-recursive maintainer-clean-recursive am__recursive_targets = \ $(RECURSIVE_TARGETS) \ $(RECURSIVE_CLEAN_TARGETS) \ $(am__extra_recursive_targets) AM_RECURSIVE_TARGETS = $(am__recursive_targets:-recursive=) TAGS CTAGS \ cscope distdir dist dist-all distcheck am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) \ $(LISP)config.h.in # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags CSCOPE = cscope DIST_SUBDIRS = $(SUBDIRS) DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) distdir = $(PACKAGE)-$(VERSION) top_distdir = $(distdir) am__remove_distdir = \ if test -d "$(distdir)"; then \ find "$(distdir)" -type d ! -perm -200 -exec chmod u+w {} ';' \ && rm -rf "$(distdir)" \ || { sleep 5 && rm -rf "$(distdir)"; }; \ else :; fi am__post_remove_distdir = $(am__remove_distdir) am__relativize = \ dir0=`pwd`; \ sed_first='s,^\([^/]*\)/.*$$,\1,'; \ sed_rest='s,^[^/]*/*,,'; \ sed_last='s,^.*/\([^/]*\)$$,\1,'; \ sed_butlast='s,/*[^/]*$$,,'; \ while test -n "$$dir1"; do \ first=`echo "$$dir1" | sed -e "$$sed_first"`; \ if test "$$first" != "."; then \ if test "$$first" = ".."; then \ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \ else \ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \ if test "$$first2" = "$$first"; then \ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \ else \ dir2="../$$dir2"; \ fi; \ dir0="$$dir0"/"$$first"; \ fi; \ fi; \ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \ done; \ reldir="$$dir2" DIST_ARCHIVES = $(distdir).tar.gz GZIP_ENV = --best DIST_TARGETS = dist-gzip distuninstallcheck_listfiles = find . -type f -print am__distuninstallcheck_listfiles = $(distuninstallcheck_listfiles) \ | sed 's|^\./|$(prefix)/|' | grep -v '$(infodir)/dir$$' distcleancheck_listfiles = find . -type f -print ACLOCAL = @ACLOCAL@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOM4TE = @AUTOM4TE@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CAPNG_LDADD = @CAPNG_LDADD@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CGCCFLAGS = @CGCCFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DBDIR = @DBDIR@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DPDK_vswitchd_LDFLAGS = @DPDK_vswitchd_LDFLAGS@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ HAVE_LIBCAPNG = @HAVE_LIBCAPNG@ HAVE_OPENSSL = @HAVE_OPENSSL@ HAVE_PYTHON = @HAVE_PYTHON@ INCLUDE_NEXT = @INCLUDE_NEXT@ INCLUDE_NEXT_AS_FIRST_DIRECTIVE = @INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ KARCH = @KARCH@ KBUILD = @KBUILD@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LOGDIR = @LOGDIR@ LTLIBOBJS = @LTLIBOBJS@ LT_AGE = @LT_AGE@ LT_CURRENT = @LT_CURRENT@ LT_REVISION = @LT_REVISION@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ MSVC64_LDFLAGS = @MSVC64_LDFLAGS@ MSVC_CFLAGS = @MSVC_CFLAGS@ NEXT_AS_FIRST_DIRECTIVE_STDIO_H = @NEXT_AS_FIRST_DIRECTIVE_STDIO_H@ NEXT_AS_FIRST_DIRECTIVE_STRING_H = @NEXT_AS_FIRST_DIRECTIVE_STRING_H@ NEXT_STDIO_H = @NEXT_STDIO_H@ NEXT_STRING_H = @NEXT_STRING_H@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ OVS_CFLAGS = @OVS_CFLAGS@ OVS_LDFLAGS = @OVS_LDFLAGS@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ PKIDIR = @PKIDIR@ PRAGMA_COLUMNS = @PRAGMA_COLUMNS@ PRAGMA_SYSTEM_HEADER = @PRAGMA_SYSTEM_HEADER@ PTHREAD_INCLUDES = @PTHREAD_INCLUDES@ PTHREAD_LDFLAGS = @PTHREAD_LDFLAGS@ PTHREAD_LIBS = @PTHREAD_LIBS@ PTHREAD_WIN32_DIR_DLL = @PTHREAD_WIN32_DIR_DLL@ PTHREAD_WIN32_DIR_DLL_WIN_FORM = @PTHREAD_WIN32_DIR_DLL_WIN_FORM@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ RUNDIR = @RUNDIR@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPARSE = @SPARSE@ SPARSEFLAGS = @SPARSEFLAGS@ SPARSE_EXTRA_INCLUDES = @SPARSE_EXTRA_INCLUDES@ SSL_INCLUDES = @SSL_INCLUDES@ SSL_LDFLAGS = @SSL_LDFLAGS@ SSL_LIBS = @SSL_LIBS@ STRIP = @STRIP@ VERSION = @VERSION@ VSTUDIO_CONFIG = @VSTUDIO_CONFIG@ WARNING_FLAGS = @WARNING_FLAGS@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ AUTOMAKE_OPTIONS = foreign subdir-objects ACLOCAL_AMFLAGS = -I m4 SUBDIRS = datapath AM_CPPFLAGS = $(SSL_CFLAGS) $(am__append_1) -I $(top_srcdir)/include \ -I $(top_builddir)/include -I $(top_srcdir)/lib -I \ $(top_builddir)/lib $(SSL_INCLUDES) $(am__append_4) AM_LDFLAGS = $(SSL_LDFLAGS) $(OVS_LDFLAGS) $(am__append_2) AM_CFLAGS = -Wstrict-prototypes $(WARNING_FLAGS) $(OVS_CFLAGS) \ $(am__append_3) $(am__append_5) @WIN32_FALSE@psep = ":" @WIN32_TRUE@psep = ";" # PYTHONDONTWRITEBYTECODE=yes keeps Python from creating .pyc and .pyo # files. Creating .py[co] works OK for any given version of Open # vSwitch, but it causes trouble if you switch from a version with # foo/__init__.py into an (older) version with plain foo.py, since # foo/__init__.pyc will cause Python to ignore foo.py. run_python = \ PYTHONPATH=$(top_srcdir)/python$(psep)$$PYTHONPATH \ PYTHONDONTWRITEBYTECODE=yes $(PYTHON) # Check that every .c file includes . # Check for printf() type modifiers that MSVC doesn't support. # Check that certain data structures are always declared "static". # Check that assert.h is not used outside a whitelist of files. # Check that LITTLE_ENDIAN and BIG_ENDIAN are not used unless BYTE_ORDER is # also mentioned. ( always defines the former two constants. They # must be compared to BYTE_ORDER to get the machine's correct endianness. But # it is better to use WORDS_BIGENDIAN.) # Version checking for vswitch.ovsschema. # Version checking for vtep.ovsschema. # Version checking for ovn-nb.ovsschema. # Version checking for ovn-sb.ovsschema. ALL_LOCAL = $(am__append_6) config-h-check printf-check static-check \ check-assert-h-usage check-endian thread-safety-check \ $(am__append_8) $(am__append_10) $(am__append_47) \ check-debian-changelog-version \ vswitchd/vswitch.ovsschema.stamp \ $(srcdir)/python/ovs/version.py $(srcdir)/python/ovs/dirs.py \ vtep/vtep.ovsschema.stamp ovn/ovn-nb.ovsschema.stamp \ ovn/ovn-sb.ovsschema.stamp BUILT_SOURCES = ofproto/ipfix-entities.def include/odp-netlink.h \ $(OVSIDL_BUILT) $(am__append_50) # Clean up generated files from older OVS versions. (This is important so that # #include "vswitch-idl.h" doesn't get the wrong copy.) CLEANFILES = $(am__append_7) $(am__append_9) manpage-dep-check \ $(nodist_lib_libopenvswitch_la_SOURCES) lib/meta-flow.inc \ lib/nx-match.inc lib/ofp-actions.inc1 lib/ofp-actions.inc2 \ lib/ofp-errors.inc lib/ofp-msgs.inc ofproto/ipfix-entities.def \ $(am__append_32) $(valgrind_wrappers) $(am__append_43) \ include/odp-netlink.h $(am__append_46) \ vswitchd/vswitch.ovsschema.stamp vswitchd/vswitch-idl.c \ vswitchd/vswitch-idl.h $(OVSIDL_BUILT) \ vtep/vtep.ovsschema.stamp \ $(srcdir)/datapath-windows/include/OvsDpInterface.h \ ovn/ovn-nb.ovsschema.stamp ovn/ovn-sb.ovsschema.stamp CLEAN_LOCAL = clean-pycov $(am__append_11) $(am__append_44) DISTCLEANFILES = utilities/ovs-appctl.8 utilities/ovs-ctl \ utilities/ovs-benchmark.1 utilities/ovs-check-dead-ifs \ utilities/ovs-testcontroller.8 utilities/ovs-dpctl.8 \ utilities/ovs-dpctl-top utilities/ovs-dpctl-top.8 \ utilities/ovs-l3ping utilities/ovs-l3ping.8 utilities/ovs-lib \ utilities/ovs-ofctl.8 utilities/ovs-parse-backtrace \ utilities/ovs-pcap utilities/ovs-pcap.1 utilities/ovs-pki \ utilities/ovs-pki.8 utilities/ovs-sim utilities/ovs-sim.1 \ utilities/ovs-tcpundump utilities/ovs-tcpundump.1 \ utilities/ovs-test utilities/ovs-test.8 \ utilities/ovs-vlan-test utilities/ovs-vlan-test.8 \ utilities/ovs-vlan-bug-workaround.8 utilities/ovs-vsctl.8 \ $(am__append_35) tests/atconfig tests/atlocal debian/copyright \ vswitchd/ovs-vswitchd.8 $(am__append_48) \ vswitchd/ovs-vswitchd.conf.db.5 ovsdb/ovsdb-tool.1 \ ovsdb/ovsdb-client.1 ovsdb/ovsdb-server.1 ovsdb/ovsdb-idlc \ ovsdb/ovsdb-dot vtep/vtep-ctl.8 $(am__append_49) vtep/vtep.5 \ $(am__append_51) ovn/ovn-sb.5 $(am__append_52) ovn/ovn-nb.5 \ ovn/ovn-architecture.7 ovn/controller/ovn-controller.8 \ ovn/controller-vtep/ovn-controller-vtep.8 \ ovn/northd/ovn-northd.8 ovn/utilities/ovn-ctl.8 \ ovn/utilities/ovn-nbctl.8 ovn/utilities/ovn-sbctl.8 PYCOV_CLEAN_FILES = build-aux/check-structs,cover \ $(CHECK_PYFILES:.py=.py,cover) .coverage \ $(PYFILES:.py=.py,cover) # A list of Markdown-formatted documentation that will automatically be # included in the "make dist-docs" output. docs = CONTRIBUTING.md CodingStyle.md DESIGN.md FAQ.md INSTALL.md \ INSTALL.Debian.md INSTALL.Docker.md INSTALL.DPDK.md \ INSTALL.Fedora.md INSTALL.KVM.md INSTALL.Libvirt.md \ INSTALL.NetBSD.md INSTALL.RHEL.md INSTALL.SELinux.md \ INSTALL.SSL.md INSTALL.XenServer.md INSTALL.userspace.md \ INSTALL.Windows.md IntegrationGuide.md OPENFLOW-1.1+.md \ PORTING.md README.md README-lisp.md README-native-tunneling.md \ REPORTING-BUGS.md SECURITY.md TODO.md WHY-OVS.md \ utilities/ovs-command-bashcomp.INSTALL.md \ third-party/README.md tutorial/Tutorial.md \ tutorial/OVN-Tutorial.md vtep/README.ovs-vtep.md # IPFIX entity definition macros generation from IANA's XML definition. # IPFIX enterprise entity definition macros. # vswitch schema and IDL # vswitch schema documentation # ovsdb-doc # ovsdb-dot # These python files are used at build time but not runtime, # so they are not installed. # PyPI support. # VTEP schema and IDL # VTEP schema documentation # OVN southbound schema and IDL # OVN southbound schema documentation # OVN northbound schema and IDL # OVN northbound schema documentation EXTRA_DIST = $(docs) NOTICE .travis.yml .travis/build.sh \ .travis/prepare.sh appveyor.yml boot.sh build-aux/cccl \ build-aux/cksum-schema-check build-aux/dist-docs \ build-aux/sodepends.pl build-aux/soexpand.pl \ build-aux/xml2nroff $(MAN_FRAGMENTS) $(MAN_ROOTS) Vagrantfile \ build-aux/thread-safety-blacklist \ Documentation/group-selection-method-property.txt \ m4/absolute-header.m4 m4/include_next.m4 lib/stdio.h.in \ lib/string.h.in lib/dh1024.pem lib/dh2048.pem lib/dh4096.pem \ lib/dirs.c.in lib/vswitch-idl.ann build-aux/extract-ofp-fields \ build-aux/extract-ofp-actions build-aux/extract-ofp-errors \ build-aux/extract-ofp-msgs ofproto/ipfix.xml \ ofproto/ipfix-enterprise-entities.def utilities/ovs-sim.in \ utilities/ovs-sim.1.xml utilities/ovs-appctl-bashcomp.bash \ utilities/ovs-check-dead-ifs.in \ utilities/ovs-command-bashcomp.INSTALL.md utilities/ovs-ctl.in \ utilities/ovs-dev.py utilities/ovs-docker \ utilities/ovs-dpctl-top.in utilities/ovs-l3ping.in \ utilities/ovs-lib.in utilities/ovs-parse-backtrace.in \ utilities/ovs-pcap.in utilities/ovs-pipegen.py \ utilities/ovs-pki.in utilities/ovs-save \ utilities/ovs-tcpundump.in utilities/ovs-test.in \ utilities/ovs-vlan-test.in utilities/ovs-vsctl-bashcomp.bash \ utilities/qemu-wrap.py $(bugtool_plugins) $(bugtool_scripts) \ utilities/bugtool/ovs-bugtool.in $(COMMON_MACROS_AT) \ $(TESTSUITE_AT) $(SYSTEM_TESTSUITE_AT) \ $(SYSTEM_KMOD_TESTSUITE_AT) $(SYSTEM_USERSPACE_TESTSUITE_AT) \ $(TESTSUITE) $(SYSTEM_KMOD_TESTSUITE) \ $(SYSTEM_USERSPACE_TESTSUITE) tests/atlocal.in \ $(srcdir)/package.m4 $(srcdir)/tests/testsuite \ $(srcdir)/tests/testsuite.patch tests/valgrind-wrapper.in \ tests/glibc.supp tests/openssl.supp tests/run-oftest \ tests/run-ryu tests/uuidfilt.pl tests/ovsdb-monitor-sort.pl \ $(IDLTEST_IDL_FILES) tests/idltest2.ovsschema $(CHECK_PYFILES) \ build-aux/extract-odp-netlink-h build-aux/check-structs \ third-party/ofp-tcpdump.patch debian/changelog debian/compat \ debian/control debian/control.modules.in debian/copyright \ debian/copyright.in debian/dkms.conf.in debian/dirs \ debian/openvswitch-common.dirs debian/openvswitch-common.docs \ debian/openvswitch-common.install \ debian/openvswitch-common.manpages \ debian/openvswitch-datapath-module-_KVERS_.postinst.modules.in \ debian/openvswitch-datapath-dkms.postinst \ debian/openvswitch-datapath-dkms.prerm \ debian/openvswitch-datapath-source.README.Debian \ debian/openvswitch-datapath-source.copyright \ debian/openvswitch-datapath-source.dirs \ debian/openvswitch-datapath-source.install \ debian/openvswitch-ipsec.dirs debian/openvswitch-ipsec.init \ debian/openvswitch-ipsec.install debian/openvswitch-pki.dirs \ debian/openvswitch-pki.postinst debian/openvswitch-pki.postrm \ debian/openvswitch-switch.README.Debian \ debian/openvswitch-switch.dirs debian/openvswitch-switch.init \ debian/openvswitch-switch.install \ debian/openvswitch-switch.logrotate \ debian/openvswitch-switch.manpages \ debian/openvswitch-switch.postinst \ debian/openvswitch-switch.postrm \ debian/openvswitch-switch.template \ debian/openvswitch-switch.links debian/openvswitch-test.dirs \ debian/openvswitch-test.install \ debian/openvswitch-test.manpages \ debian/openvswitch-testcontroller.README.Debian \ debian/openvswitch-testcontroller.default \ debian/openvswitch-testcontroller.dirs \ debian/openvswitch-testcontroller.init \ debian/openvswitch-testcontroller.install \ debian/openvswitch-testcontroller.manpages \ debian/openvswitch-testcontroller.postinst \ debian/openvswitch-testcontroller.postrm \ debian/openvswitch-vtep.default debian/openvswitch-vtep.dirs \ debian/openvswitch-vtep.init debian/openvswitch-vtep.install \ debian/openvswitch-vtep.manpages debian/ovs-monitor-ipsec \ debian/python-openvswitch.dirs \ debian/python-openvswitch.install debian/rules \ debian/rules.modules debian/ifupdown.sh debian/source/format \ vswitchd/INTERNALS vswitchd/vswitch.ovsschema \ vswitchd/vswitch.xml ovsdb/ovsdb-idlc.in ovsdb/ovsdb-doc \ ovsdb/ovsdb-dot.in ovsdb/dot2pic rhel/README.RHEL \ rhel/automake.mk rhel/etc_init.d_openvswitch \ rhel/etc_logrotate.d_openvswitch \ rhel/etc_sysconfig_network-scripts_ifdown-ovs \ rhel/etc_sysconfig_network-scripts_ifup-ovs \ rhel/openvswitch-dkms.spec rhel/openvswitch-dkms.spec.in \ rhel/openvswitch-kmod-rhel6.spec \ rhel/openvswitch-kmod-rhel6.spec.in \ rhel/openvswitch-kmod.files rhel/openvswitch-kmod-fedora.spec \ rhel/openvswitch-kmod-fedora.spec.in rhel/openvswitch.spec \ rhel/openvswitch.spec.in rhel/openvswitch-fedora.spec \ rhel/openvswitch-fedora.spec.in \ rhel/usr_share_openvswitch_scripts_sysconfig.template \ rhel/usr_share_openvswitch_scripts_systemd_sysconfig.template \ rhel/usr_lib_systemd_system_openvswitch.service \ rhel/usr_lib_systemd_system_openvswitch-nonetwork.service \ rhel/usr_lib_systemd_system_ovn-controller.service \ rhel/usr_lib_systemd_system_ovn-controller-vtep.service \ rhel/usr_lib_systemd_system_ovn-northd.service xenserver/GPLv2 \ xenserver/LICENSE xenserver/README xenserver/automake.mk \ xenserver/etc_init.d_openvswitch \ xenserver/etc_init.d_openvswitch-xapi-update \ xenserver/etc_logrotate.d_openvswitch \ xenserver/etc_profile.d_openvswitch.sh \ xenserver/etc_xapi.d_plugins_openvswitch-cfg-update \ xenserver/etc_xensource_scripts_vif \ xenserver/openvswitch-xen.spec \ xenserver/openvswitch-xen.spec.in \ xenserver/opt_xensource_libexec_InterfaceReconfigure.py \ xenserver/opt_xensource_libexec_InterfaceReconfigureBridge.py \ xenserver/opt_xensource_libexec_InterfaceReconfigureVswitch.py \ xenserver/opt_xensource_libexec_interface-reconfigure \ xenserver/usr_lib_xsconsole_plugins-base_XSFeatureVSwitch.py \ xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync \ xenserver/usr_share_openvswitch_scripts_sysconfig.template \ python/build/__init__.py python/build/nroff.py \ python/README.rst python/setup.py $(PYFILES) \ python/ovs/dirs.py.template tutorial/ovs-sandbox \ tutorial/t-setup tutorial/t-stage0 tutorial/t-stage1 \ tutorial/t-stage2 tutorial/t-stage3 tutorial/t-stage4 \ tutorial/ovn/env1/setup.sh tutorial/ovn/env1/packet1.sh \ tutorial/ovn/env1/packet2.sh \ tutorial/ovn/env1/add-third-port.sh tutorial/ovn/env2/setup.sh \ tutorial/ovn/env2/packet1.sh tutorial/ovn/env2/packet2.sh \ tutorial/ovn/env3/setup.sh tutorial/ovn/env3/packet1.sh \ tutorial/ovn/env3/packet2.sh tutorial/ovn/env4/setup1.sh \ tutorial/ovn/env4/setup2.sh tutorial/ovn/env4/packet1.sh \ tutorial/ovn/env4/packet2.sh tutorial/ovn/env4/packet3.sh \ tutorial/ovn/env4/packet4.sh tutorial/ovn/env4/packet5.sh \ tutorial/ovn/env5/setup.sh tutorial/ovn/env5/packet1.sh \ tutorial/ovn/env5/packet2.sh tutorial/ovn/env6/setup.sh \ tutorial/ovn/env6/add-acls.sh vtep/vtep-idl.ann vtep/ovs-vtep \ vtep/vtep.ovsschema vtep/vtep.xml datapath-windows/CodingStyle \ datapath-windows/DESIGN \ datapath-windows/Package/package.VcxProj \ datapath-windows/Package/package.VcxProj.user \ datapath-windows/include/OvsDpInterfaceExt.h \ datapath-windows/misc/OVS.psm1 \ datapath-windows/misc/install.cmd \ datapath-windows/misc/uninstall.cmd \ datapath-windows/ovsext.sln datapath-windows/ovsext/Actions.c \ datapath-windows/ovsext/Atomic.h \ datapath-windows/ovsext/BufferMgmt.c \ datapath-windows/ovsext/BufferMgmt.h \ datapath-windows/ovsext/Checksum.c \ datapath-windows/ovsext/Checksum.h \ datapath-windows/ovsext/Datapath.c \ datapath-windows/ovsext/Datapath.h \ datapath-windows/ovsext/Debug.c \ datapath-windows/ovsext/Debug.h \ datapath-windows/ovsext/DpInternal.h \ datapath-windows/ovsext/Driver.c \ datapath-windows/ovsext/Ethernet.h \ datapath-windows/ovsext/Event.c \ datapath-windows/ovsext/Event.h datapath-windows/ovsext/Flow.c \ datapath-windows/ovsext/Flow.h datapath-windows/ovsext/Gre.h \ datapath-windows/ovsext/Gre.c \ datapath-windows/ovsext/IpHelper.c \ datapath-windows/ovsext/IpHelper.h \ datapath-windows/ovsext/Jhash.c \ datapath-windows/ovsext/Jhash.h \ datapath-windows/ovsext/NetProto.h \ datapath-windows/ovsext/Netlink/Netlink.c \ datapath-windows/ovsext/Netlink/Netlink.h \ datapath-windows/ovsext/Netlink/NetlinkBuf.c \ datapath-windows/ovsext/Netlink/NetlinkBuf.h \ datapath-windows/ovsext/Netlink/NetlinkError.h \ datapath-windows/ovsext/Netlink/NetlinkProto.h \ datapath-windows/ovsext/Oid.c datapath-windows/ovsext/Oid.h \ datapath-windows/ovsext/PacketIO.c \ datapath-windows/ovsext/PacketIO.h \ datapath-windows/ovsext/PacketParser.c \ datapath-windows/ovsext/PacketParser.h \ datapath-windows/ovsext/Stt.c datapath-windows/ovsext/Stt.h \ datapath-windows/ovsext/Switch.c \ datapath-windows/ovsext/Switch.h \ datapath-windows/ovsext/Tunnel.c \ datapath-windows/ovsext/Tunnel.h \ datapath-windows/ovsext/TunnelFilter.c \ datapath-windows/ovsext/TunnelIntf.h \ datapath-windows/ovsext/Types.h datapath-windows/ovsext/User.c \ datapath-windows/ovsext/User.h datapath-windows/ovsext/Util.c \ datapath-windows/ovsext/Util.h datapath-windows/ovsext/Vport.c \ datapath-windows/ovsext/Vport.h \ datapath-windows/ovsext/Vxlan.c \ datapath-windows/ovsext/Vxlan.h \ datapath-windows/ovsext/ovsext.inf \ datapath-windows/ovsext/ovsext.rc \ datapath-windows/ovsext/ovsext.vcxproj \ datapath-windows/ovsext/ovsext.vcxproj.user \ datapath-windows/ovsext/precomp.h \ datapath-windows/ovsext/precompsrc.c \ datapath-windows/ovsext/resource.h \ $(srcdir)/build-aux/extract-odp-netlink-windows-dp-h \ windows/.gitignore windows/automake.mk windows/README.rst \ windows/ovs-windows-installer.sln \ windows/ovs-windows-installer/Actions/OVSActions.js \ windows/ovs-windows-installer/CustomActions.wxs \ windows/ovs-windows-installer/Dialogs/BeginningDialog.wxs \ windows/ovs-windows-installer/Dialogs/MyEndDialog.wxs \ windows/ovs-windows-installer/Dialogs/MyTroubleshootDialog.wxs \ windows/ovs-windows-installer/Dialogs/UserFinishDialog.wxs \ windows/ovs-windows-installer/License.rtf \ windows/ovs-windows-installer/Product.wxs \ windows/ovs-windows-installer/UI.wxs \ windows/ovs-windows-installer/images/bannrbmp.bmp \ windows/ovs-windows-installer/images/dlgbmp.bmp \ windows/ovs-windows-installer/ovs-windows-installer.wixproj \ ovn/ovn-sb.ovsschema ovn/ovn-sb.xml ovn/ovn-nb.ovsschema \ ovn/ovn-nb.xml ovn/ovn-architecture.7.xml ovn/TODO \ ovn/CONTAINERS.OpenStack.md ovn/OVN-GW-HA.md \ ovn/controller/ovn-controller.8.xml \ ovn/controller-vtep/ovn-controller-vtep.8.xml \ ovn/lib/ovn-sb-idl.ann ovn/lib/ovn-nb-idl.ann \ ovn/northd/ovn-northd.8.xml ovn/utilities/ovn-ctl \ ovn/utilities/ovn-ctl.8.xml \ ovn/utilities/ovn-docker-overlay-driver \ ovn/utilities/ovn-docker-underlay-driver \ ovn/utilities/ovn-nbctl.8.xml selinux/openvswitch-custom.te # Docker drivers bin_SCRIPTS = utilities/ovs-docker utilities/ovs-pki $(am__append_28) \ ovn/utilities/ovn-docker-overlay-driver \ ovn/utilities/ovn-docker-underlay-driver DIST_HOOKS = check-debian-changelog-version dist_man_MANS = dist_pkgdata_DATA = dist_pkgdata_SCRIPTS = dist_sbin_SCRIPTS = dist_scripts_SCRIPTS = dist_scripts_DATA = INSTALL_DATA_LOCAL = lib-install-data-local $(am__append_37) UNINSTALL_LOCAL = $(am__append_38) ovs-uninstall-local # ovsdb-tool.1 # ovsdb-client.1 # ovsdb-server.1 man_MANS = utilities/ovs-appctl.8 utilities/ovs-benchmark.1 \ utilities/ovs-ctl.8 utilities/ovs-testcontroller.8 \ utilities/ovs-dpctl.8 utilities/ovs-dpctl-top.8 \ utilities/ovs-l3ping.8 utilities/ovs-ofctl.8 \ utilities/ovs-parse-backtrace.8 utilities/ovs-pcap.1 \ utilities/ovs-pki.8 utilities/ovs-tcpundump.1 \ utilities/ovs-vlan-bug-workaround.8 utilities/ovs-test.8 \ utilities/ovs-vlan-test.8 utilities/ovs-vsctl.8 \ $(am__append_33) vswitchd/ovs-vswitchd.8 \ vswitchd/ovs-vswitchd.conf.db.5 ovsdb/ovsdb-tool.1 \ ovsdb/ovsdb-client.1 ovsdb/ovsdb-server.1 vtep/vtep-ctl.8 \ vtep/vtep.5 ovn/ovn-sb.5 ovn/ovn-nb.5 ovn/ovn-architecture.7 \ ovn/controller/ovn-controller.8 \ ovn/controller-vtep/ovn-controller-vtep.8 \ ovn/northd/ovn-northd.8 ovn/utilities/ovn-ctl.8 \ ovn/utilities/ovn-nbctl.8 ovn/utilities/ovn-sbctl.8 MAN_FRAGMENTS = lib/common.man lib/common-syn.man \ lib/coverage-unixctl.man lib/daemon.man lib/daemon-syn.man \ lib/db-ctl-base.man lib/dpctl.man lib/memory-unixctl.man \ lib/ofp-version.man lib/ovs.tmac lib/service.man \ lib/service-syn.man lib/ssl-bootstrap.man \ lib/ssl-bootstrap-syn.man lib/ssl-peer-ca-cert.man \ lib/ssl-peer-ca-cert-syn.man lib/ssl.man lib/ssl-syn.man \ lib/table.man lib/unixctl.man lib/unixctl-syn.man \ lib/vconn-active.man lib/vconn-passive.man \ lib/vlog-unixctl.man lib/vlog-syn.man lib/vlog.man \ ofproto/ofproto-unixctl.man ofproto/ofproto-dpif-unixctl.man \ ofproto/ofproto-tnl-unixctl.man utilities/ovs-vlan-bugs.man \ ovsdb/remote-active.man ovsdb/remote-passive.man MAN_ROOTS = utilities/ovs-appctl.8.in utilities/ovs-benchmark.1.in \ utilities/ovs-testcontroller.8.in utilities/ovs-ctl.8 \ utilities/ovs-dpctl.8.in utilities/ovs-dpctl-top.8.in \ utilities/ovs-l3ping.8.in utilities/ovs-ofctl.8.in \ utilities/ovs-parse-backtrace.8 utilities/ovs-pcap.1.in \ utilities/ovs-pki.8.in utilities/ovs-tcpundump.1.in \ utilities/ovs-vlan-bug-workaround.8.in utilities/ovs-test.8.in \ utilities/ovs-vlan-test.8.in utilities/ovs-vsctl.8.in \ $(am__append_34) vswitchd/ovs-vswitchd.8.in \ ovsdb/ovsdb-tool.1.in ovsdb/ovsdb-client.1.in \ ovsdb/ovsdb-server.1.in ovsdb/ovsdb-idlc.1 vtep/vtep-ctl.8.in \ ovn/utilities/ovn-sbctl.8.in noinst_DATA = # This ensures that files added to EXTRA_DIST are always distributed, # even if they are inside an Automake if...endif conditional block that is # disabled by some particular "configure" run. For more information, see: # http://article.gmane.org/gmane.comp.sysutils.automake.general/10891 noinst_HEADERS = $(EXTRA_DIST) include/sparse/arpa/inet.h \ include/sparse/assert.h include/sparse/bmi2intrin.h \ include/sparse/emmintrin.h include/sparse/math.h \ include/sparse/netinet/in.h include/sparse/netinet/ip6.h \ include/sparse/netpacket/packet.h include/sparse/pthread.h \ include/sparse/rte_atomic.h include/sparse/rte_lcore.h \ include/sparse/rte_vect.h include/sparse/sys/socket.h \ include/sparse/sys/wait.h include/windows/arpa/inet.h \ include/windows/dirent.h include/windows/getopt.h \ include/windows/linux/pkt_sched.h \ include/windows/linux/types.h include/windows/net/if.h \ include/windows/netdb.h include/windows/netpacket/packet.h \ include/windows/netinet/icmp6.h include/windows/netinet/in.h \ include/windows/netinet/in_systm.h \ include/windows/netinet/ip.h include/windows/netinet/ip6.h \ include/windows/netinet/tcp.h include/windows/poll.h \ include/windows/strings.h include/windows/syslog.h \ include/windows/sys/epoll.h include/windows/sys/ioctl.h \ include/windows/sys/resource.h include/windows/sys/socket.h \ include/windows/sys/time.h include/windows/sys/uio.h \ include/windows/sys/un.h include/windows/sys/wait.h \ include/windows/unistd.h include/windows/windefs.h # libovsdb # libvtep lib_LTLIBRARIES = lib/libopenvswitch.la lib/libsflow.la \ ofproto/libofproto.la ovsdb/libovsdb.la vtep/libvtep.la \ ovn/lib/libovn.la noinst_man_MANS = utilities/ovs-sim.1 # ovsdb-idlc noinst_SCRIPTS = utilities/ovs-sim ovsdb/ovsdb-idlc ovsdb/ovsdb-dot # vswitch IDL # idltest schema and IDL # vtep IDL # ovn-sb IDL # ovn-nb IDL OVSIDL_BUILT = lib/vswitch-idl.c lib/vswitch-idl.h \ lib/vswitch-idl.ovsidl tests/idltest.c tests/idltest.h \ tests/idltest.ovsidl vtep/vtep-idl.c vtep/vtep-idl.h \ vtep/vtep-idl.ovsidl ovn/lib/ovn-sb-idl.c ovn/lib/ovn-sb-idl.h \ ovn/lib/ovn-sb-idl.ovsidl ovn/lib/ovn-nb-idl.c \ ovn/lib/ovn-nb-idl.h ovn/lib/ovn-nb-idl.ovsidl pkgdata_DATA = vswitchd/vswitch.ovsschema vtep/vtep.ovsschema \ ovn/ovn-sb.ovsschema ovn/ovn-nb.ovsschema sbin_SCRIPTS = $(am__append_31) # ovs-vtep scripts_SCRIPTS = utilities/ovs-check-dead-ifs utilities/ovs-ctl \ utilities/ovs-save $(am__append_36) vtep/ovs-vtep \ ovn/utilities/ovn-ctl completion_SCRIPTS = utilities/ovs-appctl-bashcomp.bash \ utilities/ovs-vsctl-bashcomp.bash scripts_DATA = utilities/ovs-lib SUFFIXES = .in .xml $(am__append_45) .ovsidl .ovsschema check_DATA = $(am__append_42) check_SCRIPTS = utilities/ovs-appctl-bashcomp.bash \ utilities/ovs-vsctl-bashcomp.bash pkgconfig_DATA = $(srcdir)/lib/libopenvswitch.pc \ $(srcdir)/lib/libsflow.pc $(srcdir)/ofproto/libofproto.pc \ $(srcdir)/ovsdb/libovsdb.pc scriptsdir = $(pkgdatadir)/scripts completiondir = $(sysconfdir)/bash_completion.d pkgconfigdir = $(libdir)/pkgconfig ro_c = echo '/* -*- mode: c; buffer-read-only: t -*- */' ro_shell = printf '\043 Generated automatically -- do not modify! -*- buffer-read-only: t -*-\n' lib_libopenvswitch_la_LIBADD = $(SSL_LIBS) $(CAPNG_LDADD) \ $(am__append_12) lib_libopenvswitch_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -Wl,--version-script=$(top_builddir)/lib/libopenvswitch.sym \ $(AM_LDFLAGS) lib_libopenvswitch_la_SOURCES = lib/aes128.c lib/aes128.h \ lib/async-append.h lib/backtrace.c lib/backtrace.h lib/bfd.c \ lib/bfd.h lib/bitmap.h lib/bundle.c lib/bundle.h \ lib/byte-order.h lib/byteq.c lib/byteq.h lib/cfm.c lib/cfm.h \ lib/classifier.c lib/classifier.h lib/classifier-private.h \ lib/cmap.c lib/cmap.h lib/command-line.c lib/command-line.h \ lib/compiler.h lib/connectivity.c lib/connectivity.h \ lib/coverage.c lib/coverage.h lib/crc32c.c lib/crc32c.h \ lib/csum.c lib/csum.h lib/ct-dpif.c lib/ct-dpif.h lib/daemon.c \ lib/daemon.h lib/daemon-private.h lib/db-ctl-base.c \ lib/db-ctl-base.h lib/dhcp.h lib/dummy.c lib/dummy.h \ lib/dhparams.h lib/dirs.h lib/dpctl.c lib/dpctl.h \ lib/dp-packet.h lib/dp-packet.c lib/dpif-netdev.c \ lib/dpif-netdev.h lib/dpif-provider.h lib/dpif.c lib/dpif.h \ lib/heap.c lib/heap.h lib/dynamic-string.c \ lib/dynamic-string.h lib/entropy.c lib/entropy.h \ lib/fat-rwlock.c lib/fat-rwlock.h lib/fatal-signal.c \ lib/fatal-signal.h lib/flow.c lib/flow.h lib/geneve.h \ lib/guarded-list.c lib/guarded-list.h lib/hash.c lib/hash.h \ lib/hindex.c lib/hindex.h lib/hmap.c lib/hmap.h lib/hmapx.c \ lib/hmapx.h lib/id-pool.c lib/id-pool.h lib/jhash.c \ lib/jhash.h lib/json.c lib/json.h lib/jsonrpc.c lib/jsonrpc.h \ lib/lacp.c lib/lacp.h lib/latch.h lib/learn.c lib/learn.h \ lib/learning-switch.c lib/learning-switch.h lib/list.h \ lib/lockfile.c lib/lockfile.h lib/mac-learning.c \ lib/mac-learning.h lib/match.c lib/match.h \ lib/mcast-snooping.c lib/mcast-snooping.h lib/memory.c \ lib/memory.h lib/meta-flow.c lib/meta-flow.h lib/multipath.c \ lib/multipath.h lib/netdev-dummy.c lib/netdev-provider.h \ lib/netdev-vport.c lib/netdev-vport.h lib/netdev.c \ lib/netdev.h lib/netflow.h lib/netlink.c lib/netlink.h \ lib/nx-match.c lib/nx-match.h lib/odp-execute.c \ lib/odp-execute.h lib/odp-util.c lib/odp-util.h \ lib/ofp-actions.c lib/ofp-actions.h lib/ofp-errors.c \ lib/ofp-errors.h lib/ofp-msgs.c lib/ofp-msgs.h lib/ofp-parse.c \ lib/ofp-parse.h lib/ofp-print.c lib/ofp-print.h lib/ofp-util.c \ lib/ofp-util.h lib/ofp-version-opt.h lib/ofp-version-opt.c \ lib/ofpbuf.c lib/ofpbuf.h lib/ovs-atomic-c11.h \ lib/ovs-atomic-clang.h lib/ovs-atomic-flag-gcc4.7+.h \ lib/ovs-atomic-gcc4+.h lib/ovs-atomic-gcc4.7+.h \ lib/ovs-atomic-i586.h lib/ovs-atomic-locked.c \ lib/ovs-atomic-locked.h lib/ovs-atomic-msvc.h \ lib/ovs-atomic-pthreads.h lib/ovs-atomic-x86_64.h \ lib/ovs-atomic.h lib/ovs-lldp.c lib/ovs-lldp.h lib/ovs-rcu.c \ lib/ovs-rcu.h lib/ovs-router.h lib/ovs-router.c \ lib/ovs-thread.c lib/ovs-thread.h lib/ovsdb-data.c \ lib/ovsdb-data.h lib/ovsdb-error.c lib/ovsdb-error.h \ lib/ovsdb-idl-provider.h lib/ovsdb-idl.c lib/ovsdb-idl.h \ lib/ovsdb-parser.c lib/ovsdb-parser.h lib/ovsdb-types.c \ lib/ovsdb-types.h lib/packets.c lib/packets.h lib/pcap-file.c \ lib/pcap-file.h lib/perf-counter.h lib/perf-counter.c \ lib/poll-loop.c lib/poll-loop.h lib/process.c lib/process.h \ lib/pvector.c lib/pvector.h lib/random.c lib/random.h \ lib/rconn.c lib/rconn.h lib/rculist.h lib/reconnect.c \ lib/reconnect.h lib/rstp.c lib/rstp.h lib/rstp-common.h \ lib/rstp-state-machines.c lib/rstp-state-machines.h \ lib/sat-math.h lib/seq.c lib/seq.h lib/sha1.c lib/sha1.h \ lib/shash.c lib/shash.h lib/simap.c lib/simap.h lib/smap.c \ lib/smap.h lib/socket-util.c lib/socket-util.h lib/sort.c \ lib/sort.h lib/sset.c lib/sset.h lib/stp.c lib/stp.h \ lib/stream-fd.c lib/stream-fd.h lib/stream-provider.h \ lib/stream-ssl.h lib/stream-tcp.c lib/stream.c lib/stream.h \ lib/stdio.c lib/string.c lib/svec.c lib/svec.h \ lib/syslog-direct.c lib/syslog-direct.h lib/syslog-libc.c \ lib/syslog-libc.h lib/syslog-provider.h lib/table.c \ lib/table.h lib/timer.c lib/timer.h lib/timeval.c \ lib/timeval.h lib/tnl-neigh-cache.c lib/tnl-neigh-cache.h \ lib/tnl-ports.c lib/tnl-ports.h lib/token-bucket.c \ lib/tun-metadata.c lib/tun-metadata.h lib/type-props.h \ lib/unaligned.h lib/unicode.c lib/unicode.h lib/unixctl.c \ lib/unixctl.h lib/util.c lib/util.h lib/uuid.c lib/uuid.h \ lib/valgrind.h lib/vconn-provider.h lib/vconn-stream.c \ lib/vconn.c lib/vlan-bitmap.c lib/vlan-bitmap.h lib/vlandev.c \ lib/vlandev.h lib/vlog.c lib/lldp/aa-structs.h lib/lldp/lldp.c \ lib/lldp/lldp-const.h lib/lldp/lldp-tlv.h lib/lldp/lldpd.c \ lib/lldp/lldpd.h lib/lldp/lldpd-structs.c \ lib/lldp/lldpd-structs.h $(am__append_13) $(am__append_14) \ $(am__append_17) $(am__append_18) $(am__append_19) \ $(am__append_20) $(am__append_21) $(am__append_22) \ $(am__append_23) $(am__append_24) $(am__append_26) nodist_lib_libopenvswitch_la_SOURCES = lib/dirs.c lib/vswitch-idl.c \ lib/vswitch-idl.h $(am__append_25) lib_libsflow_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -Wl,--version-script=$(top_builddir)/lib/libsflow.sym \ $(AM_LDFLAGS) lib_libsflow_la_SOURCES = \ lib/sflow_api.h \ lib/sflow.h \ lib/sflow_agent.c \ lib/sflow_sampler.c \ lib/sflow_poller.c \ lib/sflow_receiver.c lib_libsflow_la_CPPFLAGS = $(AM_CPPFLAGS) lib_libsflow_la_CFLAGS = $(AM_CFLAGS) $(am__append_15) \ $(am__append_16) ofproto_libofproto_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -Wl,--version-script=$(top_builddir)/ofproto/libofproto.sym \ $(AM_LDFLAGS) # Distribute this generated file in order not to require Python at # build time if ofproto/ipfix.xml is not modified. ofproto_libofproto_la_SOURCES = ofproto/bond.c ofproto/bond.h \ ofproto/collectors.c ofproto/collectors.h ofproto/connmgr.c \ ofproto/connmgr.h ofproto/fail-open.c ofproto/fail-open.h \ ofproto/in-band.c ofproto/in-band.h ofproto/names.c \ ofproto/netflow.c ofproto/netflow.h ofproto/ofproto.c \ ofproto/ofproto.h ofproto/ofproto-dpif.c \ ofproto/ofproto-dpif.h ofproto/ofproto-dpif-ipfix.c \ ofproto/ofproto-dpif-ipfix.h ofproto/ofproto-dpif-mirror.c \ ofproto/ofproto-dpif-mirror.h ofproto/ofproto-dpif-monitor.c \ ofproto/ofproto-dpif-monitor.h ofproto/ofproto-dpif-rid.c \ ofproto/ofproto-dpif-rid.h ofproto/ofproto-dpif-sflow.c \ ofproto/ofproto-dpif-sflow.h ofproto/ofproto-dpif-upcall.c \ ofproto/ofproto-dpif-upcall.h ofproto/ofproto-dpif-xlate.c \ ofproto/ofproto-dpif-xlate.h ofproto/ofproto-provider.h \ ofproto/pktbuf.c ofproto/pktbuf.h ofproto/pinsched.c \ ofproto/pinsched.h ofproto/tunnel.c ofproto/tunnel.h \ ofproto/bundles.c ofproto/bundles.h ofproto/ipfix-entities.def ofproto_libofproto_la_CPPFLAGS = $(AM_CPPFLAGS) ofproto_libofproto_la_CFLAGS = $(AM_CFLAGS) ofproto_libofproto_la_LIBADD = lib/libsflow.la $(am__append_27) dist_noinst_SCRIPTS = ofproto/ipfix-gen-entities utilities_ovs_appctl_SOURCES = utilities/ovs-appctl.c utilities_ovs_appctl_LDADD = lib/libopenvswitch.la utilities_ovs_testcontroller_SOURCES = utilities/ovs-testcontroller.c utilities_ovs_testcontroller_LDADD = lib/libopenvswitch.la $(SSL_LIBS) utilities_ovs_dpctl_SOURCES = utilities/ovs-dpctl.c utilities_ovs_dpctl_LDADD = lib/libopenvswitch.la utilities_ovs_ofctl_SOURCES = utilities/ovs-ofctl.c utilities_ovs_ofctl_LDADD = \ ofproto/libofproto.la \ lib/libopenvswitch.la utilities_ovs_vsctl_SOURCES = utilities/ovs-vsctl.c utilities_ovs_vsctl_LDADD = lib/libopenvswitch.la @LINUX_TRUE@utilities_ovs_vlan_bug_workaround_SOURCES = utilities/ovs-vlan-bug-workaround.c @LINUX_TRUE@utilities_ovs_vlan_bug_workaround_LDADD = lib/libopenvswitch.la @LINUX_TRUE@utilities_nlmon_SOURCES = utilities/nlmon.c @LINUX_TRUE@utilities_nlmon_LDADD = lib/libopenvswitch.la utilities_ovs_benchmark_SOURCES = utilities/ovs-benchmark.c utilities_ovs_benchmark_LDADD = lib/libopenvswitch.la @HAVE_PYTHON_TRUE@bugtool_plugins = \ @HAVE_PYTHON_TRUE@ utilities/bugtool/plugins/kernel-info/openvswitch.xml \ @HAVE_PYTHON_TRUE@ utilities/bugtool/plugins/network-status/openvswitch.xml \ @HAVE_PYTHON_TRUE@ utilities/bugtool/plugins/system-configuration.xml \ @HAVE_PYTHON_TRUE@ utilities/bugtool/plugins/system-logs/openvswitch.xml \ @HAVE_PYTHON_TRUE@ utilities/bugtool/plugins/system-configuration/openvswitch.xml @HAVE_PYTHON_TRUE@bugtool_scripts = \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-bfd-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-cfm-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-coverage-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-fdb-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-lacp-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-list-dbs \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-memory-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-tc-class-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-vsctl-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-ovsdb-dump \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-daemons-ver \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-ovs-ofctl-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-ovs-ofctl-dump-flows \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-ovs-appctl-dpif \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-bond-show \ @HAVE_PYTHON_TRUE@ utilities/bugtool/ovs-bugtool-conntrack-dump @HAVE_PYTHON_TRUE@bugtoolpluginsdir = $(pkgdatadir)/bugtool-plugins COMMON_MACROS_AT = \ tests/ovsdb-macros.at \ tests/ovs-macros.at \ tests/ofproto-macros.at TESTSUITE_AT = \ tests/testsuite.at \ tests/completion.at \ tests/library.at \ tests/heap.at \ tests/bundle.at \ tests/classifier.at \ tests/check-structs.at \ tests/daemon.at \ tests/daemon-py.at \ tests/ofp-actions.at \ tests/ofp-print.at \ tests/ofp-util.at \ tests/ofp-errors.at \ tests/ovs-ofctl.at \ tests/odp.at \ tests/mpls-xlate.at \ tests/multipath.at \ tests/bfd.at \ tests/cfm.at \ tests/lacp.at \ tests/lib.at \ tests/learn.at \ tests/vconn.at \ tests/file_name.at \ tests/aes128.at \ tests/unixctl-py.at \ tests/uuid.at \ tests/json.at \ tests/jsonrpc.at \ tests/jsonrpc-py.at \ tests/tunnel.at \ tests/tunnel-push-pop.at \ tests/tunnel-push-pop-ipv6.at \ tests/lockfile.at \ tests/reconnect.at \ tests/ovs-vswitchd.at \ tests/dpif-netdev.at \ tests/dpctl.at \ tests/ofproto-dpif.at \ tests/bridge.at \ tests/vlan-splinters.at \ tests/ofproto.at \ tests/ovsdb.at \ tests/ovsdb-log.at \ tests/ovsdb-types.at \ tests/ovsdb-data.at \ tests/ovsdb-column.at \ tests/ovsdb-table.at \ tests/ovsdb-row.at \ tests/ovsdb-schema.at \ tests/ovsdb-condition.at \ tests/ovsdb-mutation.at \ tests/ovsdb-query.at \ tests/ovsdb-transaction.at \ tests/ovsdb-execution.at \ tests/ovsdb-trigger.at \ tests/ovsdb-tool.at \ tests/ovsdb-server.at \ tests/ovsdb-monitor.at \ tests/ovsdb-idl.at \ tests/ovs-vsctl.at \ tests/ovs-monitor-ipsec.at \ tests/ovs-xapi-sync.at \ tests/stp.at \ tests/rstp.at \ tests/interface-reconfigure.at \ tests/vlog.at \ tests/vtep-ctl.at \ tests/auto-attach.at \ tests/ovn.at \ tests/ovn-nbctl.at \ tests/ovn-sbctl.at \ tests/ovn-controller.at \ tests/ovn-controller-vtep.at SYSTEM_KMOD_TESTSUITE_AT = \ tests/system-common-macros.at \ tests/system-kmod-testsuite.at \ tests/system-kmod-macros.at SYSTEM_USERSPACE_TESTSUITE_AT = \ tests/system-userspace-testsuite.at \ tests/system-userspace-macros.at SYSTEM_TESTSUITE_AT = \ tests/system-common-macros.at \ tests/system-traffic.at TESTSUITE = $(srcdir)/tests/testsuite TESTSUITE_PATCH = $(srcdir)/tests/testsuite.patch SYSTEM_KMOD_TESTSUITE = $(srcdir)/tests/system-kmod-testsuite SYSTEM_USERSPACE_TESTSUITE = $(srcdir)/tests/system-userspace-testsuite AUTOTEST_PATH = utilities:vswitchd:ovsdb:vtep:tests:$(PTHREAD_WIN32_DIR_DLL):ovn/controller-vtep:ovn/northd:ovn/utilities:ovn/controller # Python Coverage support. # Requires coverage.py http://nedbatchelder.com/code/coverage/. COVERAGE = coverage COVERAGE_FILE = '$(abs_srcdir)/.coverage' # valgrind support valgrind_wrappers = \ tests/valgrind/ovs-appctl \ tests/valgrind/ovs-ofctl \ tests/valgrind/ovstest \ tests/valgrind/ovs-vsctl \ tests/valgrind/ovs-vswitchd \ tests/valgrind/ovsdb-client \ tests/valgrind/ovsdb-server \ tests/valgrind/ovsdb-tool \ tests/valgrind/test-aes128 \ tests/valgrind/test-atomic \ tests/valgrind/test-bundle \ tests/valgrind/test-byte-order \ tests/valgrind/test-classifier \ tests/valgrind/test-cmap \ tests/valgrind/test-csum \ tests/valgrind/test-flows \ tests/valgrind/test-hash \ tests/valgrind/test-hindex \ tests/valgrind/test-hmap \ tests/valgrind/test-json \ tests/valgrind/test-jsonrpc \ tests/valgrind/test-list \ tests/valgrind/test-lockfile \ tests/valgrind/test-multipath \ tests/valgrind/test-odp \ tests/valgrind/test-ofpbuf \ tests/valgrind/test-ovsdb \ tests/valgrind/test-packets \ tests/valgrind/test-random \ tests/valgrind/test-reconnect \ tests/valgrind/test-rstp \ tests/valgrind/test-sha1 \ tests/valgrind/test-stp \ tests/valgrind/test-type-props \ tests/valgrind/test-unix-socket \ tests/valgrind/test-uuid \ tests/valgrind/test-vconn VALGRIND = valgrind --log-file=valgrind.%p --leak-check=full \ --suppressions=$(abs_top_srcdir)/tests/glibc.supp \ --suppressions=$(abs_top_srcdir)/tests/openssl.supp --num-callers=20 AUTOTEST = $(AUTOM4TE) --language=autotest tests_test_ovsdb_SOURCES = tests/test-ovsdb.c nodist_tests_test_ovsdb_SOURCES = tests/idltest.c tests/idltest.h tests_test_ovsdb_LDADD = ovsdb/libovsdb.la lib/libopenvswitch.la tests_test_lib_SOURCES = \ tests/test-lib.c tests_test_lib_LDADD = lib/libopenvswitch.la IDLTEST_IDL_FILES = tests/idltest.ovsschema tests/idltest.ann @DPDK_NETDEV_TRUE@tests_test_dpdkr_SOURCES = \ @DPDK_NETDEV_TRUE@ tests/dpdk/ring_client.c @DPDK_NETDEV_TRUE@tests_test_dpdkr_LDADD = lib/libopenvswitch.la $(LIBS) tests_ovstest_SOURCES = tests/ovstest.c tests/ovstest.h \ tests/test-aes128.c tests/test-atomic.c tests/test-bundle.c \ tests/test-byte-order.c tests/test-classifier.c \ tests/test-cmap.c tests/test-csum.c tests/test-flows.c \ tests/test-hash.c tests/test-heap.c tests/test-hindex.c \ tests/test-hmap.c tests/test-json.c tests/test-jsonrpc.c \ tests/test-list.c tests/test-lockfile.c tests/test-multipath.c \ tests/test-netflow.c tests/test-odp.c tests/test-ofpbuf.c \ tests/test-ovn.c tests/test-packets.c tests/test-random.c \ tests/test-reconnect.c tests/test-rstp.c tests/test-sflow.c \ tests/test-sha1.c tests/test-stp.c tests/test-util.c \ tests/test-uuid.c tests/test-bitmap.c tests/test-vconn.c \ tests/test-aa.c $(am__append_40) $(am__append_41) tests_ovstest_LDADD = lib/libopenvswitch.la ovn/lib/libovn.la dist_check_SCRIPTS = tests/flowgen.pl tests_test_strtok_r_SOURCES = tests/test-strtok_r.c tests_test_type_props_SOURCES = tests/test-type-props.c # Python tests. CHECK_PYFILES = \ tests/appctl.py \ tests/test-daemon.py \ tests/test-json.py \ tests/test-jsonrpc.py \ tests/test-l7.py \ tests/test-ovsdb.py \ tests/test-reconnect.py \ tests/MockXenAPI.py \ tests/test-unix-socket.py \ tests/test-unixctl.py \ tests/test-vlog.py @HAVE_OPENSSL_TRUE@TESTPKI_FILES = \ @HAVE_OPENSSL_TRUE@ tests/testpki-cacert.pem \ @HAVE_OPENSSL_TRUE@ tests/testpki-cert.pem \ @HAVE_OPENSSL_TRUE@ tests/testpki-privkey.pem \ @HAVE_OPENSSL_TRUE@ tests/testpki-req.pem \ @HAVE_OPENSSL_TRUE@ tests/testpki-cert2.pem \ @HAVE_OPENSSL_TRUE@ tests/testpki-privkey2.pem \ @HAVE_OPENSSL_TRUE@ tests/testpki-req2.pem @HAVE_OPENSSL_TRUE@OVS_PKI = $(SHELL) $(srcdir)/utilities/ovs-pki.in --dir=tests/pki --log=tests/ovs-pki.log openflowincludedir = $(includedir)/openflow openflowinclude_HEADERS = \ include/openflow/netronome-ext.h \ include/openflow/nicira-ext.h \ include/openflow/openflow-1.0.h \ include/openflow/openflow-1.1.h \ include/openflow/openflow-1.2.h \ include/openflow/openflow-1.3.h \ include/openflow/openflow-1.4.h \ include/openflow/openflow-1.5.h \ include/openflow/openflow-common.h \ include/openflow/openflow.h @HAVE_PYTHON_TRUE@HSTAMP_FILES = $(openflowinclude_HEADERS:.h=.hstamp) openvswitchincludedir = $(includedir)/openvswitch openvswitchinclude_HEADERS = \ include/openvswitch/compiler.h \ include/openvswitch/list.h \ include/openvswitch/thread.h \ include/openvswitch/token-bucket.h \ include/openvswitch/types.h \ include/openvswitch/util.h \ include/openvswitch/version.h \ include/openvswitch/vconn.h \ include/openvswitch/vlog.h vswitchd_ovs_vswitchd_SOURCES = \ vswitchd/bridge.c \ vswitchd/bridge.h \ vswitchd/ovs-vswitchd.c \ vswitchd/system-stats.c \ vswitchd/system-stats.h \ vswitchd/xenserver.c \ vswitchd/xenserver.h vswitchd_ovs_vswitchd_LDADD = \ ofproto/libofproto.la \ lib/libsflow.la \ lib/libopenvswitch.la vswitchd_ovs_vswitchd_LDFLAGS = $(AM_LDFLAGS) $(DPDK_vswitchd_LDFLAGS) @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@VSWITCH_PIC = vswitchd/vswitch.pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@VSWITCH_DOT_DIAGRAM_ARG = --er-diagram=$(VSWITCH_PIC) ovsdb_libovsdb_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -Wl,--version-script=$(top_builddir)/ovsdb/libovsdb.sym \ $(AM_LDFLAGS) ovsdb_libovsdb_la_SOURCES = \ ovsdb/column.c \ ovsdb/column.h \ ovsdb/condition.c \ ovsdb/condition.h \ ovsdb/execution.c \ ovsdb/file.c \ ovsdb/file.h \ ovsdb/jsonrpc-server.c \ ovsdb/jsonrpc-server.h \ ovsdb/log.c \ ovsdb/log.h \ ovsdb/mutation.c \ ovsdb/mutation.h \ ovsdb/ovsdb.c \ ovsdb/ovsdb.h \ ovsdb/monitor.c \ ovsdb/monitor.h \ ovsdb/query.c \ ovsdb/query.h \ ovsdb/row.c \ ovsdb/row.h \ ovsdb/server.c \ ovsdb/server.h \ ovsdb/table.c \ ovsdb/table.h \ ovsdb/trigger.c \ ovsdb/trigger.h \ ovsdb/transaction.c \ ovsdb/transaction.h ovsdb_libovsdb_la_CFLAGS = $(AM_CFLAGS) ovsdb_libovsdb_la_CPPFLAGS = $(AM_CPPFLAGS) ovsdb_ovsdb_tool_SOURCES = ovsdb/ovsdb-tool.c ovsdb_ovsdb_tool_LDADD = ovsdb/libovsdb.la lib/libopenvswitch.la ovsdb_ovsdb_client_SOURCES = ovsdb/ovsdb-client.c ovsdb_ovsdb_client_LDADD = ovsdb/libovsdb.la lib/libopenvswitch.la ovsdb_ovsdb_server_SOURCES = ovsdb/ovsdb-server.c ovsdb_ovsdb_server_LDADD = ovsdb/libovsdb.la lib/libopenvswitch.la OVSDB_IDLC = $(run_python) $(srcdir)/ovsdb/ovsdb-idlc.in OVSDB_DOC = $(run_python) $(srcdir)/ovsdb/ovsdb-doc OVSDB_DOT = $(run_python) $(srcdir)/ovsdb/ovsdb-dot.in update_rhel_spec = \ $(AM_V_GEN)($(ro_shell) && sed -e 's,[@]VERSION[@],$(VERSION),g') \ < $(srcdir)/rhel/$(@F).in > $(@F).tmp || exit 1; \ if cmp -s $(@F).tmp $@; then touch $@; rm $(@F).tmp; else mv $(@F).tmp $@; fi ovstest_pyfiles = \ python/ovstest/__init__.py \ python/ovstest/args.py \ python/ovstest/rpcserver.py \ python/ovstest/tcp.py \ python/ovstest/tests.py \ python/ovstest/udp.py \ python/ovstest/util.py \ python/ovstest/vswitch.py ovs_pyfiles = \ python/ovs/__init__.py \ python/ovs/daemon.py \ python/ovs/db/__init__.py \ python/ovs/db/data.py \ python/ovs/db/error.py \ python/ovs/db/idl.py \ python/ovs/db/parser.py \ python/ovs/db/schema.py \ python/ovs/db/types.py \ python/ovs/fatal_signal.py \ python/ovs/json.py \ python/ovs/jsonrpc.py \ python/ovs/ovsuuid.py \ python/ovs/poller.py \ python/ovs/process.py \ python/ovs/reconnect.py \ python/ovs/socket_util.py \ python/ovs/stream.py \ python/ovs/timeval.py \ python/ovs/unixctl/__init__.py \ python/ovs/unixctl/client.py \ python/ovs/unixctl/server.py \ python/ovs/util.py \ python/ovs/version.py \ python/ovs/vlog.py PYFILES = $(ovs_pyfiles) python/ovs/dirs.py $(ovstest_pyfiles) @HAVE_PYTHON_TRUE@nobase_pkgdata_DATA = $(ovs_pyfiles) $(ovstest_pyfiles) VTEP_IDL_FILES = \ $(srcdir)/vtep/vtep.ovsschema \ $(srcdir)/vtep/vtep-idl.ann vtep_libvtep_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -Wl,--version-script=$(top_builddir)/vtep/libvtep.sym \ $(AM_LDFLAGS) nodist_vtep_libvtep_la_SOURCES = \ vtep/vtep-idl.c \ vtep/vtep-idl.h vtep_vtep_ctl_SOURCES = vtep/vtep-ctl.c vtep_vtep_ctl_LDADD = vtep/libvtep.la lib/libopenvswitch.la @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@VTEP_PIC = vtep/vtep.pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@VTEP_DOT_DIAGRAM_ARG = --er-diagram=$(VTEP_PIC) PTHREAD_TEMP_DIR = `echo "$(PTHREAD_LDFLAGS)" | sed 's|^.\(.*\).$:\1||'` @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@OVN_SB_PIC = ovn/ovn-sb.pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@OVN_SB_DOT_DIAGRAM_ARG = --er-diagram=$(OVN_SB_PIC) @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@OVN_NB_PIC = ovn/ovn-nb.pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@OVN_NB_DOT_DIAGRAM_ARG = --er-diagram=$(OVN_NB_PIC) ovn_controller_ovn_controller_SOURCES = \ ovn/controller/binding.c \ ovn/controller/binding.h \ ovn/controller/chassis.c \ ovn/controller/chassis.h \ ovn/controller/encaps.c \ ovn/controller/encaps.h \ ovn/controller/lflow.c \ ovn/controller/lflow.h \ ovn/controller/ofctrl.c \ ovn/controller/ofctrl.h \ ovn/controller/pinctrl.c \ ovn/controller/pinctrl.h \ ovn/controller/patch.c \ ovn/controller/patch.h \ ovn/controller/ovn-controller.c \ ovn/controller/ovn-controller.h \ ovn/controller/physical.c \ ovn/controller/physical.h ovn_controller_ovn_controller_LDADD = ovn/lib/libovn.la lib/libopenvswitch.la ovn_controller_vtep_ovn_controller_vtep_SOURCES = \ ovn/controller-vtep/binding.c \ ovn/controller-vtep/binding.h \ ovn/controller-vtep/gateway.c \ ovn/controller-vtep/gateway.h \ ovn/controller-vtep/ovn-controller-vtep.c \ ovn/controller-vtep/ovn-controller-vtep.h \ ovn/controller-vtep/vtep.c \ ovn/controller-vtep/vtep.h ovn_controller_vtep_ovn_controller_vtep_LDADD = ovn/lib/libovn.la lib/libopenvswitch.la vtep/libvtep.la ovn_lib_libovn_la_LDFLAGS = \ -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ -Wl,--version-script=$(top_builddir)/ovn/lib/libovn.sym \ $(AM_LDFLAGS) ovn_lib_libovn_la_SOURCES = \ ovn/lib/actions.c \ ovn/lib/actions.h \ ovn/lib/expr.c \ ovn/lib/expr.h \ ovn/lib/lex.c \ ovn/lib/lex.h \ ovn/lib/logical-fields.h nodist_ovn_lib_libovn_la_SOURCES = \ ovn/lib/ovn-nb-idl.c \ ovn/lib/ovn-nb-idl.h \ ovn/lib/ovn-sb-idl.c \ ovn/lib/ovn-sb-idl.h OVN_SB_IDL_FILES = \ $(srcdir)/ovn/ovn-sb.ovsschema \ $(srcdir)/ovn/lib/ovn-sb-idl.ann OVN_NB_IDL_FILES = \ $(srcdir)/ovn/ovn-nb.ovsschema \ $(srcdir)/ovn/lib/ovn-nb-idl.ann ovn_northd_ovn_northd_SOURCES = ovn/northd/ovn-northd.c ovn_northd_ovn_northd_LDADD = \ ovn/lib/libovn.la \ ovsdb/libovsdb.la \ lib/libopenvswitch.la ovn_utilities_ovn_nbctl_SOURCES = ovn/utilities/ovn-nbctl.c ovn_utilities_ovn_nbctl_LDADD = ovn/lib/libovn.la ovsdb/libovsdb.la lib/libopenvswitch.la ovn_utilities_ovn_sbctl_SOURCES = ovn/utilities/ovn-sbctl.c ovn_utilities_ovn_sbctl_LDADD = ovn/lib/libovn.la ovsdb/libovsdb.la lib/libopenvswitch.la all: $(BUILT_SOURCES) config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive .SUFFIXES: .SUFFIXES: .in .xml .h .hstamp .ovsidl .ovsschema .c .lo .o .obj am--refresh: Makefile @: $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(srcdir)/manpages.mk $(srcdir)/Documentation/automake.mk $(srcdir)/m4/automake.mk $(srcdir)/lib/automake.mk $(srcdir)/ofproto/automake.mk $(srcdir)/utilities/automake.mk $(srcdir)/utilities/bugtool/automake.mk $(srcdir)/tests/automake.mk $(srcdir)/include/automake.mk $(srcdir)/include/openflow/automake.mk $(srcdir)/include/openvswitch/automake.mk $(srcdir)/include/sparse/automake.mk $(srcdir)/include/windows/automake.mk $(srcdir)/third-party/automake.mk $(srcdir)/debian/automake.mk $(srcdir)/vswitchd/automake.mk $(srcdir)/ovsdb/automake.mk $(srcdir)/rhel/automake.mk $(srcdir)/xenserver/automake.mk $(srcdir)/python/automake.mk $(srcdir)/tutorial/automake.mk $(srcdir)/vtep/automake.mk $(srcdir)/datapath-windows/automake.mk $(srcdir)/datapath-windows/include/automake.mk $(srcdir)/windows/automake.mk $(srcdir)/ovn/automake.mk $(srcdir)/ovn/controller/automake.mk $(srcdir)/ovn/controller-vtep/automake.mk $(srcdir)/ovn/lib/automake.mk $(srcdir)/ovn/northd/automake.mk $(srcdir)/ovn/utilities/automake.mk $(srcdir)/selinux/automake.mk $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ echo ' cd $(srcdir) && $(AUTOMAKE) --foreign'; \ $(am__cd) $(srcdir) && $(AUTOMAKE) --foreign \ && exit 0; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ echo ' $(SHELL) ./config.status'; \ $(SHELL) ./config.status;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \ esac; $(srcdir)/manpages.mk $(srcdir)/Documentation/automake.mk $(srcdir)/m4/automake.mk $(srcdir)/lib/automake.mk $(srcdir)/ofproto/automake.mk $(srcdir)/utilities/automake.mk $(srcdir)/utilities/bugtool/automake.mk $(srcdir)/tests/automake.mk $(srcdir)/include/automake.mk $(srcdir)/include/openflow/automake.mk $(srcdir)/include/openvswitch/automake.mk $(srcdir)/include/sparse/automake.mk $(srcdir)/include/windows/automake.mk $(srcdir)/third-party/automake.mk $(srcdir)/debian/automake.mk $(srcdir)/vswitchd/automake.mk $(srcdir)/ovsdb/automake.mk $(srcdir)/rhel/automake.mk $(srcdir)/xenserver/automake.mk $(srcdir)/python/automake.mk $(srcdir)/tutorial/automake.mk $(srcdir)/vtep/automake.mk $(srcdir)/datapath-windows/automake.mk $(srcdir)/datapath-windows/include/automake.mk $(srcdir)/windows/automake.mk $(srcdir)/ovn/automake.mk $(srcdir)/ovn/controller/automake.mk $(srcdir)/ovn/controller-vtep/automake.mk $(srcdir)/ovn/lib/automake.mk $(srcdir)/ovn/northd/automake.mk $(srcdir)/ovn/utilities/automake.mk $(srcdir)/selinux/automake.mk: $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck $(top_srcdir)/configure: $(am__configure_deps) $(am__cd) $(srcdir) && $(AUTOCONF) $(ACLOCAL_M4): $(am__aclocal_m4_deps) $(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) $(am__aclocal_m4_deps): config.h: stamp-h1 @test -f $@ || rm -f stamp-h1 @test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1 stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status @rm -f stamp-h1 cd $(top_builddir) && $(SHELL) ./config.status config.h $(srcdir)/config.h.in: $(am__configure_deps) ($(am__cd) $(top_srcdir) && $(AUTOHEADER)) rm -f stamp-h1 touch $@ distclean-hdr: -rm -f config.h stamp-h1 lib/stdio.h: $(top_builddir)/config.status $(top_srcdir)/lib/stdio.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ lib/string.h: $(top_builddir)/config.status $(top_srcdir)/lib/string.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ ovsdb/libovsdb.sym: $(top_builddir)/config.status $(top_srcdir)/ovsdb/libovsdb.sym.in cd $(top_builddir) && $(SHELL) ./config.status $@ ofproto/libofproto.sym: $(top_builddir)/config.status $(top_srcdir)/ofproto/libofproto.sym.in cd $(top_builddir) && $(SHELL) ./config.status $@ lib/libsflow.sym: $(top_builddir)/config.status $(top_srcdir)/lib/libsflow.sym.in cd $(top_builddir) && $(SHELL) ./config.status $@ lib/libopenvswitch.sym: $(top_builddir)/config.status $(top_srcdir)/lib/libopenvswitch.sym.in cd $(top_builddir) && $(SHELL) ./config.status $@ ovn/lib/libovn.sym: $(top_builddir)/config.status $(top_srcdir)/ovn/lib/libovn.sym.in cd $(top_builddir) && $(SHELL) ./config.status $@ vtep/libvtep.sym: $(top_builddir)/config.status $(top_srcdir)/vtep/libvtep.sym.in cd $(top_builddir) && $(SHELL) ./config.status $@ datapath/linux/Kbuild: $(top_builddir)/config.status $(top_srcdir)/datapath/linux/Kbuild.in cd $(top_builddir) && $(SHELL) ./config.status $@ datapath/linux/Makefile: $(top_builddir)/config.status $(top_srcdir)/datapath/linux/Makefile.in cd $(top_builddir) && $(SHELL) ./config.status $@ datapath/linux/Makefile.main: $(top_builddir)/config.status $(top_srcdir)/datapath/linux/Makefile.main.in cd $(top_builddir) && $(SHELL) ./config.status $@ tests/atlocal: $(top_builddir)/config.status $(top_srcdir)/tests/atlocal.in cd $(top_builddir) && $(SHELL) ./config.status $@ lib/libopenvswitch.pc: $(top_builddir)/config.status $(top_srcdir)/lib/libopenvswitch.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ lib/libsflow.pc: $(top_builddir)/config.status $(top_srcdir)/lib/libsflow.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ ofproto/libofproto.pc: $(top_builddir)/config.status $(top_srcdir)/ofproto/libofproto.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ ovsdb/libovsdb.pc: $(top_builddir)/config.status $(top_srcdir)/ovsdb/libovsdb.pc.in cd $(top_builddir) && $(SHELL) ./config.status $@ include/openvswitch/version.h: $(top_builddir)/config.status $(top_srcdir)/include/openvswitch/version.h.in cd $(top_builddir) && $(SHELL) ./config.status $@ install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } lib/$(am__dirstamp): @$(MKDIR_P) lib @: > lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) lib/$(DEPDIR) @: > lib/$(DEPDIR)/$(am__dirstamp) lib/aes128.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/backtrace.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/bfd.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/bundle.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/byteq.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/cfm.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/classifier.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/cmap.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/command-line.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/connectivity.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/coverage.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/crc32c.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/csum.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ct-dpif.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/daemon.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/db-ctl-base.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dummy.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dpctl.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dp-packet.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dpif-netdev.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dpif.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/heap.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dynamic-string.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/entropy.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/fat-rwlock.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/fatal-signal.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/flow.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/guarded-list.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/hash.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/hindex.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/hmap.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/hmapx.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/id-pool.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/jhash.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/json.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/jsonrpc.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/lacp.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/learn.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/learning-switch.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/lockfile.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/mac-learning.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/match.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/mcast-snooping.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/memory.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/meta-flow.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/multipath.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netdev-dummy.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netdev-vport.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netdev.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netlink.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/nx-match.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/odp-execute.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/odp-util.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ofp-actions.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ofp-errors.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ofp-msgs.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ofp-parse.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ofp-print.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ofp-util.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ofp-version-opt.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/ofpbuf.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovs-atomic-locked.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/ovs-lldp.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovs-rcu.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovs-router.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovs-thread.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovsdb-data.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovsdb-error.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovsdb-idl.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovsdb-parser.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/ovsdb-types.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/packets.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/pcap-file.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/perf-counter.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/poll-loop.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/process.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/pvector.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/random.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/rconn.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/reconnect.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/rstp.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/rstp-state-machines.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/seq.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/sha1.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/shash.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/simap.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/smap.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/socket-util.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/sort.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/sset.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/stp.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/stream-fd.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/stream-tcp.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/stream.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/stdio.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/string.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/svec.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/syslog-direct.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/syslog-libc.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/table.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/timer.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/timeval.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/tnl-neigh-cache.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/tnl-ports.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/token-bucket.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/tun-metadata.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/unicode.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/unixctl.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/util.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/uuid.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/vconn-stream.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/vconn.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/vlan-bitmap.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/vlandev.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/vlog.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/lldp/$(am__dirstamp): @$(MKDIR_P) lib/lldp @: > lib/lldp/$(am__dirstamp) lib/lldp/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) lib/lldp/$(DEPDIR) @: > lib/lldp/$(DEPDIR)/$(am__dirstamp) lib/lldp/lldp.lo: lib/lldp/$(am__dirstamp) \ lib/lldp/$(DEPDIR)/$(am__dirstamp) lib/lldp/lldpd.lo: lib/lldp/$(am__dirstamp) \ lib/lldp/$(DEPDIR)/$(am__dirstamp) lib/lldp/lldpd-structs.lo: lib/lldp/$(am__dirstamp) \ lib/lldp/$(DEPDIR)/$(am__dirstamp) lib/daemon-windows.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/getopt_long.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/getrusage-windows.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/latch-windows.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/route-table-stub.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/if-notifier-stub.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/strsep.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/daemon-unix.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/latch-unix.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/signals.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/socket-util-unix.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/stream-unix.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dpif-netlink.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/if-notifier.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netdev-linux.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netlink-conntrack.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/netlink-notifier.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/netlink-socket.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/ovs-numa.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/rtnetlink.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/route-table.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netdev-dpdk.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/netdev-windows.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/async-append-aio.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/async-append-null.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/if-notifier-bsd.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/netdev-bsd.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/rtbsd.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/route-table-bsd.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/stream-ssl.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/stream-nossl.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dirs.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/vswitch-idl.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/dhparams.lo: lib/$(am__dirstamp) lib/$(DEPDIR)/$(am__dirstamp) lib/libopenvswitch.la: $(lib_libopenvswitch_la_OBJECTS) $(lib_libopenvswitch_la_DEPENDENCIES) $(EXTRA_lib_libopenvswitch_la_DEPENDENCIES) lib/$(am__dirstamp) $(AM_V_CCLD)$(lib_libopenvswitch_la_LINK) -rpath $(libdir) $(lib_libopenvswitch_la_OBJECTS) $(lib_libopenvswitch_la_LIBADD) $(LIBS) lib/lib_libsflow_la-sflow_agent.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/lib_libsflow_la-sflow_sampler.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/lib_libsflow_la-sflow_poller.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/lib_libsflow_la-sflow_receiver.lo: lib/$(am__dirstamp) \ lib/$(DEPDIR)/$(am__dirstamp) lib/libsflow.la: $(lib_libsflow_la_OBJECTS) $(lib_libsflow_la_DEPENDENCIES) $(EXTRA_lib_libsflow_la_DEPENDENCIES) lib/$(am__dirstamp) $(AM_V_CCLD)$(lib_libsflow_la_LINK) -rpath $(libdir) $(lib_libsflow_la_OBJECTS) $(lib_libsflow_la_LIBADD) $(LIBS) ofproto/$(am__dirstamp): @$(MKDIR_P) ofproto @: > ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ofproto/$(DEPDIR) @: > ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-bond.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-collectors.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-connmgr.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-fail-open.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-in-band.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-names.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-netflow.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif-ipfix.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif-mirror.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif-monitor.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif-rid.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif-sflow.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif-upcall.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-ofproto-dpif-xlate.lo: \ ofproto/$(am__dirstamp) ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-pktbuf.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-pinsched.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-tunnel.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/ofproto_libofproto_la-bundles.lo: ofproto/$(am__dirstamp) \ ofproto/$(DEPDIR)/$(am__dirstamp) ofproto/libofproto.la: $(ofproto_libofproto_la_OBJECTS) $(ofproto_libofproto_la_DEPENDENCIES) $(EXTRA_ofproto_libofproto_la_DEPENDENCIES) ofproto/$(am__dirstamp) $(AM_V_CCLD)$(ofproto_libofproto_la_LINK) -rpath $(libdir) $(ofproto_libofproto_la_OBJECTS) $(ofproto_libofproto_la_LIBADD) $(LIBS) ovn/lib/$(am__dirstamp): @$(MKDIR_P) ovn/lib @: > ovn/lib/$(am__dirstamp) ovn/lib/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ovn/lib/$(DEPDIR) @: > ovn/lib/$(DEPDIR)/$(am__dirstamp) ovn/lib/actions.lo: ovn/lib/$(am__dirstamp) \ ovn/lib/$(DEPDIR)/$(am__dirstamp) ovn/lib/expr.lo: ovn/lib/$(am__dirstamp) \ ovn/lib/$(DEPDIR)/$(am__dirstamp) ovn/lib/lex.lo: ovn/lib/$(am__dirstamp) \ ovn/lib/$(DEPDIR)/$(am__dirstamp) ovn/lib/ovn-nb-idl.lo: ovn/lib/$(am__dirstamp) \ ovn/lib/$(DEPDIR)/$(am__dirstamp) ovn/lib/ovn-sb-idl.lo: ovn/lib/$(am__dirstamp) \ ovn/lib/$(DEPDIR)/$(am__dirstamp) ovn/lib/libovn.la: $(ovn_lib_libovn_la_OBJECTS) $(ovn_lib_libovn_la_DEPENDENCIES) $(EXTRA_ovn_lib_libovn_la_DEPENDENCIES) ovn/lib/$(am__dirstamp) $(AM_V_CCLD)$(ovn_lib_libovn_la_LINK) -rpath $(libdir) $(ovn_lib_libovn_la_OBJECTS) $(ovn_lib_libovn_la_LIBADD) $(LIBS) ovsdb/$(am__dirstamp): @$(MKDIR_P) ovsdb @: > ovsdb/$(am__dirstamp) ovsdb/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ovsdb/$(DEPDIR) @: > ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-column.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-condition.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-execution.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-file.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-jsonrpc-server.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-log.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-mutation.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-ovsdb.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-monitor.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-query.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-row.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-server.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-table.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-trigger.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb_libovsdb_la-transaction.lo: ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/libovsdb.la: $(ovsdb_libovsdb_la_OBJECTS) $(ovsdb_libovsdb_la_DEPENDENCIES) $(EXTRA_ovsdb_libovsdb_la_DEPENDENCIES) ovsdb/$(am__dirstamp) $(AM_V_CCLD)$(ovsdb_libovsdb_la_LINK) -rpath $(libdir) $(ovsdb_libovsdb_la_OBJECTS) $(ovsdb_libovsdb_la_LIBADD) $(LIBS) vtep/$(am__dirstamp): @$(MKDIR_P) vtep @: > vtep/$(am__dirstamp) vtep/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) vtep/$(DEPDIR) @: > vtep/$(DEPDIR)/$(am__dirstamp) vtep/vtep-idl.lo: vtep/$(am__dirstamp) vtep/$(DEPDIR)/$(am__dirstamp) vtep/libvtep.la: $(vtep_libvtep_la_OBJECTS) $(vtep_libvtep_la_DEPENDENCIES) $(EXTRA_vtep_libvtep_la_DEPENDENCIES) vtep/$(am__dirstamp) $(AM_V_CCLD)$(vtep_libvtep_la_LINK) -rpath $(libdir) $(vtep_libvtep_la_OBJECTS) $(vtep_libvtep_la_LIBADD) $(LIBS) install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(bindir)" && rm -f $$files clean-binPROGRAMS: @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list install-sbinPROGRAMS: $(sbin_PROGRAMS) @$(NORMAL_INSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do echo "$$p $$p"; done | \ sed 's/$(EXEEXT)$$//' | \ while read p p1; do if test -f $$p \ || test -f $$p1 \ ; then echo "$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n;h' \ -e 's|.*|.|' \ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) files[d] = files[d] " " $$1; \ else { print "f", $$3 "/" $$4, $$1; } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinPROGRAMS: @$(NORMAL_UNINSTALL) @list='$(sbin_PROGRAMS)'; test -n "$(sbindir)" || list=; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ -e 's/$$/$(EXEEXT)/' \ `; \ test -n "$$list" || exit 0; \ echo " ( cd '$(DESTDIR)$(sbindir)' && rm -f" $$files ")"; \ cd "$(DESTDIR)$(sbindir)" && rm -f $$files clean-sbinPROGRAMS: @list='$(sbin_PROGRAMS)'; test -n "$$list" || exit 0; \ echo " rm -f" $$list; \ rm -f $$list || exit $$?; \ test -n "$(EXEEXT)" || exit 0; \ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ echo " rm -f" $$list; \ rm -f $$list ovn/controller-vtep/$(am__dirstamp): @$(MKDIR_P) ovn/controller-vtep @: > ovn/controller-vtep/$(am__dirstamp) ovn/controller-vtep/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ovn/controller-vtep/$(DEPDIR) @: > ovn/controller-vtep/$(DEPDIR)/$(am__dirstamp) ovn/controller-vtep/binding.$(OBJEXT): \ ovn/controller-vtep/$(am__dirstamp) \ ovn/controller-vtep/$(DEPDIR)/$(am__dirstamp) ovn/controller-vtep/gateway.$(OBJEXT): \ ovn/controller-vtep/$(am__dirstamp) \ ovn/controller-vtep/$(DEPDIR)/$(am__dirstamp) ovn/controller-vtep/ovn-controller-vtep.$(OBJEXT): \ ovn/controller-vtep/$(am__dirstamp) \ ovn/controller-vtep/$(DEPDIR)/$(am__dirstamp) ovn/controller-vtep/vtep.$(OBJEXT): \ ovn/controller-vtep/$(am__dirstamp) \ ovn/controller-vtep/$(DEPDIR)/$(am__dirstamp) ovn/controller-vtep/ovn-controller-vtep$(EXEEXT): $(ovn_controller_vtep_ovn_controller_vtep_OBJECTS) $(ovn_controller_vtep_ovn_controller_vtep_DEPENDENCIES) $(EXTRA_ovn_controller_vtep_ovn_controller_vtep_DEPENDENCIES) ovn/controller-vtep/$(am__dirstamp) @rm -f ovn/controller-vtep/ovn-controller-vtep$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovn_controller_vtep_ovn_controller_vtep_OBJECTS) $(ovn_controller_vtep_ovn_controller_vtep_LDADD) $(LIBS) ovn/controller/$(am__dirstamp): @$(MKDIR_P) ovn/controller @: > ovn/controller/$(am__dirstamp) ovn/controller/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ovn/controller/$(DEPDIR) @: > ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/binding.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/chassis.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/encaps.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/lflow.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/ofctrl.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/pinctrl.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/patch.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/ovn-controller.$(OBJEXT): \ ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/physical.$(OBJEXT): ovn/controller/$(am__dirstamp) \ ovn/controller/$(DEPDIR)/$(am__dirstamp) ovn/controller/ovn-controller$(EXEEXT): $(ovn_controller_ovn_controller_OBJECTS) $(ovn_controller_ovn_controller_DEPENDENCIES) $(EXTRA_ovn_controller_ovn_controller_DEPENDENCIES) ovn/controller/$(am__dirstamp) @rm -f ovn/controller/ovn-controller$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovn_controller_ovn_controller_OBJECTS) $(ovn_controller_ovn_controller_LDADD) $(LIBS) ovn/northd/$(am__dirstamp): @$(MKDIR_P) ovn/northd @: > ovn/northd/$(am__dirstamp) ovn/northd/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ovn/northd/$(DEPDIR) @: > ovn/northd/$(DEPDIR)/$(am__dirstamp) ovn/northd/ovn-northd.$(OBJEXT): ovn/northd/$(am__dirstamp) \ ovn/northd/$(DEPDIR)/$(am__dirstamp) ovn/northd/ovn-northd$(EXEEXT): $(ovn_northd_ovn_northd_OBJECTS) $(ovn_northd_ovn_northd_DEPENDENCIES) $(EXTRA_ovn_northd_ovn_northd_DEPENDENCIES) ovn/northd/$(am__dirstamp) @rm -f ovn/northd/ovn-northd$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovn_northd_ovn_northd_OBJECTS) $(ovn_northd_ovn_northd_LDADD) $(LIBS) ovn/utilities/$(am__dirstamp): @$(MKDIR_P) ovn/utilities @: > ovn/utilities/$(am__dirstamp) ovn/utilities/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) ovn/utilities/$(DEPDIR) @: > ovn/utilities/$(DEPDIR)/$(am__dirstamp) ovn/utilities/ovn-nbctl.$(OBJEXT): ovn/utilities/$(am__dirstamp) \ ovn/utilities/$(DEPDIR)/$(am__dirstamp) ovn/utilities/ovn-nbctl$(EXEEXT): $(ovn_utilities_ovn_nbctl_OBJECTS) $(ovn_utilities_ovn_nbctl_DEPENDENCIES) $(EXTRA_ovn_utilities_ovn_nbctl_DEPENDENCIES) ovn/utilities/$(am__dirstamp) @rm -f ovn/utilities/ovn-nbctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovn_utilities_ovn_nbctl_OBJECTS) $(ovn_utilities_ovn_nbctl_LDADD) $(LIBS) ovn/utilities/ovn-sbctl.$(OBJEXT): ovn/utilities/$(am__dirstamp) \ ovn/utilities/$(DEPDIR)/$(am__dirstamp) ovn/utilities/ovn-sbctl$(EXEEXT): $(ovn_utilities_ovn_sbctl_OBJECTS) $(ovn_utilities_ovn_sbctl_DEPENDENCIES) $(EXTRA_ovn_utilities_ovn_sbctl_DEPENDENCIES) ovn/utilities/$(am__dirstamp) @rm -f ovn/utilities/ovn-sbctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovn_utilities_ovn_sbctl_OBJECTS) $(ovn_utilities_ovn_sbctl_LDADD) $(LIBS) ovsdb/ovsdb-client.$(OBJEXT): ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb-client$(EXEEXT): $(ovsdb_ovsdb_client_OBJECTS) $(ovsdb_ovsdb_client_DEPENDENCIES) $(EXTRA_ovsdb_ovsdb_client_DEPENDENCIES) ovsdb/$(am__dirstamp) @rm -f ovsdb/ovsdb-client$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovsdb_ovsdb_client_OBJECTS) $(ovsdb_ovsdb_client_LDADD) $(LIBS) ovsdb/ovsdb-server.$(OBJEXT): ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb-server$(EXEEXT): $(ovsdb_ovsdb_server_OBJECTS) $(ovsdb_ovsdb_server_DEPENDENCIES) $(EXTRA_ovsdb_ovsdb_server_DEPENDENCIES) ovsdb/$(am__dirstamp) @rm -f ovsdb/ovsdb-server$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovsdb_ovsdb_server_OBJECTS) $(ovsdb_ovsdb_server_LDADD) $(LIBS) ovsdb/ovsdb-tool.$(OBJEXT): ovsdb/$(am__dirstamp) \ ovsdb/$(DEPDIR)/$(am__dirstamp) ovsdb/ovsdb-tool$(EXEEXT): $(ovsdb_ovsdb_tool_OBJECTS) $(ovsdb_ovsdb_tool_DEPENDENCIES) $(EXTRA_ovsdb_ovsdb_tool_DEPENDENCIES) ovsdb/$(am__dirstamp) @rm -f ovsdb/ovsdb-tool$(EXEEXT) $(AM_V_CCLD)$(LINK) $(ovsdb_ovsdb_tool_OBJECTS) $(ovsdb_ovsdb_tool_LDADD) $(LIBS) tests/$(am__dirstamp): @$(MKDIR_P) tests @: > tests/$(am__dirstamp) tests/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tests/$(DEPDIR) @: > tests/$(DEPDIR)/$(am__dirstamp) tests/ovstest.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-aes128.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-atomic.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-bundle.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-byte-order.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-classifier.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-cmap.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-csum.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-flows.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-hash.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-heap.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-hindex.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-hmap.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-json.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-jsonrpc.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-list.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-lockfile.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-multipath.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-netflow.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-odp.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-ofpbuf.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-ovn.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-packets.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-random.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-reconnect.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-rstp.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-sflow.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-sha1.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-stp.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-util.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-uuid.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-bitmap.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-vconn.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-aa.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-unix-socket.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-netlink-conntrack.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/ovstest$(EXEEXT): $(tests_ovstest_OBJECTS) $(tests_ovstest_DEPENDENCIES) $(EXTRA_tests_ovstest_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/ovstest$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tests_ovstest_OBJECTS) $(tests_ovstest_LDADD) $(LIBS) tests/dpdk/$(am__dirstamp): @$(MKDIR_P) tests/dpdk @: > tests/dpdk/$(am__dirstamp) tests/dpdk/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) tests/dpdk/$(DEPDIR) @: > tests/dpdk/$(DEPDIR)/$(am__dirstamp) tests/dpdk/ring_client.$(OBJEXT): tests/dpdk/$(am__dirstamp) \ tests/dpdk/$(DEPDIR)/$(am__dirstamp) tests/test-dpdkr$(EXEEXT): $(tests_test_dpdkr_OBJECTS) $(tests_test_dpdkr_DEPENDENCIES) $(EXTRA_tests_test_dpdkr_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/test-dpdkr$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tests_test_dpdkr_OBJECTS) $(tests_test_dpdkr_LDADD) $(LIBS) tests/test-lib.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-lib$(EXEEXT): $(tests_test_lib_OBJECTS) $(tests_test_lib_DEPENDENCIES) $(EXTRA_tests_test_lib_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/test-lib$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tests_test_lib_OBJECTS) $(tests_test_lib_LDADD) $(LIBS) tests/test-ovsdb.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/idltest.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-ovsdb$(EXEEXT): $(tests_test_ovsdb_OBJECTS) $(tests_test_ovsdb_DEPENDENCIES) $(EXTRA_tests_test_ovsdb_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/test-ovsdb$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tests_test_ovsdb_OBJECTS) $(tests_test_ovsdb_LDADD) $(LIBS) tests/test-strtok_r.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-strtok_r$(EXEEXT): $(tests_test_strtok_r_OBJECTS) $(tests_test_strtok_r_DEPENDENCIES) $(EXTRA_tests_test_strtok_r_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/test-strtok_r$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tests_test_strtok_r_OBJECTS) $(tests_test_strtok_r_LDADD) $(LIBS) tests/test-type-props.$(OBJEXT): tests/$(am__dirstamp) \ tests/$(DEPDIR)/$(am__dirstamp) tests/test-type-props$(EXEEXT): $(tests_test_type_props_OBJECTS) $(tests_test_type_props_DEPENDENCIES) $(EXTRA_tests_test_type_props_DEPENDENCIES) tests/$(am__dirstamp) @rm -f tests/test-type-props$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tests_test_type_props_OBJECTS) $(tests_test_type_props_LDADD) $(LIBS) utilities/$(am__dirstamp): @$(MKDIR_P) utilities @: > utilities/$(am__dirstamp) utilities/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) utilities/$(DEPDIR) @: > utilities/$(DEPDIR)/$(am__dirstamp) utilities/nlmon.$(OBJEXT): utilities/$(am__dirstamp) \ utilities/$(DEPDIR)/$(am__dirstamp) utilities/nlmon$(EXEEXT): $(utilities_nlmon_OBJECTS) $(utilities_nlmon_DEPENDENCIES) $(EXTRA_utilities_nlmon_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/nlmon$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_nlmon_OBJECTS) $(utilities_nlmon_LDADD) $(LIBS) utilities/ovs-appctl.$(OBJEXT): utilities/$(am__dirstamp) \ utilities/$(DEPDIR)/$(am__dirstamp) utilities/ovs-appctl$(EXEEXT): $(utilities_ovs_appctl_OBJECTS) $(utilities_ovs_appctl_DEPENDENCIES) $(EXTRA_utilities_ovs_appctl_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/ovs-appctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_ovs_appctl_OBJECTS) $(utilities_ovs_appctl_LDADD) $(LIBS) utilities/ovs-benchmark.$(OBJEXT): utilities/$(am__dirstamp) \ utilities/$(DEPDIR)/$(am__dirstamp) utilities/ovs-benchmark$(EXEEXT): $(utilities_ovs_benchmark_OBJECTS) $(utilities_ovs_benchmark_DEPENDENCIES) $(EXTRA_utilities_ovs_benchmark_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/ovs-benchmark$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_ovs_benchmark_OBJECTS) $(utilities_ovs_benchmark_LDADD) $(LIBS) utilities/ovs-dpctl.$(OBJEXT): utilities/$(am__dirstamp) \ utilities/$(DEPDIR)/$(am__dirstamp) utilities/ovs-dpctl$(EXEEXT): $(utilities_ovs_dpctl_OBJECTS) $(utilities_ovs_dpctl_DEPENDENCIES) $(EXTRA_utilities_ovs_dpctl_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/ovs-dpctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_ovs_dpctl_OBJECTS) $(utilities_ovs_dpctl_LDADD) $(LIBS) utilities/ovs-ofctl.$(OBJEXT): utilities/$(am__dirstamp) \ utilities/$(DEPDIR)/$(am__dirstamp) utilities/ovs-ofctl$(EXEEXT): $(utilities_ovs_ofctl_OBJECTS) $(utilities_ovs_ofctl_DEPENDENCIES) $(EXTRA_utilities_ovs_ofctl_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/ovs-ofctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_ovs_ofctl_OBJECTS) $(utilities_ovs_ofctl_LDADD) $(LIBS) utilities/ovs-testcontroller.$(OBJEXT): utilities/$(am__dirstamp) \ utilities/$(DEPDIR)/$(am__dirstamp) utilities/ovs-testcontroller$(EXEEXT): $(utilities_ovs_testcontroller_OBJECTS) $(utilities_ovs_testcontroller_DEPENDENCIES) $(EXTRA_utilities_ovs_testcontroller_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/ovs-testcontroller$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_ovs_testcontroller_OBJECTS) $(utilities_ovs_testcontroller_LDADD) $(LIBS) utilities/ovs-vlan-bug-workaround.$(OBJEXT): \ utilities/$(am__dirstamp) utilities/$(DEPDIR)/$(am__dirstamp) utilities/ovs-vlan-bug-workaround$(EXEEXT): $(utilities_ovs_vlan_bug_workaround_OBJECTS) $(utilities_ovs_vlan_bug_workaround_DEPENDENCIES) $(EXTRA_utilities_ovs_vlan_bug_workaround_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/ovs-vlan-bug-workaround$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_ovs_vlan_bug_workaround_OBJECTS) $(utilities_ovs_vlan_bug_workaround_LDADD) $(LIBS) utilities/ovs-vsctl.$(OBJEXT): utilities/$(am__dirstamp) \ utilities/$(DEPDIR)/$(am__dirstamp) utilities/ovs-vsctl$(EXEEXT): $(utilities_ovs_vsctl_OBJECTS) $(utilities_ovs_vsctl_DEPENDENCIES) $(EXTRA_utilities_ovs_vsctl_DEPENDENCIES) utilities/$(am__dirstamp) @rm -f utilities/ovs-vsctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(utilities_ovs_vsctl_OBJECTS) $(utilities_ovs_vsctl_LDADD) $(LIBS) vswitchd/$(am__dirstamp): @$(MKDIR_P) vswitchd @: > vswitchd/$(am__dirstamp) vswitchd/$(DEPDIR)/$(am__dirstamp): @$(MKDIR_P) vswitchd/$(DEPDIR) @: > vswitchd/$(DEPDIR)/$(am__dirstamp) vswitchd/bridge.$(OBJEXT): vswitchd/$(am__dirstamp) \ vswitchd/$(DEPDIR)/$(am__dirstamp) vswitchd/ovs-vswitchd.$(OBJEXT): vswitchd/$(am__dirstamp) \ vswitchd/$(DEPDIR)/$(am__dirstamp) vswitchd/system-stats.$(OBJEXT): vswitchd/$(am__dirstamp) \ vswitchd/$(DEPDIR)/$(am__dirstamp) vswitchd/xenserver.$(OBJEXT): vswitchd/$(am__dirstamp) \ vswitchd/$(DEPDIR)/$(am__dirstamp) vswitchd/ovs-vswitchd$(EXEEXT): $(vswitchd_ovs_vswitchd_OBJECTS) $(vswitchd_ovs_vswitchd_DEPENDENCIES) $(EXTRA_vswitchd_ovs_vswitchd_DEPENDENCIES) vswitchd/$(am__dirstamp) @rm -f vswitchd/ovs-vswitchd$(EXEEXT) $(AM_V_CCLD)$(vswitchd_ovs_vswitchd_LINK) $(vswitchd_ovs_vswitchd_OBJECTS) $(vswitchd_ovs_vswitchd_LDADD) $(LIBS) vtep/vtep-ctl.$(OBJEXT): vtep/$(am__dirstamp) \ vtep/$(DEPDIR)/$(am__dirstamp) vtep/vtep-ctl$(EXEEXT): $(vtep_vtep_ctl_OBJECTS) $(vtep_vtep_ctl_DEPENDENCIES) $(EXTRA_vtep_vtep_ctl_DEPENDENCIES) vtep/$(am__dirstamp) @rm -f vtep/vtep-ctl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(vtep_vtep_ctl_OBJECTS) $(vtep_vtep_ctl_LDADD) $(LIBS) install-binSCRIPTS: $(bin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(bindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ } \ ; done uninstall-binSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(bin_SCRIPTS)'; test -n "$(bindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(bindir)'; $(am__uninstall_files_from_dir) install-completionSCRIPTS: $(completion_SCRIPTS) @$(NORMAL_INSTALL) @list='$(completion_SCRIPTS)'; test -n "$(completiondir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(completiondir)'"; \ $(MKDIR_P) "$(DESTDIR)$(completiondir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(completiondir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(completiondir)$$dir" || exit $$?; \ } \ ; done uninstall-completionSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(completion_SCRIPTS)'; test -n "$(completiondir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(completiondir)'; $(am__uninstall_files_from_dir) install-dist_pkgdataSCRIPTS: $(dist_pkgdata_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_pkgdata_SCRIPTS)'; test -n "$(pkgdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(pkgdatadir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(pkgdatadir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_pkgdataSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_pkgdata_SCRIPTS)'; test -n "$(pkgdatadir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) install-dist_sbinSCRIPTS: $(dist_sbin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_sbin_SCRIPTS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_sbinSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_sbin_SCRIPTS)'; test -n "$(sbindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(sbindir)'; $(am__uninstall_files_from_dir) install-dist_scriptsSCRIPTS: $(dist_scripts_SCRIPTS) @$(NORMAL_INSTALL) @list='$(dist_scripts_SCRIPTS)'; test -n "$(scriptsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(scriptsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(scriptsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(scriptsdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(scriptsdir)$$dir" || exit $$?; \ } \ ; done uninstall-dist_scriptsSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(dist_scripts_SCRIPTS)'; test -n "$(scriptsdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(scriptsdir)'; $(am__uninstall_files_from_dir) install-sbinSCRIPTS: $(sbin_SCRIPTS) @$(NORMAL_INSTALL) @list='$(sbin_SCRIPTS)'; test -n "$(sbindir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(sbindir)'"; \ $(MKDIR_P) "$(DESTDIR)$(sbindir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(sbindir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(sbindir)$$dir" || exit $$?; \ } \ ; done uninstall-sbinSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(sbin_SCRIPTS)'; test -n "$(sbindir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(sbindir)'; $(am__uninstall_files_from_dir) install-scriptsSCRIPTS: $(scripts_SCRIPTS) @$(NORMAL_INSTALL) @list='$(scripts_SCRIPTS)'; test -n "$(scriptsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(scriptsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(scriptsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ if test -f "$$d$$p"; then echo "$$d$$p"; echo "$$p"; else :; fi; \ done | \ sed -e 'p;s,.*/,,;n' \ -e 'h;s|.*|.|' \ -e 'p;x;s,.*/,,;$(transform)' | sed 'N;N;N;s,\n, ,g' | \ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1; } \ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ if ($$2 == $$4) { files[d] = files[d] " " $$1; \ if (++n[d] == $(am__install_max)) { \ print "f", d, files[d]; n[d] = 0; files[d] = "" } } \ else { print "f", d "/" $$4, $$1 } } \ END { for (d in files) print "f", d, files[d] }' | \ while read type dir files; do \ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ test -z "$$files" || { \ echo " $(INSTALL_SCRIPT) $$files '$(DESTDIR)$(scriptsdir)$$dir'"; \ $(INSTALL_SCRIPT) $$files "$(DESTDIR)$(scriptsdir)$$dir" || exit $$?; \ } \ ; done uninstall-scriptsSCRIPTS: @$(NORMAL_UNINSTALL) @list='$(scripts_SCRIPTS)'; test -n "$(scriptsdir)" || exit 0; \ files=`for p in $$list; do echo "$$p"; done | \ sed -e 's,.*/,,;$(transform)'`; \ dir='$(DESTDIR)$(scriptsdir)'; $(am__uninstall_files_from_dir) mostlyclean-compile: -rm -f *.$(OBJEXT) -rm -f lib/*.$(OBJEXT) -rm -f lib/*.lo -rm -f lib/lldp/*.$(OBJEXT) -rm -f lib/lldp/*.lo -rm -f ofproto/*.$(OBJEXT) -rm -f ofproto/*.lo -rm -f ovn/controller-vtep/*.$(OBJEXT) -rm -f ovn/controller/*.$(OBJEXT) -rm -f ovn/lib/*.$(OBJEXT) -rm -f ovn/lib/*.lo -rm -f ovn/northd/*.$(OBJEXT) -rm -f ovn/utilities/*.$(OBJEXT) -rm -f ovsdb/*.$(OBJEXT) -rm -f ovsdb/*.lo -rm -f tests/*.$(OBJEXT) -rm -f tests/dpdk/*.$(OBJEXT) -rm -f utilities/*.$(OBJEXT) -rm -f vswitchd/*.$(OBJEXT) -rm -f vtep/*.$(OBJEXT) -rm -f vtep/*.lo distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/aes128.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/async-append-aio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/async-append-null.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/backtrace.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/bfd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/bundle.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/byteq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/cfm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/classifier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/cmap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/command-line.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/connectivity.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/coverage.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/crc32c.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/csum.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ct-dpif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/daemon-unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/daemon-windows.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/daemon.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/db-ctl-base.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dhparams.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dirs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dp-packet.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dpctl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dpif-netdev.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dpif-netlink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dpif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dummy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/dynamic-string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/entropy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/fat-rwlock.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/fatal-signal.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/flow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/getopt_long.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/getrusage-windows.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/guarded-list.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/hash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/heap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/hindex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/hmap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/hmapx.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/id-pool.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/if-notifier-bsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/if-notifier-stub.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/if-notifier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/jhash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/json.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/jsonrpc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lacp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/latch-unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/latch-windows.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/learn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/learning-switch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libsflow_la-sflow_agent.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libsflow_la-sflow_poller.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libsflow_la-sflow_receiver.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lib_libsflow_la-sflow_sampler.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/lockfile.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/mac-learning.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/match.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/mcast-snooping.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/memory.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/meta-flow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/multipath.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netdev-bsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netdev-dpdk.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netdev-dummy.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netdev-linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netdev-vport.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netdev-windows.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netdev.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netlink-conntrack.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netlink-notifier.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netlink-socket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/netlink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/nx-match.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/odp-execute.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/odp-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofp-actions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofp-errors.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofp-msgs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofp-parse.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofp-print.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofp-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofp-version-opt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ofpbuf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovs-atomic-locked.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovs-lldp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovs-numa.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovs-rcu.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovs-router.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovs-thread.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovsdb-data.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovsdb-error.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovsdb-idl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovsdb-parser.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/ovsdb-types.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/packets.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/pcap-file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/perf-counter.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/poll-loop.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/process.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/pvector.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/random.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/rconn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/reconnect.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/route-table-bsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/route-table-stub.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/route-table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/rstp-state-machines.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/rstp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/rtbsd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/rtnetlink.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/seq.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/sha1.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/shash.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/signals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/simap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/smap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/socket-util-unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/socket-util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/sort.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/sset.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stdio.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stream-fd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stream-nossl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stream-ssl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stream-tcp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stream-unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/string.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/strsep.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/svec.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/syslog-direct.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/syslog-libc.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/timer.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/timeval.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/tnl-neigh-cache.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/tnl-ports.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/token-bucket.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/tun-metadata.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/unicode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/unixctl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/util.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/uuid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/vconn-stream.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/vconn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/vlan-bitmap.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/vlandev.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/vlog.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/$(DEPDIR)/vswitch-idl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/lldp/$(DEPDIR)/lldp.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/lldp/$(DEPDIR)/lldpd-structs.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@lib/lldp/$(DEPDIR)/lldpd.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-bond.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-bundles.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-collectors.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-connmgr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-fail-open.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-in-band.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-names.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-netflow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-ipfix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-mirror.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-monitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-rid.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-sflow.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-upcall.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-xlate.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-pinsched.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-pktbuf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ofproto/$(DEPDIR)/ofproto_libofproto_la-tunnel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller-vtep/$(DEPDIR)/binding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller-vtep/$(DEPDIR)/gateway.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller-vtep/$(DEPDIR)/ovn-controller-vtep.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller-vtep/$(DEPDIR)/vtep.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/binding.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/chassis.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/encaps.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/lflow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/ofctrl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/ovn-controller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/patch.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/physical.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/controller/$(DEPDIR)/pinctrl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/lib/$(DEPDIR)/actions.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/lib/$(DEPDIR)/expr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/lib/$(DEPDIR)/lex.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/lib/$(DEPDIR)/ovn-nb-idl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/lib/$(DEPDIR)/ovn-sb-idl.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/northd/$(DEPDIR)/ovn-northd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/utilities/$(DEPDIR)/ovn-nbctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovn/utilities/$(DEPDIR)/ovn-sbctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb-client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb-server.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb-tool.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-column.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-condition.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-execution.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-file.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-jsonrpc-server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-log.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-monitor.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-mutation.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-ovsdb.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-query.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-row.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-server.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-table.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-transaction.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-trigger.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/idltest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/ovstest.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-aa.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-aes128.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-atomic.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-bitmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-bundle.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-byte-order.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-classifier.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-cmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-csum.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-flows.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-hash.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-heap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-hindex.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-hmap.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-json.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-jsonrpc.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-lib.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-list.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-lockfile.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-multipath.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-netflow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-netlink-conntrack.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-odp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-ofpbuf.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-ovn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-ovsdb.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-packets.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-random.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-reconnect.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-rstp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-sflow.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-sha1.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-stp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-strtok_r.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-type-props.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-unix-socket.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-util.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-uuid.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/$(DEPDIR)/test-vconn.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@tests/dpdk/$(DEPDIR)/ring_client.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/nlmon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/ovs-appctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/ovs-benchmark.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/ovs-dpctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/ovs-ofctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/ovs-testcontroller.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/ovs-vlan-bug-workaround.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@utilities/$(DEPDIR)/ovs-vsctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vswitchd/$(DEPDIR)/bridge.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vswitchd/$(DEPDIR)/ovs-vswitchd.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vswitchd/$(DEPDIR)/system-stats.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vswitchd/$(DEPDIR)/xenserver.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtep/$(DEPDIR)/vtep-ctl.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@vtep/$(DEPDIR)/vtep-idl.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\ @am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\ @am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\ @am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< lib/lib_libsflow_la-sflow_agent.lo: lib/sflow_agent.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -MT lib/lib_libsflow_la-sflow_agent.lo -MD -MP -MF lib/$(DEPDIR)/lib_libsflow_la-sflow_agent.Tpo -c -o lib/lib_libsflow_la-sflow_agent.lo `test -f 'lib/sflow_agent.c' || echo '$(srcdir)/'`lib/sflow_agent.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_libsflow_la-sflow_agent.Tpo lib/$(DEPDIR)/lib_libsflow_la-sflow_agent.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/sflow_agent.c' object='lib/lib_libsflow_la-sflow_agent.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -c -o lib/lib_libsflow_la-sflow_agent.lo `test -f 'lib/sflow_agent.c' || echo '$(srcdir)/'`lib/sflow_agent.c lib/lib_libsflow_la-sflow_sampler.lo: lib/sflow_sampler.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -MT lib/lib_libsflow_la-sflow_sampler.lo -MD -MP -MF lib/$(DEPDIR)/lib_libsflow_la-sflow_sampler.Tpo -c -o lib/lib_libsflow_la-sflow_sampler.lo `test -f 'lib/sflow_sampler.c' || echo '$(srcdir)/'`lib/sflow_sampler.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_libsflow_la-sflow_sampler.Tpo lib/$(DEPDIR)/lib_libsflow_la-sflow_sampler.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/sflow_sampler.c' object='lib/lib_libsflow_la-sflow_sampler.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -c -o lib/lib_libsflow_la-sflow_sampler.lo `test -f 'lib/sflow_sampler.c' || echo '$(srcdir)/'`lib/sflow_sampler.c lib/lib_libsflow_la-sflow_poller.lo: lib/sflow_poller.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -MT lib/lib_libsflow_la-sflow_poller.lo -MD -MP -MF lib/$(DEPDIR)/lib_libsflow_la-sflow_poller.Tpo -c -o lib/lib_libsflow_la-sflow_poller.lo `test -f 'lib/sflow_poller.c' || echo '$(srcdir)/'`lib/sflow_poller.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_libsflow_la-sflow_poller.Tpo lib/$(DEPDIR)/lib_libsflow_la-sflow_poller.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/sflow_poller.c' object='lib/lib_libsflow_la-sflow_poller.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -c -o lib/lib_libsflow_la-sflow_poller.lo `test -f 'lib/sflow_poller.c' || echo '$(srcdir)/'`lib/sflow_poller.c lib/lib_libsflow_la-sflow_receiver.lo: lib/sflow_receiver.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -MT lib/lib_libsflow_la-sflow_receiver.lo -MD -MP -MF lib/$(DEPDIR)/lib_libsflow_la-sflow_receiver.Tpo -c -o lib/lib_libsflow_la-sflow_receiver.lo `test -f 'lib/sflow_receiver.c' || echo '$(srcdir)/'`lib/sflow_receiver.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) lib/$(DEPDIR)/lib_libsflow_la-sflow_receiver.Tpo lib/$(DEPDIR)/lib_libsflow_la-sflow_receiver.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/sflow_receiver.c' object='lib/lib_libsflow_la-sflow_receiver.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(lib_libsflow_la_CPPFLAGS) $(CPPFLAGS) $(lib_libsflow_la_CFLAGS) $(CFLAGS) -c -o lib/lib_libsflow_la-sflow_receiver.lo `test -f 'lib/sflow_receiver.c' || echo '$(srcdir)/'`lib/sflow_receiver.c ofproto/ofproto_libofproto_la-bond.lo: ofproto/bond.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-bond.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-bond.Tpo -c -o ofproto/ofproto_libofproto_la-bond.lo `test -f 'ofproto/bond.c' || echo '$(srcdir)/'`ofproto/bond.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-bond.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-bond.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/bond.c' object='ofproto/ofproto_libofproto_la-bond.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-bond.lo `test -f 'ofproto/bond.c' || echo '$(srcdir)/'`ofproto/bond.c ofproto/ofproto_libofproto_la-collectors.lo: ofproto/collectors.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-collectors.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-collectors.Tpo -c -o ofproto/ofproto_libofproto_la-collectors.lo `test -f 'ofproto/collectors.c' || echo '$(srcdir)/'`ofproto/collectors.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-collectors.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-collectors.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/collectors.c' object='ofproto/ofproto_libofproto_la-collectors.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-collectors.lo `test -f 'ofproto/collectors.c' || echo '$(srcdir)/'`ofproto/collectors.c ofproto/ofproto_libofproto_la-connmgr.lo: ofproto/connmgr.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-connmgr.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-connmgr.Tpo -c -o ofproto/ofproto_libofproto_la-connmgr.lo `test -f 'ofproto/connmgr.c' || echo '$(srcdir)/'`ofproto/connmgr.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-connmgr.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-connmgr.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/connmgr.c' object='ofproto/ofproto_libofproto_la-connmgr.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-connmgr.lo `test -f 'ofproto/connmgr.c' || echo '$(srcdir)/'`ofproto/connmgr.c ofproto/ofproto_libofproto_la-fail-open.lo: ofproto/fail-open.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-fail-open.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-fail-open.Tpo -c -o ofproto/ofproto_libofproto_la-fail-open.lo `test -f 'ofproto/fail-open.c' || echo '$(srcdir)/'`ofproto/fail-open.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-fail-open.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-fail-open.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/fail-open.c' object='ofproto/ofproto_libofproto_la-fail-open.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-fail-open.lo `test -f 'ofproto/fail-open.c' || echo '$(srcdir)/'`ofproto/fail-open.c ofproto/ofproto_libofproto_la-in-band.lo: ofproto/in-band.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-in-band.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-in-band.Tpo -c -o ofproto/ofproto_libofproto_la-in-band.lo `test -f 'ofproto/in-band.c' || echo '$(srcdir)/'`ofproto/in-band.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-in-band.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-in-band.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/in-band.c' object='ofproto/ofproto_libofproto_la-in-band.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-in-band.lo `test -f 'ofproto/in-band.c' || echo '$(srcdir)/'`ofproto/in-band.c ofproto/ofproto_libofproto_la-names.lo: ofproto/names.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-names.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-names.Tpo -c -o ofproto/ofproto_libofproto_la-names.lo `test -f 'ofproto/names.c' || echo '$(srcdir)/'`ofproto/names.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-names.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-names.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/names.c' object='ofproto/ofproto_libofproto_la-names.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-names.lo `test -f 'ofproto/names.c' || echo '$(srcdir)/'`ofproto/names.c ofproto/ofproto_libofproto_la-netflow.lo: ofproto/netflow.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-netflow.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-netflow.Tpo -c -o ofproto/ofproto_libofproto_la-netflow.lo `test -f 'ofproto/netflow.c' || echo '$(srcdir)/'`ofproto/netflow.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-netflow.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-netflow.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/netflow.c' object='ofproto/ofproto_libofproto_la-netflow.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-netflow.lo `test -f 'ofproto/netflow.c' || echo '$(srcdir)/'`ofproto/netflow.c ofproto/ofproto_libofproto_la-ofproto.lo: ofproto/ofproto.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto.lo `test -f 'ofproto/ofproto.c' || echo '$(srcdir)/'`ofproto/ofproto.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto.c' object='ofproto/ofproto_libofproto_la-ofproto.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto.lo `test -f 'ofproto/ofproto.c' || echo '$(srcdir)/'`ofproto/ofproto.c ofproto/ofproto_libofproto_la-ofproto-dpif.lo: ofproto/ofproto-dpif.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif.lo `test -f 'ofproto/ofproto-dpif.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif.lo `test -f 'ofproto/ofproto-dpif.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif.c ofproto/ofproto_libofproto_la-ofproto-dpif-ipfix.lo: ofproto/ofproto-dpif-ipfix.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif-ipfix.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-ipfix.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-ipfix.lo `test -f 'ofproto/ofproto-dpif-ipfix.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-ipfix.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-ipfix.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-ipfix.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif-ipfix.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif-ipfix.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-ipfix.lo `test -f 'ofproto/ofproto-dpif-ipfix.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-ipfix.c ofproto/ofproto_libofproto_la-ofproto-dpif-mirror.lo: ofproto/ofproto-dpif-mirror.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif-mirror.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-mirror.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-mirror.lo `test -f 'ofproto/ofproto-dpif-mirror.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-mirror.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-mirror.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-mirror.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif-mirror.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif-mirror.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-mirror.lo `test -f 'ofproto/ofproto-dpif-mirror.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-mirror.c ofproto/ofproto_libofproto_la-ofproto-dpif-monitor.lo: ofproto/ofproto-dpif-monitor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif-monitor.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-monitor.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-monitor.lo `test -f 'ofproto/ofproto-dpif-monitor.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-monitor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-monitor.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-monitor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif-monitor.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif-monitor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-monitor.lo `test -f 'ofproto/ofproto-dpif-monitor.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-monitor.c ofproto/ofproto_libofproto_la-ofproto-dpif-rid.lo: ofproto/ofproto-dpif-rid.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif-rid.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-rid.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-rid.lo `test -f 'ofproto/ofproto-dpif-rid.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-rid.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-rid.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-rid.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif-rid.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif-rid.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-rid.lo `test -f 'ofproto/ofproto-dpif-rid.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-rid.c ofproto/ofproto_libofproto_la-ofproto-dpif-sflow.lo: ofproto/ofproto-dpif-sflow.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif-sflow.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-sflow.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-sflow.lo `test -f 'ofproto/ofproto-dpif-sflow.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-sflow.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-sflow.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-sflow.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif-sflow.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif-sflow.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-sflow.lo `test -f 'ofproto/ofproto-dpif-sflow.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-sflow.c ofproto/ofproto_libofproto_la-ofproto-dpif-upcall.lo: ofproto/ofproto-dpif-upcall.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif-upcall.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-upcall.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-upcall.lo `test -f 'ofproto/ofproto-dpif-upcall.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-upcall.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-upcall.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-upcall.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif-upcall.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif-upcall.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-upcall.lo `test -f 'ofproto/ofproto-dpif-upcall.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-upcall.c ofproto/ofproto_libofproto_la-ofproto-dpif-xlate.lo: ofproto/ofproto-dpif-xlate.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-ofproto-dpif-xlate.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-xlate.Tpo -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-xlate.lo `test -f 'ofproto/ofproto-dpif-xlate.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-xlate.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-xlate.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-ofproto-dpif-xlate.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/ofproto-dpif-xlate.c' object='ofproto/ofproto_libofproto_la-ofproto-dpif-xlate.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-ofproto-dpif-xlate.lo `test -f 'ofproto/ofproto-dpif-xlate.c' || echo '$(srcdir)/'`ofproto/ofproto-dpif-xlate.c ofproto/ofproto_libofproto_la-pktbuf.lo: ofproto/pktbuf.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-pktbuf.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-pktbuf.Tpo -c -o ofproto/ofproto_libofproto_la-pktbuf.lo `test -f 'ofproto/pktbuf.c' || echo '$(srcdir)/'`ofproto/pktbuf.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-pktbuf.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-pktbuf.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/pktbuf.c' object='ofproto/ofproto_libofproto_la-pktbuf.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-pktbuf.lo `test -f 'ofproto/pktbuf.c' || echo '$(srcdir)/'`ofproto/pktbuf.c ofproto/ofproto_libofproto_la-pinsched.lo: ofproto/pinsched.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-pinsched.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-pinsched.Tpo -c -o ofproto/ofproto_libofproto_la-pinsched.lo `test -f 'ofproto/pinsched.c' || echo '$(srcdir)/'`ofproto/pinsched.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-pinsched.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-pinsched.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/pinsched.c' object='ofproto/ofproto_libofproto_la-pinsched.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-pinsched.lo `test -f 'ofproto/pinsched.c' || echo '$(srcdir)/'`ofproto/pinsched.c ofproto/ofproto_libofproto_la-tunnel.lo: ofproto/tunnel.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-tunnel.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-tunnel.Tpo -c -o ofproto/ofproto_libofproto_la-tunnel.lo `test -f 'ofproto/tunnel.c' || echo '$(srcdir)/'`ofproto/tunnel.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-tunnel.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-tunnel.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/tunnel.c' object='ofproto/ofproto_libofproto_la-tunnel.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-tunnel.lo `test -f 'ofproto/tunnel.c' || echo '$(srcdir)/'`ofproto/tunnel.c ofproto/ofproto_libofproto_la-bundles.lo: ofproto/bundles.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -MT ofproto/ofproto_libofproto_la-bundles.lo -MD -MP -MF ofproto/$(DEPDIR)/ofproto_libofproto_la-bundles.Tpo -c -o ofproto/ofproto_libofproto_la-bundles.lo `test -f 'ofproto/bundles.c' || echo '$(srcdir)/'`ofproto/bundles.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ofproto/$(DEPDIR)/ofproto_libofproto_la-bundles.Tpo ofproto/$(DEPDIR)/ofproto_libofproto_la-bundles.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ofproto/bundles.c' object='ofproto/ofproto_libofproto_la-bundles.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ofproto_libofproto_la_CPPFLAGS) $(CPPFLAGS) $(ofproto_libofproto_la_CFLAGS) $(CFLAGS) -c -o ofproto/ofproto_libofproto_la-bundles.lo `test -f 'ofproto/bundles.c' || echo '$(srcdir)/'`ofproto/bundles.c ovsdb/ovsdb_libovsdb_la-column.lo: ovsdb/column.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-column.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-column.Tpo -c -o ovsdb/ovsdb_libovsdb_la-column.lo `test -f 'ovsdb/column.c' || echo '$(srcdir)/'`ovsdb/column.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-column.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-column.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/column.c' object='ovsdb/ovsdb_libovsdb_la-column.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-column.lo `test -f 'ovsdb/column.c' || echo '$(srcdir)/'`ovsdb/column.c ovsdb/ovsdb_libovsdb_la-condition.lo: ovsdb/condition.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-condition.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-condition.Tpo -c -o ovsdb/ovsdb_libovsdb_la-condition.lo `test -f 'ovsdb/condition.c' || echo '$(srcdir)/'`ovsdb/condition.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-condition.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-condition.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/condition.c' object='ovsdb/ovsdb_libovsdb_la-condition.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-condition.lo `test -f 'ovsdb/condition.c' || echo '$(srcdir)/'`ovsdb/condition.c ovsdb/ovsdb_libovsdb_la-execution.lo: ovsdb/execution.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-execution.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-execution.Tpo -c -o ovsdb/ovsdb_libovsdb_la-execution.lo `test -f 'ovsdb/execution.c' || echo '$(srcdir)/'`ovsdb/execution.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-execution.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-execution.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/execution.c' object='ovsdb/ovsdb_libovsdb_la-execution.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-execution.lo `test -f 'ovsdb/execution.c' || echo '$(srcdir)/'`ovsdb/execution.c ovsdb/ovsdb_libovsdb_la-file.lo: ovsdb/file.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-file.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-file.Tpo -c -o ovsdb/ovsdb_libovsdb_la-file.lo `test -f 'ovsdb/file.c' || echo '$(srcdir)/'`ovsdb/file.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-file.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-file.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/file.c' object='ovsdb/ovsdb_libovsdb_la-file.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-file.lo `test -f 'ovsdb/file.c' || echo '$(srcdir)/'`ovsdb/file.c ovsdb/ovsdb_libovsdb_la-jsonrpc-server.lo: ovsdb/jsonrpc-server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-jsonrpc-server.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-jsonrpc-server.Tpo -c -o ovsdb/ovsdb_libovsdb_la-jsonrpc-server.lo `test -f 'ovsdb/jsonrpc-server.c' || echo '$(srcdir)/'`ovsdb/jsonrpc-server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-jsonrpc-server.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-jsonrpc-server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/jsonrpc-server.c' object='ovsdb/ovsdb_libovsdb_la-jsonrpc-server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-jsonrpc-server.lo `test -f 'ovsdb/jsonrpc-server.c' || echo '$(srcdir)/'`ovsdb/jsonrpc-server.c ovsdb/ovsdb_libovsdb_la-log.lo: ovsdb/log.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-log.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-log.Tpo -c -o ovsdb/ovsdb_libovsdb_la-log.lo `test -f 'ovsdb/log.c' || echo '$(srcdir)/'`ovsdb/log.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-log.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-log.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/log.c' object='ovsdb/ovsdb_libovsdb_la-log.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-log.lo `test -f 'ovsdb/log.c' || echo '$(srcdir)/'`ovsdb/log.c ovsdb/ovsdb_libovsdb_la-mutation.lo: ovsdb/mutation.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-mutation.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-mutation.Tpo -c -o ovsdb/ovsdb_libovsdb_la-mutation.lo `test -f 'ovsdb/mutation.c' || echo '$(srcdir)/'`ovsdb/mutation.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-mutation.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-mutation.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/mutation.c' object='ovsdb/ovsdb_libovsdb_la-mutation.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-mutation.lo `test -f 'ovsdb/mutation.c' || echo '$(srcdir)/'`ovsdb/mutation.c ovsdb/ovsdb_libovsdb_la-ovsdb.lo: ovsdb/ovsdb.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-ovsdb.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-ovsdb.Tpo -c -o ovsdb/ovsdb_libovsdb_la-ovsdb.lo `test -f 'ovsdb/ovsdb.c' || echo '$(srcdir)/'`ovsdb/ovsdb.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-ovsdb.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-ovsdb.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/ovsdb.c' object='ovsdb/ovsdb_libovsdb_la-ovsdb.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-ovsdb.lo `test -f 'ovsdb/ovsdb.c' || echo '$(srcdir)/'`ovsdb/ovsdb.c ovsdb/ovsdb_libovsdb_la-monitor.lo: ovsdb/monitor.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-monitor.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-monitor.Tpo -c -o ovsdb/ovsdb_libovsdb_la-monitor.lo `test -f 'ovsdb/monitor.c' || echo '$(srcdir)/'`ovsdb/monitor.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-monitor.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-monitor.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/monitor.c' object='ovsdb/ovsdb_libovsdb_la-monitor.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-monitor.lo `test -f 'ovsdb/monitor.c' || echo '$(srcdir)/'`ovsdb/monitor.c ovsdb/ovsdb_libovsdb_la-query.lo: ovsdb/query.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-query.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-query.Tpo -c -o ovsdb/ovsdb_libovsdb_la-query.lo `test -f 'ovsdb/query.c' || echo '$(srcdir)/'`ovsdb/query.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-query.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-query.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/query.c' object='ovsdb/ovsdb_libovsdb_la-query.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-query.lo `test -f 'ovsdb/query.c' || echo '$(srcdir)/'`ovsdb/query.c ovsdb/ovsdb_libovsdb_la-row.lo: ovsdb/row.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-row.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-row.Tpo -c -o ovsdb/ovsdb_libovsdb_la-row.lo `test -f 'ovsdb/row.c' || echo '$(srcdir)/'`ovsdb/row.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-row.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-row.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/row.c' object='ovsdb/ovsdb_libovsdb_la-row.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-row.lo `test -f 'ovsdb/row.c' || echo '$(srcdir)/'`ovsdb/row.c ovsdb/ovsdb_libovsdb_la-server.lo: ovsdb/server.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-server.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-server.Tpo -c -o ovsdb/ovsdb_libovsdb_la-server.lo `test -f 'ovsdb/server.c' || echo '$(srcdir)/'`ovsdb/server.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-server.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-server.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/server.c' object='ovsdb/ovsdb_libovsdb_la-server.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-server.lo `test -f 'ovsdb/server.c' || echo '$(srcdir)/'`ovsdb/server.c ovsdb/ovsdb_libovsdb_la-table.lo: ovsdb/table.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-table.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-table.Tpo -c -o ovsdb/ovsdb_libovsdb_la-table.lo `test -f 'ovsdb/table.c' || echo '$(srcdir)/'`ovsdb/table.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-table.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-table.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/table.c' object='ovsdb/ovsdb_libovsdb_la-table.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-table.lo `test -f 'ovsdb/table.c' || echo '$(srcdir)/'`ovsdb/table.c ovsdb/ovsdb_libovsdb_la-trigger.lo: ovsdb/trigger.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-trigger.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-trigger.Tpo -c -o ovsdb/ovsdb_libovsdb_la-trigger.lo `test -f 'ovsdb/trigger.c' || echo '$(srcdir)/'`ovsdb/trigger.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-trigger.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-trigger.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/trigger.c' object='ovsdb/ovsdb_libovsdb_la-trigger.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-trigger.lo `test -f 'ovsdb/trigger.c' || echo '$(srcdir)/'`ovsdb/trigger.c ovsdb/ovsdb_libovsdb_la-transaction.lo: ovsdb/transaction.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -MT ovsdb/ovsdb_libovsdb_la-transaction.lo -MD -MP -MF ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-transaction.Tpo -c -o ovsdb/ovsdb_libovsdb_la-transaction.lo `test -f 'ovsdb/transaction.c' || echo '$(srcdir)/'`ovsdb/transaction.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-transaction.Tpo ovsdb/$(DEPDIR)/ovsdb_libovsdb_la-transaction.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ovsdb/transaction.c' object='ovsdb/ovsdb_libovsdb_la-transaction.lo' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(ovsdb_libovsdb_la_CPPFLAGS) $(CPPFLAGS) $(ovsdb_libovsdb_la_CFLAGS) $(CFLAGS) -c -o ovsdb/ovsdb_libovsdb_la-transaction.lo `test -f 'ovsdb/transaction.c' || echo '$(srcdir)/'`ovsdb/transaction.c mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs -rm -rf lib/.libs lib/_libs -rm -rf lib/lldp/.libs lib/lldp/_libs -rm -rf ofproto/.libs ofproto/_libs -rm -rf ovn/controller/.libs ovn/controller/_libs -rm -rf ovn/controller-vtep/.libs ovn/controller-vtep/_libs -rm -rf ovn/lib/.libs ovn/lib/_libs -rm -rf ovn/northd/.libs ovn/northd/_libs -rm -rf ovn/utilities/.libs ovn/utilities/_libs -rm -rf ovsdb/.libs ovsdb/_libs -rm -rf tests/.libs tests/_libs -rm -rf utilities/.libs utilities/_libs -rm -rf vswitchd/.libs vswitchd/_libs -rm -rf vtep/.libs vtep/_libs distclean-libtool: -rm -f libtool config.lt install-man1: $(dist_man_MANS) $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS) $(man_MANS)'; \ test -n "$(man1dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man1dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man1dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.1[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ done; } uninstall-man1: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man1dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS) $(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.1[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man1dir)'; $(am__uninstall_files_from_dir) install-man5: $(dist_man_MANS) $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS) $(man_MANS)'; \ test -n "$(man5dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man5dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man5dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.5[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man5dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man5dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man5dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man5dir)" || exit $$?; }; \ done; } uninstall-man5: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man5dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS) $(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.5[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^5][0-9a-z]*$$,5,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man5dir)'; $(am__uninstall_files_from_dir) install-man7: $(dist_man_MANS) $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS) $(man_MANS)'; \ test -n "$(man7dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man7dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man7dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.7[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man7dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man7dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man7dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man7dir)" || exit $$?; }; \ done; } uninstall-man7: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man7dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS) $(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.7[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^7][0-9a-z]*$$,7,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man7dir)'; $(am__uninstall_files_from_dir) install-man8: $(dist_man_MANS) $(man_MANS) @$(NORMAL_INSTALL) @list1=''; \ list2='$(dist_man_MANS) $(man_MANS)'; \ test -n "$(man8dir)" \ && test -n "`echo $$list1$$list2`" \ || exit 0; \ echo " $(MKDIR_P) '$(DESTDIR)$(man8dir)'"; \ $(MKDIR_P) "$(DESTDIR)$(man8dir)" || exit 1; \ { for i in $$list1; do echo "$$i"; done; \ if test -n "$$list2"; then \ for i in $$list2; do echo "$$i"; done \ | sed -n '/\.8[a-z]*$$/p'; \ fi; \ } | while read p; do \ if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; echo "$$p"; \ done | \ sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ sed 'N;N;s,\n, ,g' | { \ list=; while read file base inst; do \ if test "$$base" = "$$inst"; then list="$$list $$file"; else \ echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man8dir)/$$inst'"; \ $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man8dir)/$$inst" || exit $$?; \ fi; \ done; \ for i in $$list; do echo "$$i"; done | $(am__base_list) | \ while read files; do \ test -z "$$files" || { \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man8dir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(man8dir)" || exit $$?; }; \ done; } uninstall-man8: @$(NORMAL_UNINSTALL) @list=''; test -n "$(man8dir)" || exit 0; \ files=`{ for i in $$list; do echo "$$i"; done; \ l2='$(dist_man_MANS) $(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ sed -n '/\.8[a-z]*$$/p'; \ } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^8][0-9a-z]*$$,8,;x' \ -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ dir='$(DESTDIR)$(man8dir)'; $(am__uninstall_files_from_dir) install-dist_pkgdataDATA: $(dist_pkgdata_DATA) @$(NORMAL_INSTALL) @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ done uninstall-dist_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(dist_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) install-dist_scriptsDATA: $(dist_scripts_DATA) @$(NORMAL_INSTALL) @list='$(dist_scripts_DATA)'; test -n "$(scriptsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(scriptsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(scriptsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(scriptsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(scriptsdir)" || exit $$?; \ done uninstall-dist_scriptsDATA: @$(NORMAL_UNINSTALL) @list='$(dist_scripts_DATA)'; test -n "$(scriptsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(scriptsdir)'; $(am__uninstall_files_from_dir) install-nobase_pkgdataDATA: $(nobase_pkgdata_DATA) @$(NORMAL_INSTALL) @list='$(nobase_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ fi; \ $(am__nobase_list) | while read dir files; do \ xfiles=; for file in $$files; do \ if test -f "$$file"; then xfiles="$$xfiles $$file"; \ else xfiles="$$xfiles $(srcdir)/$$file"; fi; done; \ test -z "$$xfiles" || { \ test "x$$dir" = x. || { \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)/$$dir'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)/$$dir"; }; \ echo " $(INSTALL_DATA) $$xfiles '$(DESTDIR)$(pkgdatadir)/$$dir'"; \ $(INSTALL_DATA) $$xfiles "$(DESTDIR)$(pkgdatadir)/$$dir" || exit $$?; }; \ done uninstall-nobase_pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(nobase_pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ $(am__nobase_strip_setup); files=`$(am__nobase_strip)`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) install-pkgconfigDATA: $(pkgconfig_DATA) @$(NORMAL_INSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgconfigdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgconfigdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgconfigdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgconfigdir)" || exit $$?; \ done uninstall-pkgconfigDATA: @$(NORMAL_UNINSTALL) @list='$(pkgconfig_DATA)'; test -n "$(pkgconfigdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgconfigdir)'; $(am__uninstall_files_from_dir) install-pkgdataDATA: $(pkgdata_DATA) @$(NORMAL_INSTALL) @list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \ $(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \ done uninstall-pkgdataDATA: @$(NORMAL_UNINSTALL) @list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir) install-scriptsDATA: $(scripts_DATA) @$(NORMAL_INSTALL) @list='$(scripts_DATA)'; test -n "$(scriptsdir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(scriptsdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(scriptsdir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(scriptsdir)'"; \ $(INSTALL_DATA) $$files "$(DESTDIR)$(scriptsdir)" || exit $$?; \ done uninstall-scriptsDATA: @$(NORMAL_UNINSTALL) @list='$(scripts_DATA)'; test -n "$(scriptsdir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(scriptsdir)'; $(am__uninstall_files_from_dir) install-openflowincludeHEADERS: $(openflowinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(openflowinclude_HEADERS)'; test -n "$(openflowincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(openflowincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(openflowincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(openflowincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(openflowincludedir)" || exit $$?; \ done uninstall-openflowincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(openflowinclude_HEADERS)'; test -n "$(openflowincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(openflowincludedir)'; $(am__uninstall_files_from_dir) install-openvswitchincludeHEADERS: $(openvswitchinclude_HEADERS) @$(NORMAL_INSTALL) @list='$(openvswitchinclude_HEADERS)'; test -n "$(openvswitchincludedir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(openvswitchincludedir)'"; \ $(MKDIR_P) "$(DESTDIR)$(openvswitchincludedir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(openvswitchincludedir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(openvswitchincludedir)" || exit $$?; \ done uninstall-openvswitchincludeHEADERS: @$(NORMAL_UNINSTALL) @list='$(openvswitchinclude_HEADERS)'; test -n "$(openvswitchincludedir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(openvswitchincludedir)'; $(am__uninstall_files_from_dir) # This directory's subdirectories are mostly independent; you can cd # into them and run 'make' without going through this Makefile. # To change the values of 'make' variables: instead of editing Makefiles, # (1) if the variable is set in 'config.status', edit 'config.status' # (which will cause the Makefiles to be regenerated when you run 'make'); # (2) otherwise, pass the desired values on the 'make' command line. $(am__recursive_targets): @fail=; \ if $(am__make_keepgoing); then \ failcom='fail=yes'; \ else \ failcom='exit 1'; \ fi; \ dot_seen=no; \ target=`echo $@ | sed s/-recursive//`; \ case "$@" in \ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ *) list='$(SUBDIRS)' ;; \ esac; \ for subdir in $$list; do \ echo "Making $$target in $$subdir"; \ if test "$$subdir" = "."; then \ dot_seen=yes; \ local_target="$$target-am"; \ else \ local_target="$$target"; \ fi; \ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ || eval $$failcom; \ done; \ if test "$$dot_seen" = "no"; then \ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ fi; test -z "$$fail" ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-recursive TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \ include_option=--etags-include; \ empty_fix=.; \ else \ include_option=--include; \ empty_fix=; \ fi; \ list='$(SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ test ! -f $$subdir/TAGS || \ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \ fi; \ done; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-recursive CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscope: cscope.files test ! -s cscope.files \ || $(CSCOPE) -b -q $(AM_CSCOPEFLAGS) $(CSCOPEFLAGS) -i cscope.files $(CSCOPE_ARGS) clean-cscope: -rm -f cscope.files cscope.files: clean-cscope cscopelist cscopelist: cscopelist-recursive cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags -rm -f cscope.out cscope.in.out cscope.po.out cscope.files distdir: $(DISTFILES) $(am__remove_distdir) test -d "$(distdir)" || mkdir "$(distdir)" @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \ if test "$$subdir" = .; then :; else \ $(am__make_dryrun) \ || test -d "$(distdir)/$$subdir" \ || $(MKDIR_P) "$(distdir)/$$subdir" \ || exit 1; \ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \ $(am__relativize); \ new_distdir=$$reldir; \ dir1=$$subdir; dir2="$(top_distdir)"; \ $(am__relativize); \ new_top_distdir=$$reldir; \ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \ ($(am__cd) $$subdir && \ $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$$new_top_distdir" \ distdir="$$new_distdir" \ am__remove_distdir=: \ am__skip_length_check=: \ am__skip_mode_fix=: \ distdir) \ || exit 1; \ fi; \ done $(MAKE) $(AM_MAKEFLAGS) \ top_distdir="$(top_distdir)" distdir="$(distdir)" \ dist-hook -test -n "$(am__skip_mode_fix)" \ || find "$(distdir)" -type d ! -perm -755 \ -exec chmod u+rwx,go+rx {} \; -o \ ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ ! -type d ! -perm -444 -exec $(install_sh) -c -m a+r {} {} \; \ || chmod -R a+r "$(distdir)" dist-gzip: distdir tardir=$(distdir) && $(am__tar) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz $(am__post_remove_distdir) dist-bzip2: distdir tardir=$(distdir) && $(am__tar) | BZIP2=$${BZIP2--9} bzip2 -c >$(distdir).tar.bz2 $(am__post_remove_distdir) dist-lzip: distdir tardir=$(distdir) && $(am__tar) | lzip -c $${LZIP_OPT--9} >$(distdir).tar.lz $(am__post_remove_distdir) dist-xz: distdir tardir=$(distdir) && $(am__tar) | XZ_OPT=$${XZ_OPT--e} xz -c >$(distdir).tar.xz $(am__post_remove_distdir) dist-tarZ: distdir @echo WARNING: "Support for shar distribution archives is" \ "deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 tardir=$(distdir) && $(am__tar) | compress -c >$(distdir).tar.Z $(am__post_remove_distdir) dist-shar: distdir @echo WARNING: "Support for distribution archives compressed with" \ "legacy program 'compress' is deprecated." >&2 @echo WARNING: "It will be removed altogether in Automake 2.0" >&2 shar $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).shar.gz $(am__post_remove_distdir) dist-zip: distdir -rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) $(am__post_remove_distdir) dist dist-all: $(MAKE) $(AM_MAKEFLAGS) $(DIST_TARGETS) am__post_remove_distdir='@:' $(am__post_remove_distdir) # This target untars the dist file and tries a VPATH configuration. Then # it guarantees that the distribution is self-contained by making another # tarfile. distcheck: dist case '$(DIST_ARCHIVES)' in \ *.tar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).tar.gz | $(am__untar) ;;\ *.tar.bz2*) \ bzip2 -dc $(distdir).tar.bz2 | $(am__untar) ;;\ *.tar.lz*) \ lzip -dc $(distdir).tar.lz | $(am__untar) ;;\ *.tar.xz*) \ xz -dc $(distdir).tar.xz | $(am__untar) ;;\ *.tar.Z*) \ uncompress -c $(distdir).tar.Z | $(am__untar) ;;\ *.shar.gz*) \ GZIP=$(GZIP_ENV) gzip -dc $(distdir).shar.gz | unshar ;;\ *.zip*) \ unzip $(distdir).zip ;;\ esac chmod -R a-w $(distdir) chmod u+w $(distdir) mkdir $(distdir)/_build $(distdir)/_inst chmod a-w $(distdir) test -d $(distdir)/_build || exit 0; \ dc_install_base=`$(am__cd) $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && am__cwd=`pwd` \ && $(am__cd) $(distdir)/_build \ && ../configure \ $(AM_DISTCHECK_CONFIGURE_FLAGS) \ $(DISTCHECK_CONFIGURE_FLAGS) \ --srcdir=.. --prefix="$$dc_install_base" \ && $(MAKE) $(AM_MAKEFLAGS) \ && $(MAKE) $(AM_MAKEFLAGS) dvi \ && $(MAKE) $(AM_MAKEFLAGS) check \ && $(MAKE) $(AM_MAKEFLAGS) install \ && $(MAKE) $(AM_MAKEFLAGS) installcheck \ && $(MAKE) $(AM_MAKEFLAGS) uninstall \ && $(MAKE) $(AM_MAKEFLAGS) distuninstallcheck_dir="$$dc_install_base" \ distuninstallcheck \ && chmod -R a-w "$$dc_install_base" \ && ({ \ (cd ../.. && umask 077 && mkdir "$$dc_destdir") \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" install \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" uninstall \ && $(MAKE) $(AM_MAKEFLAGS) DESTDIR="$$dc_destdir" \ distuninstallcheck_dir="$$dc_destdir" distuninstallcheck; \ } || { rm -rf "$$dc_destdir"; exit 1; }) \ && rm -rf "$$dc_destdir" \ && $(MAKE) $(AM_MAKEFLAGS) dist \ && rm -rf $(DIST_ARCHIVES) \ && $(MAKE) $(AM_MAKEFLAGS) distcleancheck \ && cd "$$am__cwd" \ || exit 1 $(am__post_remove_distdir) @(echo "$(distdir) archives ready for distribution: "; \ list='$(DIST_ARCHIVES)'; for i in $$list; do echo $$i; done) | \ sed -e 1h -e 1s/./=/g -e 1p -e 1x -e '$$p' -e '$$x' distuninstallcheck: @test -n '$(distuninstallcheck_dir)' || { \ echo 'ERROR: trying to run $@ with an empty' \ '$$(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ $(am__cd) '$(distuninstallcheck_dir)' || { \ echo 'ERROR: cannot chdir into $(distuninstallcheck_dir)' >&2; \ exit 1; \ }; \ test `$(am__distuninstallcheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 check-am: all-am $(MAKE) $(AM_MAKEFLAGS) $(check_SCRIPTS) $(dist_check_SCRIPTS) \ $(check_DATA) $(MAKE) $(AM_MAKEFLAGS) check-local check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(SCRIPTS) $(MANS) $(DATA) \ $(HEADERS) config.h all-local install-binPROGRAMS: install-libLTLIBRARIES installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(bindir)" "$(DESTDIR)$(completiondir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(scriptsdir)" "$(DESTDIR)$(sbindir)" "$(DESTDIR)$(scriptsdir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" "$(DESTDIR)$(man7dir)" "$(DESTDIR)$(man8dir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(scriptsdir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(pkgdatadir)" "$(DESTDIR)$(scriptsdir)" "$(DESTDIR)$(openflowincludedir)" "$(DESTDIR)$(openvswitchincludedir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-recursive install-exec: install-exec-recursive install-data: install-data-recursive uninstall: uninstall-recursive install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-recursive install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) -rm -f lib/$(DEPDIR)/$(am__dirstamp) -rm -f lib/$(am__dirstamp) -rm -f lib/lldp/$(DEPDIR)/$(am__dirstamp) -rm -f lib/lldp/$(am__dirstamp) -rm -f ofproto/$(DEPDIR)/$(am__dirstamp) -rm -f ofproto/$(am__dirstamp) -rm -f ovn/controller-vtep/$(DEPDIR)/$(am__dirstamp) -rm -f ovn/controller-vtep/$(am__dirstamp) -rm -f ovn/controller/$(DEPDIR)/$(am__dirstamp) -rm -f ovn/controller/$(am__dirstamp) -rm -f ovn/lib/$(DEPDIR)/$(am__dirstamp) -rm -f ovn/lib/$(am__dirstamp) -rm -f ovn/northd/$(DEPDIR)/$(am__dirstamp) -rm -f ovn/northd/$(am__dirstamp) -rm -f ovn/utilities/$(DEPDIR)/$(am__dirstamp) -rm -f ovn/utilities/$(am__dirstamp) -rm -f ovsdb/$(DEPDIR)/$(am__dirstamp) -rm -f ovsdb/$(am__dirstamp) -rm -f tests/$(DEPDIR)/$(am__dirstamp) -rm -f tests/$(am__dirstamp) -rm -f tests/dpdk/$(DEPDIR)/$(am__dirstamp) -rm -f tests/dpdk/$(am__dirstamp) -rm -f utilities/$(DEPDIR)/$(am__dirstamp) -rm -f utilities/$(am__dirstamp) -rm -f vswitchd/$(DEPDIR)/$(am__dirstamp) -rm -f vswitchd/$(am__dirstamp) -rm -f vtep/$(DEPDIR)/$(am__dirstamp) -rm -f vtep/$(am__dirstamp) -test -z "$(DISTCLEANFILES)" || rm -f $(DISTCLEANFILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) clean: clean-recursive clean-am: clean-binPROGRAMS clean-generic clean-libLTLIBRARIES \ clean-libtool clean-local clean-noinstPROGRAMS \ clean-sbinPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf lib/$(DEPDIR) lib/lldp/$(DEPDIR) ofproto/$(DEPDIR) ovn/controller-vtep/$(DEPDIR) ovn/controller/$(DEPDIR) ovn/lib/$(DEPDIR) ovn/northd/$(DEPDIR) ovn/utilities/$(DEPDIR) ovsdb/$(DEPDIR) tests/$(DEPDIR) tests/dpdk/$(DEPDIR) utilities/$(DEPDIR) vswitchd/$(DEPDIR) vtep/$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-hdr distclean-libtool distclean-tags dvi: dvi-recursive dvi-am: html: html-recursive html-am: info: info-recursive info-am: install-data-am: install-completionSCRIPTS install-data-local \ install-dist_pkgdataDATA install-dist_pkgdataSCRIPTS \ install-dist_scriptsDATA install-dist_scriptsSCRIPTS \ install-man install-nobase_pkgdataDATA \ install-openflowincludeHEADERS \ install-openvswitchincludeHEADERS install-pkgconfigDATA \ install-pkgdataDATA install-scriptsDATA install-scriptsSCRIPTS install-dvi: install-dvi-recursive install-dvi-am: install-exec-am: install-binPROGRAMS install-binSCRIPTS \ install-dist_sbinSCRIPTS install-libLTLIBRARIES \ install-sbinPROGRAMS install-sbinSCRIPTS install-html: install-html-recursive install-html-am: install-info: install-info-recursive install-info-am: install-man: install-man1 install-man5 install-man7 install-man8 install-pdf: install-pdf-recursive install-pdf-am: install-ps: install-ps-recursive install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-recursive -rm -f $(am__CONFIG_DISTCLEAN_FILES) -rm -rf $(top_srcdir)/autom4te.cache -rm -rf lib/$(DEPDIR) lib/lldp/$(DEPDIR) ofproto/$(DEPDIR) ovn/controller-vtep/$(DEPDIR) ovn/controller/$(DEPDIR) ovn/lib/$(DEPDIR) ovn/northd/$(DEPDIR) ovn/utilities/$(DEPDIR) ovsdb/$(DEPDIR) tests/$(DEPDIR) tests/dpdk/$(DEPDIR) utilities/$(DEPDIR) vswitchd/$(DEPDIR) vtep/$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic mostlyclean: mostlyclean-recursive mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-recursive pdf-am: ps: ps-recursive ps-am: uninstall-am: uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-completionSCRIPTS uninstall-dist_pkgdataDATA \ uninstall-dist_pkgdataSCRIPTS uninstall-dist_sbinSCRIPTS \ uninstall-dist_scriptsDATA uninstall-dist_scriptsSCRIPTS \ uninstall-libLTLIBRARIES uninstall-local uninstall-man \ uninstall-nobase_pkgdataDATA uninstall-openflowincludeHEADERS \ uninstall-openvswitchincludeHEADERS uninstall-pkgconfigDATA \ uninstall-pkgdataDATA uninstall-sbinPROGRAMS \ uninstall-sbinSCRIPTS uninstall-scriptsDATA \ uninstall-scriptsSCRIPTS uninstall-man: uninstall-man1 uninstall-man5 uninstall-man7 \ uninstall-man8 .MAKE: $(am__recursive_targets) all check check-am install install-am \ install-strip .PHONY: $(am__recursive_targets) CTAGS GTAGS TAGS all all-am all-local \ am--refresh check check-am check-local clean clean-binPROGRAMS \ clean-cscope clean-generic clean-libLTLIBRARIES clean-libtool \ clean-local clean-noinstPROGRAMS clean-sbinPROGRAMS cscope \ cscopelist-am ctags ctags-am dist dist-all dist-bzip2 \ dist-gzip dist-hook dist-lzip dist-shar dist-tarZ dist-xz \ dist-zip distcheck distclean distclean-compile \ distclean-generic distclean-hdr distclean-libtool \ distclean-tags distcleancheck distdir distuninstallcheck dvi \ dvi-am html html-am info info-am install install-am \ install-binPROGRAMS install-binSCRIPTS \ install-completionSCRIPTS install-data install-data-am \ install-data-local install-dist_pkgdataDATA \ install-dist_pkgdataSCRIPTS install-dist_sbinSCRIPTS \ install-dist_scriptsDATA install-dist_scriptsSCRIPTS \ install-dvi install-dvi-am install-exec install-exec-am \ install-html install-html-am install-info install-info-am \ install-libLTLIBRARIES install-man install-man1 install-man5 \ install-man7 install-man8 install-nobase_pkgdataDATA \ install-openflowincludeHEADERS \ install-openvswitchincludeHEADERS install-pdf install-pdf-am \ install-pkgconfigDATA install-pkgdataDATA install-ps \ install-ps-am install-sbinPROGRAMS install-sbinSCRIPTS \ install-scriptsDATA install-scriptsSCRIPTS install-strip \ installcheck installcheck-am installdirs installdirs-am \ maintainer-clean maintainer-clean-generic mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-binPROGRAMS uninstall-binSCRIPTS \ uninstall-completionSCRIPTS uninstall-dist_pkgdataDATA \ uninstall-dist_pkgdataSCRIPTS uninstall-dist_sbinSCRIPTS \ uninstall-dist_scriptsDATA uninstall-dist_scriptsSCRIPTS \ uninstall-libLTLIBRARIES uninstall-local uninstall-man \ uninstall-man1 uninstall-man5 uninstall-man7 uninstall-man8 \ uninstall-nobase_pkgdataDATA uninstall-openflowincludeHEADERS \ uninstall-openvswitchincludeHEADERS uninstall-pkgconfigDATA \ uninstall-pkgdataDATA uninstall-sbinPROGRAMS \ uninstall-sbinSCRIPTS uninstall-scriptsDATA \ uninstall-scriptsSCRIPTS .in: $(AM_V_GEN)$(PERL) $(srcdir)/build-aux/soexpand.pl -I$(srcdir) < $< | \ sed \ -e 's,[@]PKIDIR[@],$(PKIDIR),g' \ -e 's,[@]LOGDIR[@],$(LOGDIR),g' \ -e 's,[@]DBDIR[@],$(DBDIR),g' \ -e 's,[@]PERL[@],$(PERL),g' \ -e 's,[@]PYTHON[@],$(PYTHON),g' \ -e 's,[@]RUNDIR[@],$(RUNDIR),g' \ -e 's,[@]VERSION[@],$(VERSION),g' \ -e 's,[@]localstatedir[@],$(localstatedir),g' \ -e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \ -e 's,[@]sysconfdir[@],$(sysconfdir),g' \ -e 's,[@]bindir[@],$(bindir),g' \ -e 's,[@]sbindir[@],$(sbindir),g' \ -e 's,[@]abs_builddir[@],$(abs_builddir),g' \ -e 's,[@]abs_top_srcdir[@],$(abs_top_srcdir),g' \ > $@.tmp @if head -n 1 $@.tmp | grep '#!' > /dev/null; then \ chmod +x $@.tmp; \ fi $(AM_V_at) mv $@.tmp $@ %: %.xml $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/xml2nroff $< > $@.tmp \ --version=$(VERSION) \ PKIDIR='$(PKIDIR)' \ LOGDIR='$(LOGDIR)' \ DBDIR='$(DBDIR)' \ PERL='$(PERL)' \ PYTHON='$(PYTHON)' \ RUNDIR='$(RUNDIR)' \ VERSION='$(VERSION)' \ localstatedir='$(localstatedir)' \ pkgdatadir='$(pkgdatadir)' \ sysconfdir='$(sysconfdir)' \ bindir='$(bindir)' \ sbindir='$(sbindir)' $(AM_v_at)mv $@.tmp $@ .PHONY: clean-pycov clean-pycov: cd $(srcdir) && rm -f $(PYCOV_CLEAN_FILES) @GNU_MAKE_TRUE@dist-hook-git: distfiles @GNU_MAKE_TRUE@ @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1; then \ @GNU_MAKE_TRUE@ (cd datapath && $(MAKE) distfiles); \ @GNU_MAKE_TRUE@ (cat distfiles; sed 's|^|datapath/|' datapath/distfiles) | \ @GNU_MAKE_TRUE@ LC_ALL=C sort -u > all-distfiles; \ @GNU_MAKE_TRUE@ (cd $(srcdir) && git ls-files) | grep -v '\.gitignore$$' | \ @GNU_MAKE_TRUE@ LC_ALL=C sort -u > all-gitfiles; \ @GNU_MAKE_TRUE@ LC_ALL=C comm -1 -3 all-distfiles all-gitfiles > missing-distfiles; \ @GNU_MAKE_TRUE@ if test -s missing-distfiles; then \ @GNU_MAKE_TRUE@ echo "The following files are in git but not the distribution:"; \ @GNU_MAKE_TRUE@ cat missing-distfiles; \ @GNU_MAKE_TRUE@ exit 1; \ @GNU_MAKE_TRUE@ fi; \ @GNU_MAKE_TRUE@ fi # The following is based on commands for the Automake "distdir" target. @GNU_MAKE_TRUE@distfiles: Makefile @GNU_MAKE_TRUE@ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @GNU_MAKE_TRUE@ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ @GNU_MAKE_TRUE@ list='$(DISTFILES)'; \ @GNU_MAKE_TRUE@ for file in $$list; do echo $$file; done | \ @GNU_MAKE_TRUE@ sed -e "s|^$$srcdirstrip/||;t" \ @GNU_MAKE_TRUE@ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t" | \ @GNU_MAKE_TRUE@ LC_ALL=C sort -u > $@ .PHONY: dist-hook-git config-h-check: @cd $(srcdir); \ if test -e .git && (git --version) >/dev/null 2>&1 && \ git --no-pager grep -L '#include ' `git ls-files | grep '\.c$$' | \ grep -vE '^datapath|^lib/sflow|^third-party|^datapath-windows'`; \ then \ echo "See above for list of violations of the rule that"; \ echo "every C source file must #include ."; \ exit 1; \ fi .PHONY: config-h-check printf-check: @cd $(srcdir); \ if test -e .git && (git --version) >/dev/null 2>&1 && \ git --no-pager grep -n -E -e '%[-+ #0-9.*]*([ztj]|hh)' --and --not -e 'ovs_scan' `git ls-files | grep '\.[ch]$$' | \ grep -vE '^datapath|^lib/sflow|^third-party'`; \ then \ echo "See above for list of violations of the rule that"; \ echo "'z', 't', 'j', 'hh' printf() type modifiers are"; \ echo "forbidden. See CodingStyle.md for replacements."; \ exit 1; \ fi .PHONY: printf-check static-check: @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1 && \ git --no-pager grep -n -E '^[ ]+(struct vlog_rate_limit|pthread_once_t|struct ovsthread_once).*=' $(srcdir); \ then \ echo "See above for list of violations of the rule that "; \ echo "certain data structures must always be 'static'"; \ exit 1; \ fi .PHONY: static-check check-assert-h-usage: @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1 && \ (cd $(srcdir) && git --no-pager grep -l -E '[<]assert.h[>]') | \ $(EGREP) -v '^lib/(sflow_receiver|vlog).c$$|^tests/'; \ then \ echo "Files listed above unexpectedly #include <""assert.h"">."; \ echo "Please use ovs_assert (from util.h) instead of assert."; \ exit 1; \ fi .PHONY: check-assert-h-usage check-endian: @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1 && \ (cd $(srcdir) && git --no-pager grep -l -E \ -e 'BIG_ENDIAN|LITTLE_ENDIAN' --and --not -e 'BYTE_ORDER' | \ $(EGREP) -v '^datapath/'); \ then \ echo "See above for list of files that misuse LITTLE""_ENDIAN"; \ echo "or BIG""_ENDIAN. Please use WORDS_BIGENDIAN instead."; \ exit 1; \ fi .PHONY: check-endian thread-safety-check: @cd $(srcdir); \ if test -e .git && (git --version) >/dev/null 2>&1 && \ grep -n -f build-aux/thread-safety-blacklist \ `git ls-files | grep '\.[ch]$$' \ | $(EGREP) -v '^datapath|^lib/sflow|^third-party'` /dev/null \ | $(EGREP) -v ':[ ]*/?\*'; \ then \ echo "See above for list of calls to functions that are"; \ echo "blacklisted due to thread safety issues"; \ exit 1; \ fi .PHONY: thread-safety-check @HAVE_GROFF_TRUE@manpage-check: $(man_MANS) $(dist_man_MANS) $(noinst_man_MANS) @HAVE_GROFF_TRUE@ @error=false; \ @HAVE_GROFF_TRUE@ for manpage in $?; do \ @HAVE_GROFF_TRUE@ LANG=en_US.UTF-8 groff -w mac -w delim -w escape -w input -w missing -w tab -T utf8 -man -p -z $$manpage >$@.tmp 2>&1; \ @HAVE_GROFF_TRUE@ if grep warning: $@.tmp; then error=:; fi; \ @HAVE_GROFF_TRUE@ rm -f $@.tmp; \ @HAVE_GROFF_TRUE@ done; \ @HAVE_GROFF_TRUE@ if $$error; then exit 1; else touch $@; fi @HAVE_GROFF_TRUE@ $(AM_V_GEN) touch -c $@ ovn/utilities/ovn-sbctl.8: \ ovn/utilities/ovn-sbctl.8.in \ lib/db-ctl-base.man \ lib/table.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man ovn/utilities/ovn-sbctl.8.in: lib/db-ctl-base.man: lib/table.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/ovsdb-client.1: \ ovsdb/ovsdb-client.1.in \ lib/common-syn.man \ lib/common.man \ lib/daemon-syn.man \ lib/daemon.man \ lib/ssl-bootstrap-syn.man \ lib/ssl-bootstrap.man \ lib/ssl-syn.man \ lib/ssl.man \ lib/table.man \ lib/vlog-syn.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man ovsdb/ovsdb-client.1.in: lib/common-syn.man: lib/common.man: lib/daemon-syn.man: lib/daemon.man: lib/ssl-bootstrap-syn.man: lib/ssl-bootstrap.man: lib/ssl-syn.man: lib/ssl.man: lib/table.man: lib/vlog-syn.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/ovsdb-server.1: \ ovsdb/ovsdb-server.1.in \ lib/common-syn.man \ lib/common.man \ lib/coverage-unixctl.man \ lib/daemon-syn.man \ lib/daemon.man \ lib/memory-unixctl.man \ lib/service-syn.man \ lib/service.man \ lib/ssl-bootstrap-syn.man \ lib/ssl-bootstrap.man \ lib/ssl-peer-ca-cert-syn.man \ lib/ssl-peer-ca-cert.man \ lib/ssl-syn.man \ lib/ssl.man \ lib/unixctl-syn.man \ lib/unixctl.man \ lib/vlog-syn.man \ lib/vlog-unixctl.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man ovsdb/ovsdb-server.1.in: lib/common-syn.man: lib/common.man: lib/coverage-unixctl.man: lib/daemon-syn.man: lib/daemon.man: lib/memory-unixctl.man: lib/service-syn.man: lib/service.man: lib/ssl-bootstrap-syn.man: lib/ssl-bootstrap.man: lib/ssl-peer-ca-cert-syn.man: lib/ssl-peer-ca-cert.man: lib/ssl-syn.man: lib/ssl.man: lib/unixctl-syn.man: lib/unixctl.man: lib/vlog-syn.man: lib/vlog-unixctl.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/ovsdb-tool.1: \ ovsdb/ovsdb-tool.1.in \ lib/common-syn.man \ lib/common.man \ lib/vlog-syn.man \ lib/vlog.man ovsdb/ovsdb-tool.1.in: lib/common-syn.man: lib/common.man: lib/vlog-syn.man: lib/vlog.man: utilities/bugtool/ovs-bugtool.8: \ utilities/bugtool/ovs-bugtool.8.in utilities/bugtool/ovs-bugtool.8.in: utilities/ovs-appctl.8: \ utilities/ovs-appctl.8.in \ lib/common.man utilities/ovs-appctl.8.in: lib/common.man: utilities/ovs-benchmark.1: \ utilities/ovs-benchmark.1.in \ lib/ovs.tmac utilities/ovs-benchmark.1.in: lib/ovs.tmac: utilities/ovs-dpctl-top.8: \ utilities/ovs-dpctl-top.8.in utilities/ovs-dpctl-top.8.in: utilities/ovs-dpctl.8: \ utilities/ovs-dpctl.8.in \ lib/common.man \ lib/dpctl.man \ lib/vlog.man utilities/ovs-dpctl.8.in: lib/common.man: lib/dpctl.man: lib/vlog.man: utilities/ovs-l3ping.8: \ utilities/ovs-l3ping.8.in \ lib/common-syn.man \ lib/common.man utilities/ovs-l3ping.8.in: lib/common-syn.man: lib/common.man: utilities/ovs-ofctl.8: \ utilities/ovs-ofctl.8.in \ lib/common.man \ lib/daemon.man \ lib/ofp-version.man \ lib/ssl.man \ lib/unixctl.man \ lib/vconn-active.man \ lib/vlog.man utilities/ovs-ofctl.8.in: lib/common.man: lib/daemon.man: lib/ofp-version.man: lib/ssl.man: lib/unixctl.man: lib/vconn-active.man: lib/vlog.man: utilities/ovs-pcap.1: \ utilities/ovs-pcap.1.in \ lib/common-syn.man \ lib/common.man utilities/ovs-pcap.1.in: lib/common-syn.man: lib/common.man: utilities/ovs-pki.8: \ utilities/ovs-pki.8.in utilities/ovs-pki.8.in: utilities/ovs-tcpundump.1: \ utilities/ovs-tcpundump.1.in \ lib/common-syn.man \ lib/common.man utilities/ovs-tcpundump.1.in: lib/common-syn.man: lib/common.man: utilities/ovs-test.8: \ utilities/ovs-test.8.in \ lib/common-syn.man \ lib/common.man \ utilities/ovs-vlan-bugs.man utilities/ovs-test.8.in: lib/common-syn.man: lib/common.man: utilities/ovs-vlan-bugs.man: utilities/ovs-testcontroller.8: \ utilities/ovs-testcontroller.8.in \ lib/common.man \ lib/daemon.man \ lib/ofp-version.man \ lib/ssl-peer-ca-cert.man \ lib/ssl.man \ lib/unixctl.man \ lib/vconn-active.man \ lib/vconn-passive.man \ lib/vlog.man utilities/ovs-testcontroller.8.in: lib/common.man: lib/daemon.man: lib/ofp-version.man: lib/ssl-peer-ca-cert.man: lib/ssl.man: lib/unixctl.man: lib/vconn-active.man: lib/vconn-passive.man: lib/vlog.man: utilities/ovs-vlan-bug-workaround.8: \ utilities/ovs-vlan-bug-workaround.8.in \ lib/common.man \ utilities/ovs-vlan-bugs.man utilities/ovs-vlan-bug-workaround.8.in: lib/common.man: utilities/ovs-vlan-bugs.man: utilities/ovs-vlan-test.8: \ utilities/ovs-vlan-test.8.in \ lib/common-syn.man \ lib/common.man \ utilities/ovs-vlan-bugs.man utilities/ovs-vlan-test.8.in: lib/common-syn.man: lib/common.man: utilities/ovs-vlan-bugs.man: utilities/ovs-vsctl.8: \ utilities/ovs-vsctl.8.in \ lib/common.man \ lib/db-ctl-base.man \ lib/ssl-bootstrap.man \ lib/ssl-peer-ca-cert.man \ lib/ssl.man \ lib/table.man \ lib/vconn-active.man \ lib/vconn-passive.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man \ ovsdb/remote-passive.man utilities/ovs-vsctl.8.in: lib/common.man: lib/db-ctl-base.man: lib/ssl-bootstrap.man: lib/ssl-peer-ca-cert.man: lib/ssl.man: lib/table.man: lib/vconn-active.man: lib/vconn-passive.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/remote-passive.man: vswitchd/ovs-vswitchd.8: \ vswitchd/ovs-vswitchd.8.in \ lib/common.man \ lib/coverage-unixctl.man \ lib/daemon.man \ lib/dpctl.man \ lib/memory-unixctl.man \ lib/service.man \ lib/ssl-bootstrap.man \ lib/ssl.man \ lib/unixctl.man \ lib/vlog-unixctl.man \ lib/vlog.man \ ofproto/ofproto-dpif-unixctl.man \ ofproto/ofproto-tnl-unixctl.man \ ofproto/ofproto-unixctl.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man vswitchd/ovs-vswitchd.8.in: lib/common.man: lib/coverage-unixctl.man: lib/daemon.man: lib/dpctl.man: lib/memory-unixctl.man: lib/service.man: lib/ssl-bootstrap.man: lib/ssl.man: lib/unixctl.man: lib/vlog-unixctl.man: lib/vlog.man: ofproto/ofproto-dpif-unixctl.man: ofproto/ofproto-tnl-unixctl.man: ofproto/ofproto-unixctl.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: vtep/vtep-ctl.8: \ vtep/vtep-ctl.8.in \ lib/common.man \ lib/db-ctl-base.man \ lib/ssl-bootstrap.man \ lib/ssl-peer-ca-cert.man \ lib/ssl.man \ lib/table.man \ lib/vlog.man \ ovsdb/remote-active.man \ ovsdb/remote-active.man \ ovsdb/remote-passive.man \ ovsdb/remote-passive.man vtep/vtep-ctl.8.in: lib/common.man: lib/db-ctl-base.man: lib/ssl-bootstrap.man: lib/ssl-peer-ca-cert.man: lib/ssl.man: lib/table.man: lib/vlog.man: ovsdb/remote-active.man: ovsdb/remote-active.man: ovsdb/remote-passive.man: ovsdb/remote-passive.man: $(srcdir)/manpages.mk: $(MAN_ROOTS) build-aux/sodepends.pl @$(PERL) $(srcdir)/build-aux/sodepends.pl -I. -I$(srcdir) $(MAN_ROOTS) >$(@F).tmp @if cmp -s $(@F).tmp $@; then \ touch $@; \ rm -f $(@F).tmp; \ else \ mv $(@F).tmp $@; \ fi @VSTUDIO_DDK_TRUE@ovsext_make: datapath-windows/ovsext.sln @VSTUDIO_DDK_TRUE@ MSBuild.exe datapath-windows/ovsext.sln /target:Build /property:Configuration="Win8$(VSTUDIO_CONFIG)" @VSTUDIO_DDK_TRUE@ MSBuild.exe datapath-windows/ovsext.sln /target:Build /property:Configuration="Win8.1$(VSTUDIO_CONFIG)" @VSTUDIO_DDK_TRUE@ovsext_clean: datapath-windows/ovsext.sln @VSTUDIO_DDK_TRUE@ MSBuild.exe datapath-windows/ovsext.sln /target:Clean /property:Configuration="Win8$(VSTUDIO_CONFIG)" @VSTUDIO_DDK_TRUE@ MSBuild.exe datapath-windows/ovsext.sln /target:Clean /property:Configuration="Win8.1$(VSTUDIO_CONFIG)" .PHONY: ovsext_make dist-hook: $(DIST_HOOKS) all-local: $(ALL_LOCAL) clean-local: $(CLEAN_LOCAL) install-data-local: $(INSTALL_DATA_LOCAL) uninstall-local: $(UNINSTALL_LOCAL) .PHONY: $(DIST_HOOKS) $(CLEAN_LOCAL) $(INSTALL_DATA_LOCAL) $(UNINSTALL_LOCAL) modules_install: @LINUX_ENABLED_TRUE@ cd datapath/linux && $(MAKE) modules_install dist-docs: VERSION=$(VERSION) $(srcdir)/build-aux/dist-docs $(srcdir) $(docs) .PHONY: dist-docs @HAVE_OPENSSL_TRUE@lib/dhparams.c: lib/dh1024.pem lib/dh2048.pem lib/dh4096.pem @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)(echo '#include "lib/dhparams.h"' && \ @HAVE_OPENSSL_TRUE@ openssl dhparam -C -in $(srcdir)/lib/dh1024.pem -noout && \ @HAVE_OPENSSL_TRUE@ openssl dhparam -C -in $(srcdir)/lib/dh2048.pem -noout && \ @HAVE_OPENSSL_TRUE@ openssl dhparam -C -in $(srcdir)/lib/dh4096.pem -noout) \ @HAVE_OPENSSL_TRUE@ | sed 's/\(get_dh[0-9]*\)()/\1(void)/' > lib/dhparams.c.tmp && \ @HAVE_OPENSSL_TRUE@ mv lib/dhparams.c.tmp lib/dhparams.c lib/vswitch-idl.ovsidl: vswitchd/vswitch.ovsschema lib/vswitch-idl.ann $(AM_V_GEN)$(OVSDB_IDLC) annotate $(srcdir)/vswitchd/vswitch.ovsschema $(srcdir)/lib/vswitch-idl.ann > $@.tmp && mv $@.tmp $@ lib/dirs.c: lib/dirs.c.in Makefile $(AM_V_GEN)($(ro_c) && sed < $(srcdir)/lib/dirs.c.in \ -e 's,[@]srcdir[@],$(srcdir),g' \ -e 's,[@]LOGDIR[@],"$(LOGDIR)",g' \ -e 's,[@]RUNDIR[@],"$(RUNDIR)",g' \ -e 's,[@]DBDIR[@],"$(DBDIR)",g' \ -e 's,[@]bindir[@],"$(bindir)",g' \ -e 's,[@]sysconfdir[@],"$(sysconfdir)",g' \ -e 's,[@]pkgdatadir[@],"$(pkgdatadir)",g') \ > lib/dirs.c.tmp && \ mv lib/dirs.c.tmp lib/dirs.c lib/meta-flow.inc: $(srcdir)/build-aux/extract-ofp-fields lib/meta-flow.h $(AM_V_GEN)$(run_python) $^ --meta-flow > $@.tmp && mv $@.tmp $@ lib/meta-flow.lo: lib/meta-flow.inc lib/nx-match.inc: $(srcdir)/build-aux/extract-ofp-fields lib/meta-flow.h $(AM_V_GEN)$(run_python) $^ --nx-match > $@.tmp && mv $@.tmp $@ lib/nx-match.lo: lib/nx-match.inc lib/ofp-actions.inc1: $(srcdir)/build-aux/extract-ofp-actions lib/ofp-actions.c $(AM_V_GEN)$(run_python) $^ --prototypes > $@.tmp && mv $@.tmp $@ lib/ofp-actions.inc2: $(srcdir)/build-aux/extract-ofp-actions lib/ofp-actions.c $(AM_V_GEN)$(run_python) $^ --definitions > $@.tmp && mv $@.tmp $@ lib/ofp-actions.lo: lib/ofp-actions.inc1 lib/ofp-actions.inc2 lib/ofp-errors.inc: lib/ofp-errors.h include/openflow/openflow-common.h \ $(srcdir)/build-aux/extract-ofp-errors $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/extract-ofp-errors \ $(srcdir)/lib/ofp-errors.h \ $(srcdir)/include/openflow/openflow-common.h > $@.tmp && \ mv $@.tmp $@ lib/ofp-errors.lo: lib/ofp-errors.inc lib/ofp-msgs.inc: lib/ofp-msgs.h $(srcdir)/build-aux/extract-ofp-msgs $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/extract-ofp-msgs \ $(srcdir)/lib/ofp-msgs.h $@ > $@.tmp && mv $@.tmp $@ lib/ofp-msgs.lo: lib/ofp-msgs.inc lib-install-data-local: $(MKDIR_P) $(DESTDIR)$(RUNDIR) $(MKDIR_P) $(DESTDIR)$(PKIDIR) $(MKDIR_P) $(DESTDIR)$(LOGDIR) $(MKDIR_P) $(DESTDIR)$(DBDIR) ofproto/ipfix-entities.def: ofproto/ipfix.xml ofproto/ipfix-gen-entities $(AM_V_GEN)$(run_python) $(srcdir)/ofproto/ipfix-gen-entities $< > $@.tmp && \ mv $@.tmp $@ utilities/ovs-lib: $(top_builddir)/config.status @HAVE_PYTHON_TRUE@bugtool-install-data-local: @HAVE_PYTHON_TRUE@ for plugin in $(bugtool_plugins); do \ @HAVE_PYTHON_TRUE@ stem=`echo "$$plugin" | sed 's,utilities/bugtool/plugins/,,'`; \ @HAVE_PYTHON_TRUE@ dir=`expr "$$stem" : '\(.*\)/[^/]*$$'`; \ @HAVE_PYTHON_TRUE@ $(MKDIR_P) "$(DESTDIR)$(bugtoolpluginsdir)/$$dir"; \ @HAVE_PYTHON_TRUE@ $(INSTALL_DATA) "$(srcdir)/$$plugin" "$(DESTDIR)$(bugtoolpluginsdir)/$$stem"; \ @HAVE_PYTHON_TRUE@ done @HAVE_PYTHON_TRUE@bugtool-uninstall-local: @HAVE_PYTHON_TRUE@ for plugin in $(bugtool_plugins); do \ @HAVE_PYTHON_TRUE@ stem=`echo "$$plugin" | sed 's,utilities/bugtool/plugins/,,'`; \ @HAVE_PYTHON_TRUE@ rm -f "$(DESTDIR)$(bugtoolpluginsdir)/$$stem"; \ @HAVE_PYTHON_TRUE@ done @HAVE_PYTHON_TRUE@ for plugin in $(bugtool_plugins); do \ @HAVE_PYTHON_TRUE@ stem=`echo "$$plugin" | sed 's,utilities/bugtool/plugins/,,'`; \ @HAVE_PYTHON_TRUE@ dir=`expr "$$stem" : '\(.*\)/[^/]*$$'`; \ @HAVE_PYTHON_TRUE@ rmdir "$(DESTDIR)$(bugtoolpluginsdir)/$$dir"; \ @HAVE_PYTHON_TRUE@ done; exit 0 check-local: tests/atconfig tests/atlocal $(TESTSUITE) $(SHELL) '$(TESTSUITE)' -C tests AUTOTEST_PATH=$(AUTOTEST_PATH) $(TESTSUITEFLAGS) check-pycov: all tests/atconfig tests/atlocal $(TESTSUITE) clean-pycov PYTHONDONTWRITEBYTECODE=yes COVERAGE_FILE=$(COVERAGE_FILE) PYTHON='$(COVERAGE) run -p' $(SHELL) '$(TESTSUITE)' -C tests AUTOTEST_PATH=$(AUTOTEST_PATH) $(TESTSUITEFLAGS) @cd $(srcdir) && $(COVERAGE) combine && COVERAGE_FILE=$(COVERAGE_FILE) $(COVERAGE) annotate @echo @echo '----------------------------------------------------------------------' @echo 'Annotated coverage source has the ",cover" extension.' @echo '----------------------------------------------------------------------' @echo @COVERAGE_FILE=$(COVERAGE_FILE) $(COVERAGE) report $(valgrind_wrappers): tests/valgrind-wrapper.in @test -d tests/valgrind || mkdir tests/valgrind $(AM_V_GEN) sed -e 's,[@]wrap_program[@],$@,' \ $(top_srcdir)/tests/valgrind-wrapper.in > $@.tmp && \ chmod +x $@.tmp && \ mv $@.tmp $@ check-valgrind: all tests/atconfig tests/atlocal $(TESTSUITE) \ $(valgrind_wrappers) $(check_DATA) $(SHELL) '$(TESTSUITE)' -C tests CHECK_VALGRIND=true VALGRIND='$(VALGRIND)' AUTOTEST_PATH='tests/valgrind:$(AUTOTEST_PATH)' -d $(TESTSUITEFLAGS) @echo @echo '----------------------------------------------------------------------' @echo 'Valgrind output can be found in tests/testsuite.dir/*/valgrind.*' @echo '----------------------------------------------------------------------' # OFTest support. check-oftest: all $(AM_V_at)srcdir='$(srcdir)' $(SHELL) $(srcdir)/tests/run-oftest # Ryu support. check-ryu: all $(AM_V_at)srcdir='$(srcdir)' $(SHELL) $(srcdir)/tests/run-ryu # Run kmod tests. Assume kernel modules has been installed or linked into the kernel check-kernel: all tests/atconfig tests/atlocal $(SYSTEM_KMOD_TESTSUITE) $(SHELL) '$(SYSTEM_KMOD_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)' -d $(TESTSUITEFLAGS) # Testing the out of tree Kernel module check-kmod: all tests/atconfig tests/atlocal $(SYSTEM_KMOD_TESTSUITE) $(MAKE) modules_install modprobe -r openvswitch $(MAKE) check-kernel check-system-userspace: all tests/atconfig tests/atlocal $(SYSTEM_USERSPACE_TESTSUITE) $(SHELL) '$(SYSTEM_USERSPACE_TESTSUITE)' -C tests AUTOTEST_PATH='$(AUTOTEST_PATH)' $(TESTSUITEFLAGS) clean-local: test ! -f '$(TESTSUITE)' || $(SHELL) '$(TESTSUITE)' -C tests --clean @WIN32_TRUE@$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(COMMON_MACROS_AT) $(TESTSUITE_PATCH) @WIN32_TRUE@ $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o testsuite.tmp $@.at @WIN32_TRUE@ patch -p0 testsuite.tmp $(TESTSUITE_PATCH) @WIN32_TRUE@ $(AM_V_at)mv testsuite.tmp $@ @WIN32_FALSE@$(TESTSUITE): package.m4 $(TESTSUITE_AT) $(COMMON_MACROS_AT) @WIN32_FALSE@ $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at @WIN32_FALSE@ $(AM_V_at)mv $@.tmp $@ $(SYSTEM_KMOD_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_KMOD_TESTSUITE_AT) $(COMMON_MACROS_AT) $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at $(AM_V_at)mv $@.tmp $@ $(SYSTEM_USERSPACE_TESTSUITE): package.m4 $(SYSTEM_TESTSUITE_AT) $(SYSTEM_USERSPACE_TESTSUITE_AT) $(COMMON_MACROS_AT) $(AM_V_GEN)$(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at $(AM_V_at)mv $@.tmp $@ # The `:;' works around a Bash 3.2 bug when the output is not writeable. $(srcdir)/package.m4: $(top_srcdir)/configure.ac $(AM_V_GEN):;{ \ echo '# Signature of the current package.' && \ echo 'm4_define([AT_PACKAGE_NAME], [$(PACKAGE_NAME)])' && \ echo 'm4_define([AT_PACKAGE_TARNAME], [$(PACKAGE_TARNAME)])' && \ echo 'm4_define([AT_PACKAGE_VERSION], [$(PACKAGE_VERSION)])' && \ echo 'm4_define([AT_PACKAGE_STRING], [$(PACKAGE_STRING)])' && \ echo 'm4_define([AT_PACKAGE_BUGREPORT], [$(PACKAGE_BUGREPORT)])'; \ } >'$(srcdir)/package.m4' tests/idltest.ovsidl: $(IDLTEST_IDL_FILES) $(AM_V_GEN)$(OVSDB_IDLC) -C $(srcdir) annotate $(IDLTEST_IDL_FILES) > $@.tmp && \ mv $@.tmp $@ tests/idltest.c: tests/idltest.h @HAVE_OPENSSL_TRUE@tests/testpki-cacert.pem: tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)cp tests/pki/switchca/cacert.pem $@ @HAVE_OPENSSL_TRUE@tests/testpki-cert.pem: tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)cp tests/pki/test-cert.pem $@ @HAVE_OPENSSL_TRUE@tests/testpki-req.pem: tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)cp tests/pki/test-req.pem $@ @HAVE_OPENSSL_TRUE@tests/testpki-privkey.pem: tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)cp tests/pki/test-privkey.pem $@ @HAVE_OPENSSL_TRUE@tests/testpki-cert2.pem: tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)cp tests/pki/test2-cert.pem $@ @HAVE_OPENSSL_TRUE@tests/testpki-req2.pem: tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)cp tests/pki/test2-req.pem $@ @HAVE_OPENSSL_TRUE@tests/testpki-privkey2.pem: tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)cp tests/pki/test2-privkey.pem $@ @HAVE_OPENSSL_TRUE@tests/pki/stamp: @HAVE_OPENSSL_TRUE@ $(AM_V_at)rm -f tests/pki/stamp @HAVE_OPENSSL_TRUE@ $(AM_V_at)rm -rf tests/pki @HAVE_OPENSSL_TRUE@ $(AM_V_GEN)$(OVS_PKI) init && \ @HAVE_OPENSSL_TRUE@ $(OVS_PKI) req+sign tests/pki/test && \ @HAVE_OPENSSL_TRUE@ $(OVS_PKI) req+sign tests/pki/test2 && \ @HAVE_OPENSSL_TRUE@ : > tests/pki/stamp @HAVE_OPENSSL_TRUE@clean-pki: @HAVE_OPENSSL_TRUE@ rm -f tests/pki/stamp @HAVE_OPENSSL_TRUE@ rm -rf tests/pki include/odp-netlink.h: datapath/linux/compat/include/linux/openvswitch.h \ build-aux/extract-odp-netlink-h $(AM_V_GEN)sed -f $(srcdir)/build-aux/extract-odp-netlink-h < $< > $@ @HAVE_PYTHON_TRUE@.h.hstamp: @HAVE_PYTHON_TRUE@ $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/check-structs -I$(srcdir)/include $< && \ @HAVE_PYTHON_TRUE@ touch $@ @HAVE_PYTHON_TRUE@$(HSTAMP_FILES): build-aux/check-structs $(openflowinclude_HEADERS) check-debian-changelog-version: @DEB_VERSION=`echo '$(VERSION)' | sed 's/pre/~pre/'`; \ if $(FGREP) '($(DEB_VERSION)' $(srcdir)/debian/changelog >/dev/null; \ then \ :; \ else \ echo "Update debian/changelog to mention version $(VERSION)"; \ exit 1; \ fi $(srcdir)/debian/copyright: AUTHORS debian/copyright.in $(AM_V_GEN) \ { sed -n -e '/%AUTHORS%/q' -e p < $(srcdir)/debian/copyright.in; \ sed '1,/^$$/d' $(srcdir)/AUTHORS | \ sed -n -e '/^$$/q' -e 's/^/ /p'; \ sed -e '1,/%AUTHORS%/d' $(srcdir)/debian/copyright.in; \ } > $@ # vswitch E-R diagram # # If "python" or "dot" is not available, then we do not add graphical diagram # to the documentation. @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@vswitchd/vswitch.gv: ovsdb/ovsdb-dot.in vswitchd/vswitch.ovsschema @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/vswitchd/vswitch.ovsschema > $@ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@vswitchd/vswitch.pic: vswitchd/vswitch.gv ovsdb/dot2pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)(dot -T plain < vswitchd/vswitch.gv | $(PERL) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ mv $@.tmp $@ vswitchd/ovs-vswitchd.conf.db.5: \ ovsdb/ovsdb-doc vswitchd/vswitch.xml vswitchd/vswitch.ovsschema \ $(VSWITCH_PIC) $(AM_V_GEN)$(OVSDB_DOC) \ $(VSWITCH_DOT_DIAGRAM_ARG) \ --version=$(VERSION) \ $(srcdir)/vswitchd/vswitch.ovsschema \ $(srcdir)/vswitchd/vswitch.xml > $@.tmp && \ mv $@.tmp $@ vswitchd/vswitch.ovsschema.stamp: vswitchd/vswitch.ovsschema $(srcdir)/build-aux/cksum-schema-check $? $@ .ovsidl.c: $(AM_V_GEN)$(OVSDB_IDLC) c-idl-source $< > $@.tmp && mv $@.tmp $@ .ovsidl.h: $(AM_V_GEN)$(OVSDB_IDLC) c-idl-header $< > $@.tmp && mv $@.tmp $@ # This must be done late: macros in targets are expanded when the # target line is read, so if this file were to be included before some # other file that added to OVSIDL_BUILT, then those files wouldn't get # the dependency. # # However, current versions of Automake seem to output all variable # assignments before any targets, so it doesn't seem to be a problem, # at least for now. $(OVSIDL_BUILT): ovsdb/ovsdb-idlc.in $(srcdir)/rhel/openvswitch-dkms.spec: rhel/openvswitch-dkms.spec.in $(top_builddir)/config.status $(update_rhel_spec) $(srcdir)/rhel/openvswitch-kmod-rhel6.spec: rhel/openvswitch-kmod-rhel6.spec.in $(top_builddir)/config.status $(update_rhel_spec) $(srcdir)/rhel/openvswitch-kmod-fedora.spec: rhel/openvswitch-kmod-fedora.spec.in $(top_builddir)/config.status $(update_rhel_spec) $(srcdir)/rhel/openvswitch.spec: rhel/openvswitch.spec.in $(top_builddir)/config.status $(update_rhel_spec) $(srcdir)/rhel/openvswitch-fedora.spec: rhel/openvswitch-fedora.spec.in $(top_builddir)/config.status $(update_rhel_spec) $(srcdir)/xenserver/openvswitch-xen.spec: xenserver/openvswitch-xen.spec.in $(top_builddir)/config.status $(AM_V_GEN)($(ro_shell) && sed -e 's,[@]VERSION[@],$(VERSION),g') \ < $(srcdir)/xenserver/$(@F).in > $(@F).tmp || exit 1; \ if cmp -s $(@F).tmp $@; then touch $@; rm $(@F).tmp; else mv $(@F).tmp $@; fi @HAVE_PYTHON_TRUE@ovs-install-data-local: @HAVE_PYTHON_TRUE@ $(MKDIR_P) python/ovs @HAVE_PYTHON_TRUE@ sed \ @HAVE_PYTHON_TRUE@ -e '/^##/d' \ @HAVE_PYTHON_TRUE@ -e 's,[@]pkgdatadir[@],$(pkgdatadir),g' \ @HAVE_PYTHON_TRUE@ -e 's,[@]RUNDIR[@],$(RUNDIR),g' \ @HAVE_PYTHON_TRUE@ -e 's,[@]LOGDIR[@],$(LOGDIR),g' \ @HAVE_PYTHON_TRUE@ -e 's,[@]bindir[@],$(bindir),g' \ @HAVE_PYTHON_TRUE@ -e 's,[@]sysconfdir[@],$(sysconfdir),g' \ @HAVE_PYTHON_TRUE@ -e 's,[@]DBDIR[@],$(DBDIR),g' \ @HAVE_PYTHON_TRUE@ < $(srcdir)/python/ovs/dirs.py.template \ @HAVE_PYTHON_TRUE@ > python/ovs/dirs.py.tmp @HAVE_PYTHON_TRUE@ $(MKDIR_P) $(DESTDIR)$(pkgdatadir)/python/ovs @HAVE_PYTHON_TRUE@ $(INSTALL_DATA) python/ovs/dirs.py.tmp $(DESTDIR)$(pkgdatadir)/python/ovs/dirs.py @HAVE_PYTHON_TRUE@ rm python/ovs/dirs.py.tmp @HAVE_PYTHON_TRUE@python-sdist: $(srcdir)/python/ovs/version.py $(ovs_pyfiles) python/ovs/dirs.py @HAVE_PYTHON_TRUE@ (cd python/ && $(PYTHON) setup.py sdist) @HAVE_PYTHON_TRUE@pypi-upload: $(srcdir)/python/ovs/version.py $(ovs_pyfiles) python/ovs/dirs.py @HAVE_PYTHON_TRUE@ (cd python/ && $(PYTHON) setup.py sdist upload) @HAVE_PYTHON_FALSE@ovs-install-data-local: @HAVE_PYTHON_FALSE@ @: install-data-local: ovs-install-data-local ovs-uninstall-local: rm -f $(DESTDIR)$(pkgdatadir)/python/ovs/dirs.py $(srcdir)/python/ovs/version.py: config.status $(AM_V_GEN)$(ro_shell) > $(@F).tmp && \ echo 'VERSION = "$(VERSION)"' >> $(@F).tmp && \ if cmp -s $(@F).tmp $@; then touch $@; rm $(@F).tmp; else mv $(@F).tmp $@; fi $(srcdir)/python/ovs/dirs.py: python/ovs/dirs.py.template $(AM_V_GEN)sed \ -e '/^##/d' \ -e 's,[@]pkgdatadir[@],/usr/local/share/openvswitch,g' \ -e 's,[@]RUNDIR[@],/var/run,g' \ -e 's,[@]LOGDIR[@],/usr/local/var/log,g' \ -e 's,[@]bindir[@],/usr/local/bin,g' \ -e 's,[@]sysconfdir[@],/usr/local/etc,g' \ -e 's,[@]DBDIR[@],/usr/local/etc/openvswitch,g' \ < $? > $@.tmp && \ mv $@.tmp $@ sandbox: all cd $(srcdir)/tutorial && MAKE=$(MAKE) ./ovs-sandbox -b $(abs_builddir) $(SANDBOXFLAGS) vtep/vtep-idl.ovsidl: $(VTEP_IDL_FILES) $(AM_V_GEN)$(OVSDB_IDLC) annotate $(VTEP_IDL_FILES) > $@.tmp && \ mv $@.tmp $@ # VTEP E-R diagram # # If "python" or "dot" is not available, then we do not add graphical diagram # to the documentation. @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@vtep/vtep.gv: ovsdb/ovsdb-dot.in vtep/vtep.ovsschema @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/vtep/vtep.ovsschema > $@ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@vtep/vtep.pic: vtep/vtep.gv ovsdb/dot2pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)(dot -T plain < vtep/vtep.gv | $(PERL) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ mv $@.tmp $@ vtep/vtep.5: \ ovsdb/ovsdb-doc vtep/vtep.xml $(srcdir)/vtep/vtep.ovsschema $(VTEP_PIC) $(AM_V_GEN)$(OVSDB_DOC) \ $(VTEP_DOT_DIAGRAM_ARG) \ --version=$(VERSION) \ $(srcdir)/vtep/vtep.ovsschema \ $(srcdir)/vtep/vtep.xml > $@.tmp && \ mv $@.tmp $@ vtep/vtep.ovsschema.stamp: vtep/vtep.ovsschema $(srcdir)/build-aux/cksum-schema-check $? $@ $(srcdir)/datapath-windows/include/OvsDpInterface.h: \ datapath/linux/compat/include/linux/openvswitch.h \ build-aux/extract-odp-netlink-windows-dp-h $(AM_V_GEN)sed -f $(srcdir)/build-aux/extract-odp-netlink-windows-dp-h < $< > $@ windows_installer: all #Userspace files needed for the installer cp -f $(top_srcdir)/datapath-windows/misc/OVS.psm1 windows/ovs-windows-installer/Services/OVS.psm1 cp -f $(top_srcdir)/vswitchd/vswitch.ovsschema windows/ovs-windows-installer/Services/vswitch.ovsschema cp -f $(top_srcdir)/vswitchd/ovs-vswitchd.exe windows/ovs-windows-installer/Services/ovs-vswitchd.exe cp -f $(top_srcdir)/ovsdb/ovsdb-server.exe windows/ovs-windows-installer/Services/ovsdb-server.exe cp -f $(top_srcdir)/utilities/*.exe windows/ovs-windows-installer/Binaries/ cp -f $(top_srcdir)/utilities/*.pdb windows/ovs-windows-installer/Symbols/ cp -f $(top_srcdir)/ovsdb/ovsdb-client.exe windows/ovs-windows-installer/Binaries/ovsdb-client.exe cp -f $(top_srcdir)/ovsdb/ovsdb-tool.exe windows/ovs-windows-installer/Binaries/ovsdb-tool.exe cp -f $(top_srcdir)/ovsdb/ovsdb-client.pdb windows/ovs-windows-installer/Symbols/ cp -f $(top_srcdir)/ovsdb/ovsdb-tool.pdb windows/ovs-windows-installer/Symbols/ #Third party files needed by the installer cp -f $(PTHREAD_WIN32_DIR_DLL_WIN_FORM)/*.dll windows/ovs-windows-installer/Binaries/ cp -f "/c/Program Files (x86)/Common Files/Merge Modules/Microsoft_VC120_CRT_x86.msm" windows/ovs-windows-installer/Redist/Microsoft_VC120_CRT_x86.msm #Forwarding extension files needed for the installer cp -f $(top_srcdir)/datapath-windows/x64/Win8$(VSTUDIO_CONFIG)/package/ovsext.cat windows/ovs-windows-installer/Driver/Win8/ovsext.cat cp -f $(top_srcdir)/datapath-windows/x64/Win8$(VSTUDIO_CONFIG)/package/ovsext.inf windows/ovs-windows-installer/Driver/Win8/ovsext.inf cp -f $(top_srcdir)/datapath-windows/x64/Win8$(VSTUDIO_CONFIG)/package/OVSExt.sys windows/ovs-windows-installer/Driver/Win8/OVSExt.sys cp -f $(top_srcdir)/datapath-windows/x64/Win8.1$(VSTUDIO_CONFIG)/package/ovsext.cat windows/ovs-windows-installer/Driver/Win8.1/ovsext.cat cp -f $(top_srcdir)/datapath-windows/x64/Win8.1$(VSTUDIO_CONFIG)/package/ovsext.inf windows/ovs-windows-installer/Driver/Win8.1/ovsext.inf cp -f $(top_srcdir)/datapath-windows/x64/Win8.1$(VSTUDIO_CONFIG)/package/ovsext.sys windows/ovs-windows-installer/Driver/Win8.1/ovsext.sys MSBuild.exe windows/ovs-windows-installer.sln /target:Build /property:Configuration="Release" # OVN southbound E-R diagram # # If "python" or "dot" is not available, then we do not add graphical diagram # to the documentation. @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ovn/ovn-sb.gv: ovsdb/ovsdb-dot.in ovn/ovn-sb.ovsschema @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/ovn/ovn-sb.ovsschema > $@ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ovn/ovn-sb.pic: ovn/ovn-sb.gv ovsdb/dot2pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)(dot -T plain < ovn/ovn-sb.gv | $(PERL) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ mv $@.tmp $@ ovn/ovn-sb.5: \ ovsdb/ovsdb-doc ovn/ovn-sb.xml ovn/ovn-sb.ovsschema $(OVN_SB_PIC) $(AM_V_GEN)$(OVSDB_DOC) \ $(OVN_SB_DOT_DIAGRAM_ARG) \ --version=$(VERSION) \ $(srcdir)/ovn/ovn-sb.ovsschema \ $(srcdir)/ovn/ovn-sb.xml > $@.tmp && \ mv $@.tmp $@ # OVN northbound E-R diagram # # If "python" or "dot" is not available, then we do not add graphical diagram # to the documentation. @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ovn/ovn-nb.gv: ovsdb/ovsdb-dot.in ovn/ovn-nb.ovsschema @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)$(OVSDB_DOT) --no-arrows $(srcdir)/ovn/ovn-nb.ovsschema > $@ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ovn/ovn-nb.pic: ovn/ovn-nb.gv ovsdb/dot2pic @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ $(AM_V_GEN)(dot -T plain < ovn/ovn-nb.gv | $(PERL) $(srcdir)/ovsdb/dot2pic -f 3) > $@.tmp && \ @HAVE_DOT_TRUE@@HAVE_PYTHON_TRUE@ mv $@.tmp $@ ovn/ovn-nb.5: \ ovsdb/ovsdb-doc ovn/ovn-nb.xml ovn/ovn-nb.ovsschema $(OVN_NB_PIC) $(AM_V_GEN)$(OVSDB_DOC) \ $(OVN_NB_DOT_DIAGRAM_ARG) \ --version=$(VERSION) \ $(srcdir)/ovn/ovn-nb.ovsschema \ $(srcdir)/ovn/ovn-nb.xml > $@.tmp && \ mv $@.tmp $@ ovn/ovn-nb.ovsschema.stamp: ovn/ovn-nb.ovsschema $(srcdir)/build-aux/cksum-schema-check $? $@ ovn/ovn-sb.ovsschema.stamp: ovn/ovn-sb.ovsschema $(srcdir)/build-aux/cksum-schema-check $? $@ ovn/lib/ovn-sb-idl.ovsidl: $(OVN_SB_IDL_FILES) $(AM_V_GEN)$(OVSDB_IDLC) annotate $(OVN_SB_IDL_FILES) > $@.tmp && \ mv $@.tmp $@ ovn/lib/ovn-nb-idl.ovsidl: $(OVN_NB_IDL_FILES) $(AM_V_GEN)$(OVSDB_IDLC) annotate $(OVN_NB_IDL_FILES) > $@.tmp && \ mv $@.tmp $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: openvswitch-2.5.0/PaxHeaders.69223/PORTING.md0000644000000000000000000000013112631676262015307 xustar0029 mtime=1449622706.91043722 30 atime=1456592667.291089585 30 ctime=1456594659.661266455 openvswitch-2.5.0/PORTING.md0000664000175000017500000003425112631676262017005 0ustar00jpettitjpettit00000000000000How to Port Open vSwitch to New Software or Hardware ==================================================== Open vSwitch (OVS) is intended to be easily ported to new software and hardware platforms. This document describes the types of changes that are most likely to be necessary in porting OVS to Unix-like platforms. (Porting OVS to other kinds of platforms is likely to be more difficult.) Vocabulary ---------- For historical reasons, different words are used for essentially the same concept in different areas of the Open vSwitch source tree. Here is a concordance, indexed by the area of the source tree: datapath/ vport --- vswitchd/ iface port ofproto/ port bundle ofproto/bond.c slave bond lib/lacp.c slave lacp lib/netdev.c netdev --- database Interface Port Open vSwitch Architectural Overview ----------------------------------- The following diagram shows the very high-level architecture of Open vSwitch from a porter's perspective. +-------------------+ | ovs-vswitchd |<-->ovsdb-server +-------------------+ | ofproto |<-->OpenFlow controllers +--------+-+--------+ | netdev | | ofproto| +--------+ |provider| | netdev | +--------+ |provider| +--------+ Some of the components are generic. Modulo bugs or inadequacies, these components should not need to be modified as part of a port: - "ovs-vswitchd" is the main Open vSwitch userspace program, in vswitchd/. It reads the desired Open vSwitch configuration from the ovsdb-server program over an IPC channel and passes this configuration down to the "ofproto" library. It also passes certain status and statistical information from ofproto back into the database. - "ofproto" is the Open vSwitch library, in ofproto/, that implements an OpenFlow switch. It talks to OpenFlow controllers over the network and to switch hardware or software through an "ofproto provider", explained further below. - "netdev" is the Open vSwitch library, in lib/netdev.c, that abstracts interacting with network devices, that is, Ethernet interfaces. The netdev library is a thin layer over "netdev provider" code, explained further below. The other components may need attention during a port. You will almost certainly have to implement a "netdev provider". Depending on the type of port you are doing and the desired performance, you may also have to implement an "ofproto provider" or a lower-level component called a "dpif" provider. The following sections talk about these components in more detail. Writing a netdev Provider ------------------------- A "netdev provider" implements an operating system and hardware specific interface to "network devices", e.g. eth0 on Linux. Open vSwitch must be able to open each port on a switch as a netdev, so you will need to implement a "netdev provider" that works with your switch hardware and software. struct netdev_class, in lib/netdev-provider.h, defines the interfaces required to implement a netdev. That structure contains many function pointers, each of which has a comment that is meant to describe its behavior in detail. If the requirements are unclear, please report this as a bug. The netdev interface can be divided into a few rough categories: * Functions required to properly implement OpenFlow features. For example, OpenFlow requires the ability to report the Ethernet hardware address of a port. These functions must be implemented for minimally correct operation. * Functions required to implement optional Open vSwitch features. For example, the Open vSwitch support for in-band control requires netdev support for inspecting the TCP/IP stack's ARP table. These functions must be implemented if the corresponding OVS features are to work, but may be omitted initially. * Functions needed in some implementations but not in others. For example, most kinds of ports (see below) do not need functionality to receive packets from a network device. The existing netdev implementations may serve as useful examples during a port: * lib/netdev-linux.c implements netdev functionality for Linux network devices, using Linux kernel calls. It may be a good place to start for full-featured netdev implementations. * lib/netdev-vport.c provides support for "virtual ports" implemented by the Open vSwitch datapath module for the Linux kernel. This may serve as a model for minimal netdev implementations. * lib/netdev-dummy.c is a fake netdev implementation useful only for testing. Porting Strategies ------------------ After a netdev provider has been implemented for a system's network devices, you may choose among three basic porting strategies. The lowest-effort strategy is to use the "userspace switch" implementation built into Open vSwitch. This ought to work, without writing any more code, as long as the netdev provider that you implemented supports receiving packets. It yields poor performance, however, because every packet passes through the ovs-vswitchd process. See [INSTALL.userspace.md] for instructions on how to configure a userspace switch. If the userspace switch is not the right choice for your port, then you will have to write more code. You may implement either an "ofproto provider" or a "dpif provider". Which you should choose depends on a few different factors: * Only an ofproto provider can take full advantage of hardware with built-in support for wildcards (e.g. an ACL table or a TCAM). * A dpif provider can take advantage of the Open vSwitch built-in implementations of bonding, LACP, 802.1ag, 802.1Q VLANs, and other features. An ofproto provider has to provide its own implementations, if the hardware can support them at all. * A dpif provider is usually easier to implement, but most appropriate for software switching. It "explodes" wildcard rules into exact-match entries (with an optional wildcard mask). This allows fast hash lookups in software, but makes inefficient use of TCAMs in hardware that support wildcarding. The following sections describe how to implement each kind of port. ofproto Providers ----------------- An "ofproto provider" is what ofproto uses to directly monitor and control an OpenFlow-capable switch. struct ofproto_class, in ofproto/ofproto-provider.h, defines the interfaces to implement an ofproto provider for new hardware or software. That structure contains many function pointers, each of which has a comment that is meant to describe its behavior in detail. If the requirements are unclear, please report this as a bug. The ofproto provider interface is preliminary. Please let us know if it seems unsuitable for your purpose. We will try to improve it. Writing a dpif Provider ----------------------- Open vSwitch has a built-in ofproto provider named "ofproto-dpif", which is built on top of a library for manipulating datapaths, called "dpif". A "datapath" is a simple flow table, one that is only required to support exact-match flows, that is, flows without wildcards. When a packet arrives on a network device, the datapath looks for it in this table. If there is a match, then it performs the associated actions. If there is no match, the datapath passes the packet up to ofproto-dpif, which maintains the full OpenFlow flow table. If the packet matches in this flow table, then ofproto-dpif executes its actions and inserts a new entry into the dpif flow table. (Otherwise, ofproto-dpif passes the packet up to ofproto to send the packet to the OpenFlow controller, if one is configured.) When calculating the dpif flow, ofproto-dpif generates an exact-match flow that describes the missed packet. It makes an effort to figure out what fields can be wildcarded based on the switch's configuration and OpenFlow flow table. The dpif is free to ignore the suggested wildcards and only support the exact-match entry. However, if the dpif supports wildcarding, then it can use the masks to match multiple flows with fewer entries and potentially significantly reduce the number of flow misses handled by ofproto-dpif. The "dpif" library in turn delegates much of its functionality to a "dpif provider". The following diagram shows how dpif providers fit into the Open vSwitch architecture: _ | +-------------------+ | | ovs-vswitchd |<-->ovsdb-server | +-------------------+ | | ofproto |<-->OpenFlow controllers | +--------+-+--------+ _ | | netdev | |ofproto-| | userspace | +--------+ | dpif | | | | netdev | +--------+ | | |provider| | dpif | | | +---||---+ +--------+ | | || | dpif | | implementation of | || |provider| | ofproto provider |_ || +---||---+ | || || | _ +---||-----+---||---+ | | | |datapath| | kernel | | +--------+ _| | | | |_ +--------||---------+ || physical NIC struct dpif_class, in lib/dpif-provider.h, defines the interfaces required to implement a dpif provider for new hardware or software. That structure contains many function pointers, each of which has a comment that is meant to describe its behavior in detail. If the requirements are unclear, please report this as a bug. There are two existing dpif implementations that may serve as useful examples during a port: * lib/dpif-netlink.c is a Linux-specific dpif implementation that talks to an Open vSwitch-specific kernel module (whose sources are in the "datapath" directory). The kernel module performs all of the switching work, passing packets that do not match any flow table entry up to userspace. This dpif implementation is essentially a wrapper around calls into the kernel module. * lib/dpif-netdev.c is a generic dpif implementation that performs all switching internally. This is how the Open vSwitch userspace switch is implemented. Miscellaneous Notes ------------------- Open vSwitch source code uses uint16_t, uint32_t, and uint64_t as fixed-width types in host byte order, and ovs_be16, ovs_be32, and ovs_be64 as fixed-width types in network byte order. Each of the latter is equivalent to the one of the former, but the difference in name makes the intended use obvious. The default "fail-mode" for Open vSwitch bridges is "standalone", meaning that, when the OpenFlow controllers cannot be contacted, Open vSwitch acts as a regular MAC-learning switch. This works well in virtualization environments where there is normally just one uplink (either a single physical interface or a bond). In a more general environment, it can create loops. So, if you are porting to a general-purpose switch platform, you should consider changing the default "fail-mode" to "secure", which does not behave this way. See documentation for the "fail-mode" column in the Bridge table in ovs-vswitchd.conf.db(5) for more information. lib/entropy.c assumes that it can obtain high-quality random number seeds at startup by reading from /dev/urandom. You will need to modify it if this is not true on your platform. vswitchd/system-stats.c only knows how to obtain some statistics on Linux. Optionally you may implement them for your platform as well. Why OVS Does Not Support Hybrid Providers ----------------------------------------- The "Porting Strategies" section above describes the "ofproto provider" and "dpif provider" porting strategies. Only an ofproto provider can take advantage of hardware TCAM support, and only a dpif provider can take advantage of the OVS built-in implementations of various features. It is therefore tempting to suggest a hybrid approach that shares the advantages of both strategies. However, Open vSwitch does not support a hybrid approach. Doing so may be possible, with a significant amount of extra development work, but it does not yet seem worthwhile, for the reasons explained below. First, user surprise is likely when a switch supports a feature only with a high performance penalty. For example, one user questioned why adding a particular OpenFlow action to a flow caused a 1,058x slowdown on a hardware OpenFlow implementation [1]. The action required the flow to be implemented in software. Given that implementing a flow in software on the slow management CPU of a hardware switch causes a major slowdown, software-implemented flows would only make sense for very low-volume traffic. But many of the features built into the OVS software switch implementation would need to apply to every flow to be useful. There is no value, for example, in applying bonding or 802.1Q VLAN support only to low-volume traffic. Besides supporting features of OpenFlow actions, a hybrid approach could also support forms of matching not supported by particular switching hardware, by sending all packets that might match a rule to software. But again this can cause an unacceptable slowdown by forcing bulk traffic through software in the hardware switch's slow management CPU. Consider, for example, a hardware switch that can match on the IPv6 Ethernet type but not on fields in IPv6 headers. An OpenFlow table that matched on the IPv6 Ethernet type would perform well, but adding a rule that matched only UDPv6 would force every IPv6 packet to software, slowing down not just UDPv6 but all IPv6 processing. [1] Aaron Rosen, "Modify packet fields extremely slow", openflow-discuss mailing list, June 26, 2011, archived at https://mailman.stanford.edu/pipermail/openflow-discuss/2011-June/002386.html. Questions --------- Please direct porting questions to dev@openvswitch.org. We will try to use questions to improve this porting guide. [INSTALL.userspace.md]:INSTALL.userspace.md openvswitch-2.5.0/PaxHeaders.69223/configure.ac0000644000000000000000000000013212664357124016131 xustar0030 mtime=1456594516.111228629 30 atime=1456594522.235486393 30 ctime=1456594659.617264604 openvswitch-2.5.0/configure.ac0000664000175000017500000001420012664357124017616 0ustar00jpettitjpettit00000000000000# Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Nicira, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at: # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. AC_PREREQ(2.63) AC_INIT(openvswitch, 2.5.0, bugs@openvswitch.org) AC_CONFIG_SRCDIR([datapath/datapath.c]) AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR([build-aux]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_TESTDIR([tests]) AM_INIT_AUTOMAKE([tar-pax]) AC_PROG_CC_C99 AM_PROG_CC_C_O AC_PROG_CPP AC_PROG_MKDIR_P AC_PROG_FGREP AC_PROG_EGREP AC_ARG_VAR([PERL], [path to Perl interpreter]) AC_PATH_PROG([PERL], perl, no) if test "$PERL" = no; then AC_MSG_ERROR([Perl interpreter not found in $PATH or $PERL.]) fi AM_MISSING_PROG([AUTOM4TE], [autom4te]) AC_USE_SYSTEM_EXTENSIONS AC_C_BIGENDIAN AC_SYS_LARGEFILE LT_INIT([disable-shared]) m4_pattern_forbid([LT_INIT]) dnl Make autoconf fail if libtool is missing. # The following explanation may help to understand the use of the # version number fields: current, revision, and age. # # Consider that there are three possible kinds of reactions from # users of your library to changes in a shared library: # # 1. Programs using the previous version may use the new version as drop-in # replacement, and programs using the new version can also work with the # previous one. In other words, no recompiling nor relinking is needed. # In short, there are no changes to any symbols, no symbols removed, # and no symbols added. In this case, bump revision only, don't touch # current nor age. # # 2. Programs using the previous version may use the new version as drop-in # replacement, but programs using the new version may use APIs not # present in the previous one. In other words, new symbols have been # added and a program linking against the new version may fail with # "unresolved symbols." If linking against the old version at runtime: # set revision to 0, bump current and age. # # 3. Programs may need to be changed, recompiled, relinked in order to use # the new version. This is the case when symbols have been modified or # deleted. Bump current, set revision and age to 0. m4_define([libopenvswitch_lt_current], [1]) m4_define([libopenvswitch_lt_revision], [0]) m4_define([libopenvswitch_lt_age], [0]) LT_CURRENT=libopenvswitch_lt_current AC_SUBST([LT_CURRENT]) LT_REVISION=libopenvswitch_lt_revision AC_SUBST([LT_REVISION]) LT_AGE=libopenvswitch_lt_age AC_SUBST([LT_AGE]) AC_SEARCH_LIBS([pow], [m]) AC_SEARCH_LIBS([clock_gettime], [rt]) AC_SEARCH_LIBS([timer_create], [rt]) AC_SEARCH_LIBS([pthread_create], [pthread]) AC_FUNC_STRERROR_R OVS_CHECK_ESX OVS_CHECK_WIN64 OVS_CHECK_WIN32 OVS_CHECK_VISUAL_STUDIO_DDK OVS_CHECK_COVERAGE OVS_CHECK_NDEBUG OVS_CHECK_NETLINK OVS_CHECK_OPENSSL OVS_CHECK_LIBCAPNG OVS_CHECK_LOGDIR OVS_CHECK_PYTHON OVS_CHECK_DOT OVS_CHECK_IF_PACKET OVS_CHECK_IF_DL OVS_CHECK_STRTOK_R AC_CHECK_DECLS([sys_siglist], [], [], [[#include ]]) AC_CHECK_MEMBERS([struct stat.st_mtim.tv_nsec, struct stat.st_mtimensec], [], [], [[#include ]]) AC_CHECK_MEMBERS([struct ifreq.ifr_flagshigh], [], [], [[#include ]]) AC_CHECK_FUNCS([mlockall strnlen getloadavg statvfs getmntent_r]) AC_CHECK_HEADERS([mntent.h sys/statvfs.h linux/types.h linux/if_ether.h stdatomic.h]) AC_CHECK_HEADERS([net/if_mib.h], [], [], [[#include #include ]]) OVS_CHECK_PKIDIR OVS_CHECK_RUNDIR OVS_CHECK_DBDIR OVS_CHECK_BACKTRACE OVS_CHECK_PERF_EVENT OVS_CHECK_VALGRIND OVS_CHECK_SOCKET_LIBS OVS_CHECK_XENSERVER_VERSION OVS_CHECK_GROFF OVS_CHECK_GNU_MAKE OVS_CHECK_TLS OVS_CHECK_ATOMIC_LIBS OVS_CHECK_GCC4_ATOMICS OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(1) OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(2) OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(4) OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(8) OVS_CHECK_POSIX_AIO OVS_CHECK_PTHREAD_SET_NAME OVS_CHECK_LINUX_HOST AX_FUNC_POSIX_MEMALIGN OVS_CHECK_INCLUDE_NEXT([stdio.h string.h]) AC_CONFIG_FILES([ lib/stdio.h lib/string.h ovsdb/libovsdb.sym ofproto/libofproto.sym lib/libsflow.sym lib/libopenvswitch.sym ovn/lib/libovn.sym vtep/libvtep.sym]) OVS_ENABLE_OPTION([-Wall]) OVS_ENABLE_OPTION([-Wextra]) OVS_ENABLE_OPTION([-Wno-sign-compare]) OVS_ENABLE_OPTION([-Wpointer-arith]) OVS_ENABLE_OPTION([-Wformat-security]) OVS_ENABLE_OPTION([-Wswitch-enum]) OVS_ENABLE_OPTION([-Wunused-parameter]) OVS_ENABLE_OPTION([-Wbad-function-cast]) OVS_ENABLE_OPTION([-Wcast-align]) OVS_ENABLE_OPTION([-Wstrict-prototypes]) OVS_ENABLE_OPTION([-Wold-style-definition]) OVS_ENABLE_OPTION([-Wmissing-prototypes]) OVS_ENABLE_OPTION([-Wmissing-field-initializers]) OVS_ENABLE_OPTION([-Wthread-safety]) OVS_ENABLE_OPTION([-fno-strict-aliasing]) OVS_ENABLE_OPTION([-Qunused-arguments]) OVS_CONDITIONAL_CC_OPTION([-Wno-unused], [HAVE_WNO_UNUSED]) OVS_CONDITIONAL_CC_OPTION([-Wno-unused-parameter], [HAVE_WNO_UNUSED_PARAMETER]) OVS_ENABLE_WERROR OVS_ENABLE_SPARSE AC_ARG_VAR(KARCH, [Kernel Architecture String]) AC_SUBST(KARCH) OVS_CHECK_LINUX OVS_CHECK_DPDK OVS_CHECK_PRAGMA_MESSAGE AC_SUBST([OVS_CFLAGS]) AC_SUBST([OVS_LDFLAGS]) AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(datapath/Makefile) AC_CONFIG_FILES(datapath/linux/Kbuild) AC_CONFIG_FILES(datapath/linux/Makefile) AC_CONFIG_FILES(datapath/linux/Makefile.main) AC_CONFIG_FILES(tests/atlocal) AC_CONFIG_FILES(lib/libopenvswitch.pc) AC_CONFIG_FILES(lib/libsflow.pc) AC_CONFIG_FILES(ofproto/libofproto.pc) AC_CONFIG_FILES(ovsdb/libovsdb.pc) AC_CONFIG_FILES(include/openvswitch/version.h) dnl This makes sure that include/openflow gets created in the build directory. AC_CONFIG_COMMANDS([include/openflow/openflow.h.stamp]) AC_CONFIG_COMMANDS([utilities/bugtool/dummy], [:]) AC_CONFIG_COMMANDS([ovn/dummy], [:]) AC_CONFIG_COMMANDS([ovn/utilities/dummy], [:]) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) AC_OUTPUT openvswitch-2.5.0/PaxHeaders.69223/Vagrantfile0000644000000000000000000000013212652645507016032 xustar0030 mtime=1454066503.374754586 30 atime=1456592667.299089913 30 ctime=1456594659.753270322 openvswitch-2.5.0/Vagrantfile0000664000175000017500000000404412652645507017524 0ustar00jpettitjpettit00000000000000# -*- mode: ruby -*- # vi: set ft=ruby : # Vagrantfile API/syntax version. Don't touch unless you know what you're doing! VAGRANTFILE_API_VERSION = "2" Vagrant.require_version ">=1.7.0" $bootstrap_fedora = <