pax_global_header00006660000000000000000000000064147662260000014515gustar00rootroot0000000000000052 comment=33c0c7d0eb1f3372e761301841f1764bd1373ddb ovn-vif-25.09.0~git20250813.23884f5/000077500000000000000000000000001476622600000157275ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/.github/000077500000000000000000000000001476622600000172675ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/.github/workflows/000077500000000000000000000000001476622600000213245ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/.github/workflows/tests.yaml000066400000000000000000000073321476622600000233570ustar00rootroot00000000000000name: Build and Test on: push: branches: - main - 'branch-**' pull_request: jobs: build-linux: env: apt-dependencies: | automake libtool gcc bc libssl-dev llvm-dev libelf-dev \ libnuma-dev libpcap-dev ncat libunbound-dev libunwind-dev \ libudev-dev python3-pip pip-dependencies: | scapy CC: ${{ matrix.compiler }} TESTSUITE: ${{ matrix.testsuite }} ASAN: ${{ matrix.asan }} name: linux ${{ join(matrix.*, ' ') }} runs-on: ubuntu-22.04 strategy: fail-fast: false matrix: include: - compiler: gcc - compiler: clang - compiler: clang testsuite: test asan: asan steps: - name: checkout self uses: actions/checkout@v3 - name: checkout OVN uses: actions/checkout@v3 with: repository: 'ovn-org/ovn' path: 'ovn' # The `base_ref` will only be set for PR and contain the name of the # target branch. The `ref_name` will be correct for the final push # check after a PR is merged. # # This setup may lead to failures on push to arbitrarily named branches # on a fork, but that is a price worth paying. # # Contributors can raise a draft PR to get accurate results. ref: ${{ github.base_ref || github.ref_name }} submodules: recursive - name: dependencies run: | set -euxo pipefail sudo apt update sudo apt remove -y netcat-openbsd sudo apt -y install ${{ env.apt-dependencies }} sudo pip install ${{ env.pip-dependencies }} - name: build OVS run: | set -euxo pipefail pushd ovn/ovs ./boot.sh && ./configure || { cat config.log; exit 1; } make -j4 || { cat config.log; exit 1; } popd - name: configure OVN run: | set -euxo pipefail pushd ovn ./boot.sh && ./configure \ || { cat config.log; exit 1; } popd - name: build ovn-vif run: | set -euxo pipefail ./boot.sh && ./configure \ --with-ovs-source=./ovn/ovs \ --with-ovn-source=./ovn \ --enable-plug-representor \ || { cat config.log; exit 1; } make -j4 || { cat config.log; exit 1; } - name: OVN VIF testsuite - test if: matrix.testsuite == 'test' run: | set -euxo pipefail if [ "$ASAN" ]; then export CFLAGS="-fno-omit-frame-pointer -fno-common" export OVN_CFLAGS="-fsanitize=address" fi export DISTCHECK_CONFIGURE_FLAGS="--with-ovs-source=$(realpath ./ovn/ovs) --with-ovn-source=$(realpath ./ovn) --enable-plug-representor" make distcheck -j4 TESTSUITEFLAGS="-j4" RECHECK=yes \ || { cat */_build/sub/tests/testsuite.log ; exit 1; } - name: re-configure and build OVN run: | set -euxo pipefail pushd ovn ./boot.sh && ./configure \ --with-ovs-source=$(realpath ./ovs) \ --with-vif-plug-provider=$(realpath ../) \ || { cat config.log; exit 1; } make -j4 || { cat config.log; exit 1; } popd - name: OVN testsuite - test if: matrix.testsuite == 'test' run: | set -euxo pipefail pushd ovn if [ "$ASAN" ]; then export CFLAGS="-fno-omit-frame-pointer -fno-common" export OVN_CFLAGS="-fsanitize=address" fi export DISTCHECK_CONFIGURE_FLAGS="--with-ovs-source=$(realpath ./ovs) --with-plug-provider=$(realpath ../)" make distcheck -j4 TESTSUITEFLAGS="-j4" RECHECK=yes \ || { cat */_build/sub/tests/testsuite.log ; exit 1; } popd ovn-vif-25.09.0~git20250813.23884f5/.gitignore000066400000000000000000000012261476622600000177200ustar00rootroot00000000000000#*# *.a *.d *.gcno *.gcda *.ko *.la *.lo *.loT *.mod.c *.o *.obj *.exe *.exp *.ilk *.lib *.pdb *.pyc *.retry *.so *.suo **/*.sym *~ *,cover .#* .*.cmd .*.swp .coverage .deps .dirstamp .libs .tmp_versions .vagrant /Makefile /Makefile.in /aclocal.m4 /all-distfiles /all-gitfiles /autom4te.cache /config.guess /config.h /config.h.in /config.log /config.status /config.sub /configure /configure-stamp /distfiles /install-sh /libtool /manpages.mk /missing /missing-distfiles /package.m4 /stamp-h1 /_build-gcc /_build-clang Module.symvers TAGS cscope.* tags _debian /.vagrant/ testsuite.tmp.orig /openvswitch*.tar.gz /.venv /cxx-check /Documentation/_build docs-check ovn-vif-25.09.0~git20250813.23884f5/AUTHORS.rst000066400000000000000000000053351476622600000176140ustar00rootroot00000000000000.. 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ======= Authors ======= The following people authored or signed off on commits in the OVN VIF source code version control repository. The build system was adopted from OVN and since OVN originated in the Open vSwitch git repository, this list also includes any contributors to the OVS build system. ================================== =============================================== Name Email ================================== =============================================== Aaron Conole aconole@redhat.com Alex Wang ee07b291@gmail.com Andy Zhou azhou@ovn.org Ben Pfaff blp@ovn.org Christian Ehrhardt christian.ehrhardt@canonical.com Daniele Di Proietto daniele.di.proietto@gmail.com Dumitru Ceara dceara@redhat.com Ed Maste emaste@freebsd.org Edward Tomasz Napierała trasz@freebsd.org Ethan J. Jackson ejj@eecs.berkeley.edu Flavio Leitner fbl@redhat.com Frode Nordahl frode.nordahl@canonical.com Gaetano Catalli gaetano.catalli@gmail.com Gurucharan Shetty guru@ovn.org Helmut Schaa helmut.schaa@googlemail.com Ilya Maximets i.maximets@ovn.org James Page james.page@ubuntu.com Jarno Rajahalme jarno@ovn.org Jesse Gross jesse@kernel.org Justin Pettit jpettit@ovn.org Mark Michelson mmichels@redhat.com Numan Siddique nusiddiq@redhat.com Stephen Finucane stephen@that.guru YAMAMOTO Takashi yamamoto@midokura.com ================================== =============================================== ovn-vif-25.09.0~git20250813.23884f5/CONTRIBUTING.rst000066400000000000000000000054531476622600000203770ustar00rootroot00000000000000.. 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ======================= Contributing to OVN VIF ======================= As an open source project, we welcome contributions of any kind. These can range from bug reports and code reviews, to signficant code or documentation features. How to submit patches --------------------- OVN VIF uses the GitHub Pull Request workflow. In general submissions should adhere to the `OVN Contributing guidelines`_. Please include a Signed-off-by header in the commit message. 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 OVN VIF 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. .. LINKS .. _OVN Contributing guidelines: https://docs.ovn.org/en/latest/internals/contributing/ ovn-vif-25.09.0~git20250813.23884f5/Documentation/000077500000000000000000000000001476622600000205405ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/Documentation/_static/000077500000000000000000000000001476622600000221665ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/Documentation/_static/logo.png000066400000000000000000000246051476622600000236430ustar00rootroot00000000000000PNG  IHDRXgAMA a cHRMz&u0`:pQ< pHYsgRYiTXtXML:com.adobe.xmp 1 L'Y'IDATx Ž2 kT j jN⾞DE3.ϼw\b|xB4񸞧ƿFP@0nD(↌ ì} ~Mޙ̝}o՝շ~ڻLLU4Fjvz(6jB}S".+++kch8SR{:QjP.'BWzjg6Q)BF@+^VjjԞVmaQo<@'zJګI*3'UCmX]6m$}x t\*++_~&arp.xX-s4<^n6Dfy曲h"Oi̟?z #w}e„ 2ydod]vR9j:C j4즞n5MMMl2[䮻r,S]]-[=3@"@}Ō3Ff͚%'tɤ5 wtM=l'*"h=Yt8 \B,b0 Pmm2/{ѣGPR5cǠuUTUUwz{'VF8QmL8p'/@# ľꪫuօz97ю''GQj;jjy@Ge;.:5sw{ֱpHł}%K#<"1J wb7^s`N7bB]7}祥0bx b}bnQ-hڒY_=EaH 19n23e"c!i|Do!F;VIȃׯwN=AhZAaH3rKaZf&ڠ=6IdB%?hz|4 {#0 䚏< 6.>&)AܝgJ]eAhkR'ӣ)}>6F0"Xa!Ԥ $t&m.ZM,+J5/F;L6ͭg}dZ?ڀ>cη8ـv9ciG!&Mq{-ŋ\KzԸ :.ᄏr!NN [d}W\tbK%ZV>sIc9&qᢓmN^O>+ɋl䅈E3tA!/! g…Nw BnܸaQAB,t1PscĪY+=;s@3XvmnY[>c;Æ 8ΡCgtM~ Eč K, .0y^J0 /0v2i!rAKU]t2;v{F!-y$.~]RvW3|Do .t J@%OnwX(Y6JکG?rࢵx8a:!s+A w|'aNz_2dHړwA Do|_te[d!F<0@;BBEi37[cy UիWw'n@>W_}EOG^ o}[@x ~:8]|` IsIIc uԍLd%dNWe;I<I[ԩSCp6?,9j{.,8\&g -+<(%A-˕u45\*jW$!+o^t2, 6Gc9G͕d׽N@p0 'Q?K. iH@kQSo C:&J_2X \h'dH%~̟}c PXS??$I|A@E\Fĸչ˂L7>㗦5aJ'{ $JIb tmq?e]s$q>w܀6*&诜y.>Ґ*#grn|k_ kl}əI4Yk:fٓ]g}alM̨<`mǏ&&|e9W:H:I:Q ب6Ys_ݨU(XnB3HQ a'qcuP''82 p]qpALA!"M4|`٢63jk[owFلMHhpwZ,mLuYaDIN~X7~x7ᣤsG|pg,.g*L>nb\\k70d 'tHrb~|gc:H~Zc5&S_7`o͏Sn6Lwԁ{Z7pC؇ ,LiF.x/ i&A+⮻3*+#hNYpR63CȬ $/<nJ x{v?9[}:p|DG:4lkMc6}ܑTIg*qShe.i]8n#~lYu\ NT'pn1QGʜN|dHǍ:#?ᲊT2NZX.BN阎L%/uíWKgU6mrjJj L8eUjKmjwǫ,1cGJtI8mjwyǽOŅNSO=|NNTrd .pҰ ||\Ӥfu4;G.^sC:ߓ1E|d @'C|2G R*3*k갋2R͛F4T ё& K 3,` (: n:?L&58M>oaU\#?O׶ to"so<"#3LVۺGހUDHM]G&+e 3R4,X|[5$"eL4HGA !i&H\aj 6Fg;64`htjnΩ9M+wJt*#|vt{`bew~IS.t~:)iɟtIELy+@< y}']q%LP\RI vVXVF PP35CJaa+ų,LJ YX~lN)IAm K)e3j8dC^ܰK80߃#q Nٸ G$pŊƇ ɱƛ9 rbtnrH7H|%>t|7WBb1d6 L-t'Y%қD]yG x=yE$㎀'Hs˟W.JKrǻ]ZVU?6'Am̜9S.RG@b* var׻ۈ%,x4tdw4f63H\0-_i&{ }Rǚ LEP.lU!cp7^Cp!?SOuf/0R`bMk -"[;9(w/[>n8L ]xo6# R`$dͺ52{lϗ5KCU)jy6_ƏbPλ=CKjkwddK܃Ε}wWV t(Rk~= :۲:Cɔo_MyTl;߸SN򫅿6|wKAz Lmh vp(b4d d~0mp#56D TYQ) ڱyOcW%)$2D}\%_L1Ij*قde} 5t[\n E(++4zG q3w+G-ȳelv>OhWɍVi mKF%W]Q-A2o^"7|k qR&:l .WMJfN)CuP$K$U1$lC}dg-?h+Q+7h (mmrʞ}''<[ɡn| X:+o޸MEG-L>G;<1hDH i0Ers+piU^>b v 7eAAY BxȈ|ݒɝ .쵕FZ5S9Uf2 YZÐz܊V>3b,Zvr?op K0bL9hARUQk WOHN9pZ۴VZܻ^y|,ruڨ?{7U}BdT6O˵ [02|rcrk7lL6i h5UWddt_'&2|9ٓD>1H*ˤ!hH:lƦMq=xH MW.m€$TIl4-9FݼwO_$`@M$Iv@\}P{,]T\ɡ݌ch5}miiҗ%Cfϖy'ϓ44ɦMR8͌gQ00aיSjKŤngvK&2Yn_|۶G"425lYɧyj:t@D(=QvY.zLqܾvytգn(>IP3*ds*ݢ\>^I/J Z+ĝ&ʄ'u\'Mn Q-f;ua#umePG@$APIgLaqF-kg&:c° rGˀI${ݐyVRڱޖ#nCdHi-kưnDK47Vbuj {%yT;\Y8c>tsilkKf B" $E SFM9Α_+8}Km9ٞ3j6Qn_arI*I0#jG7|SS:E?Mq# EZ@N-rtMSC+nM"(+xqP@݆辵ӮY/x'u44~:N(V%| _=C.dfxS4xdL1>O]D2hX! cf 7Hjzbc> 9Mr ?^x1I#'Hgo[}'Hgo[}'Hgo[}'Hgo[}'Hgo[}'Hgo[}'Hgo[}'Hgo( 7A N{%O[[[|%[~Ŗ Yn$1!n_bTUU0X>%@WVns7ސfq^[rʢEB-A 曾)pM~{$Ň|bM+yYj2ijZ}Æ Ow^`Ė ڲ˖-[oU Y1zJ6 W_}U̙jXQ7|Hvw!vp $)5.;ݠ Emk0oܸQ(gyxrgȰaä:yP27 pB[ss+Ald2{lyGK.8!EV aV[P3ZrJ/_DM[ 5P}/X@O.L:U&L d'IzGokpYۗ AP}3?BAf%ȥ7C ͭ8"@b1J9q|Zqo$ûb$sM+Cwq&D"BEKhB)âG Pxw'H'HkOxt Yxw'H'HkOxt Yxw'H'HkOC zz)%w[mGҟ 뮻DG ׼=z{.1II xM; b@=CvygMN1"Og'H1OC2mqƥA,^U;v;*:Jjjj'IF7|`Сfl :>.7.zjz1Zk87@pW@DEu@k@[C!9K6DPIߨ3MVy/)Js˚\44 }@a".E–y,\pL81lj%v/T%oNs[fM0w`ҤIMXNaguVۡJSdG8LݥLvZ$zjvo~#/v!hz'C`]vEƌ#Gy\֩L3 B=ZmZTl )asb c[#P`u va|KWZҥah=nlBC'CjW5jeդ#ީ0Xo<rl*}8\hՓ>A-O5cVO&3@ `zDs>  +îUG $xJZMj$Tr5~ijvZ>TFR'o<FE-}UT(ހcvjQ;@7bA %jTH|˔%4S1;IENDB`ovn-vif-25.09.0~git20250813.23884f5/Documentation/automake.mk000066400000000000000000000022271476622600000227020ustar00rootroot00000000000000DOC_SOURCE = \ Documentation/_static/logo.png \ Documentation/index.rst \ Documentation/topics/index.rst \ Documentation/topics/vif-plug-providers/index.rst \ Documentation/topics/vif-plug-providers/vif-plug-representor.rst EXTRA_DIST += $(DOC_SOURCE) # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build SPHINXSRCDIR = $(srcdir)/Documentation SPHINXBUILDDIR = $(builddir)/Documentation/_build # Internal variables. ALLSPHINXOPTS = -W -n -d $(SPHINXBUILDDIR)/doctrees $(SPHINXOPTS) $(SPHINXSRCDIR) sphinx_verbose = $(sphinx_verbose_@AM_V@) sphinx_verbose_ = $(sphinx_verbose_@AM_DEFAULT_V@) sphinx_verbose_0 = -q if HAVE_SPHINX docs-check: $(DOC_SOURCE) $(AM_V_GEN)$(SPHINXBUILD) $(sphinx_verbose) -b html $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html && touch $@ $(AM_V_GEN)$(SPHINXBUILD) $(sphinx_verbose) -b man $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/man && touch $@ ALL_LOCAL += docs-check CLEANFILES += docs-check check-docs: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/linkcheck clean-docs: rm -rf $(SPHINXBUILDDIR) rm -f docs-check CLEAN_LOCAL += clean-docs endif .PHONY: check-docs .PHONY: clean-docs ovn-vif-25.09.0~git20250813.23884f5/Documentation/conf.py000066400000000000000000000071001476622600000220350ustar00rootroot00000000000000# -*- coding: utf-8 -*- # # Open Virtual Network (OVN) documentation build configuration file, created by # sphinx-quickstart on Fri Sep 30 09:57:36 2016. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. import string import sys try: import ovs_sphinx_theme use_ovs_theme = True except ImportError: print("Cannot find 'ovs-sphinx-theme' package. " "Falling back to default theme.") use_ovs_theme = False # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.1' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = ['sphinx.ext.todo'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # # source_suffix = ['.rst', '.md'] source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Open Virtual Network (OVN)' copyright = u'2020, The Open Virtual Network (OVN) Development Community' author = u'The Open Virtual Network (OVN) Development Community' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The full version, including alpha/beta/rc tags. release = None filename = "../configure.ac" with open(filename, 'r') as f: for line in f: if 'AC_INIT' in line: # Parse "AC_INIT(openvswitch, 2.7.90, bugs@openvswitch.org)": release = line.split(',')[1].strip(string.whitespace + '[]') break if release is None: sys.stderr.write('%s: failed to determine Open Virtual Network (OVN) ' 'version\n' % filename) sys.exit(1) # The short X.Y version. # # However, it's important to know the difference between, e.g., 2.7 # and 2.7.90, which can be very different versions (2.7.90 may be much # closer to 2.8 than to 2.7), so check for that. version = release if '.90' in release else '.'.join(release.split('.')[0:2]) # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This patterns also effect to html_static_path and html_extra_path exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] # If true, check the validity of #anchors in links. linkcheck_anchors = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # if use_ovs_theme: html_theme = 'ovs' # Add any paths that contain custom themes here, relative to this directory. if use_ovs_theme: html_theme_path = [ovs_sphinx_theme.get_theme_dir()] else: html_theme_path = [] # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = '_static/logo.png' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] ovn-vif-25.09.0~git20250813.23884f5/Documentation/index.rst000066400000000000000000000017471476622600000224120ustar00rootroot00000000000000.. Copyright (c) 2021 Canonical 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ===================== OVN VIF Documentation ===================== .. toctree:: topics/index ovn-vif-25.09.0~git20250813.23884f5/Documentation/topics/000077500000000000000000000000001476622600000220415ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/Documentation/topics/index.rst000066400000000000000000000017471476622600000237130ustar00rootroot00000000000000.. Copyright (c) 2021 Canonical 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ====== Topics ====== OVN VIF ------- .. toctree:: :maxdepth: 2 vif-plug-providers/index ovn-vif-25.09.0~git20250813.23884f5/Documentation/topics/vif-plug-providers/000077500000000000000000000000001476622600000256055ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/Documentation/topics/vif-plug-providers/index.rst000066400000000000000000000017231476622600000274510ustar00rootroot00000000000000.. 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ================== VIF Plug Providers ================== .. toctree:: :maxdepth: 2 vif-plug-representor ovn-vif-25.09.0~git20250813.23884f5/Documentation/topics/vif-plug-providers/vif-plug-representor.rst000066400000000000000000000031511476622600000324360ustar00rootroot00000000000000.. 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ================================= The Representor VIF Plug Provider ================================= Logical Switch Port Options --------------------------- vif-plug:representor:pf-mac ~~~~~~~~~~~~~~~~~~~~~~~~~~~ MAC address for identifying PF device. When `OVN_Northbound:Logical_Switch_Port:options` key `vif-plug:representor:vf-num` is also set, this option is used to identify PF to use as base to locate the correct VF representor port. When `OVN_Northbound:Logical_Switch_Port:options` key `vif-plug:representor:vf-num` is not set this option is used to locate a PF representor port. vif-plug:representor:vf-num ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Logical VF number relative to PF device specified in `OVN_Northbound:Logical_Switch_Port:options` key `vif-plug-pf-mac`. ovn-vif-25.09.0~git20250813.23884f5/LICENSE000066400000000000000000000250171476622600000167410ustar00rootroot00000000000000 Apache License Version 2.0, January 2004 https://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS Copyright The Open vSwitch Authors 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 https://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. ovn-vif-25.09.0~git20250813.23884f5/MAINTAINERS.rst000066400000000000000000000022641476622600000202370ustar00rootroot00000000000000.. 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ========== Committers ========== OVN VIF committers are the people who have been granted access to push changes to the OVN VIF git repository. .. list-table:: OVN VIF Maintainers :header-rows: 1 * - Name - Email * - Frode Nordahl - frode.nordahl@canonical.com * - Martin Kalcok - martin.kalcok@canonical.com ovn-vif-25.09.0~git20250813.23884f5/Makefile.am000066400000000000000000000267001476622600000177700ustar00rootroot00000000000000# Copyright (C) 2007-2017 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. AUTOMAKE_OPTIONS = foreign subdir-objects ACLOCAL_AMFLAGS = -I m4 #SUBDIRS = ovs OVS_SRCDIR=@ovs_srcdir@ OVS_BUILDDIR=@ovs_builddir@ OVS_LIBDIR=@ovs_libdir@ OVSDB_LIBDIR=@ovsdb_libdir@ OVS_MANDIR=@ovs_mandir@ OVN_SRCDIR=@ovn_srcdir@ OVN_BUILDDIR=@ovn_builddir@ OVN_LIBDIR=@ovn_libdir@ OVN_MANDIR=@ovn_mandir@ AM_CPPFLAGS = $(SSL_CFLAGS) AM_LDFLAGS = $(SSL_LDFLAGS) AM_LDFLAGS += $(OVS_LDFLAGS) AM_CPPFLAGS += -I $(top_srcdir)/include AM_CPPFLAGS += -I $(top_srcdir)/include AM_CPPFLAGS += -I $(top_srcdir)/ovn AM_CPPFLAGS += -I $(top_builddir)/include AM_CPPFLAGS += -I $(top_srcdir)/lib AM_CPPFLAGS += -I $(top_builddir)/lib AM_CPPFLAGS += -I $(OVS_SRCDIR)/include AM_CPPFLAGS += -I $(OVS_BUILDDIR)/include AM_CPPFLAGS += -I $(OVS_SRCDIR)/lib AM_CPPFLAGS += -I $(OVS_BUILDDIR)/lib AM_CPPFLAGS += -I $(OVS_SRCDIR) AM_CPPFLAGS += -I $(OVS_BUILDDIR) AM_CPPFLAGS += -I $(OVN_SRCDIR)/include AM_CPPFLAGS += -I $(OVN_BUILDDIR)/include AM_CPPFLAGS += -I $(OVN_SRCDIR)/lib AM_CPPFLAGS += -I $(OVN_BUILDDIR)/lib AM_CPPFLAGS += -I $(OVN_SRCDIR) AM_CPPFLAGS += -I $(OVN_BUILDDIR) AM_CPPFLAGS += $(SSL_INCLUDES) AM_CFLAGS = -Wstrict-prototypes AM_CFLAGS += $(WARNING_FLAGS) AM_CFLAGS += $(OVS_CFLAGS) AM_DISTCHECK_CONFIGURE_FLAGS = --with-ovs-source=$(PWD)/ovs if NDEBUG AM_CPPFLAGS += -DNDEBUG AM_CFLAGS += -fomit-frame-pointer endif AM_CTAGSFLAGS = $(OVS_CTAGS_IDENTIFIERS_LIST) psep=":" ALL_LOCAL = BUILT_SOURCES = CLEANFILES = CLEAN_LOCAL = DISTCLEANFILES = PYCOV_CLEAN_FILES = build-aux/check-structs,cover EXTRA_DIST = \ AUTHORS.rst \ CONTRIBUTING.rst \ LICENSE \ MAINTAINERS.rst \ README.rst \ boot.sh \ .github/workflows/tests.yaml bin_PROGRAMS = sbin_PROGRAMS = bin_SCRIPTS = DIST_HOOKS = dist_man_MANS = dist_pkgdata_DATA = dist_pkgdata_SCRIPTS = dist_sbin_SCRIPTS = dist_scripts_SCRIPTS = dist_scripts_DATA = EXTRA_PROGRAMS = INSTALL_DATA_LOCAL = UNINSTALL_LOCAL = man_MANS = MAN_FRAGMENTS = MAN_ROOTS = noinst_DATA = noinst_HEADERS = lib_LTLIBRARIES = noinst_LTLIBRARIES = noinst_man_MANS = noinst_PROGRAMS = noinst_SCRIPTS = OVSIDL_BUILT = pkgdata_DATA = sbin_SCRIPTS = scripts_SCRIPTS = completion_SCRIPTS = scripts_DATA = SUFFIXES = check_DATA = check_SCRIPTS = pkgconfig_DATA = FLAKE8_PYFILES = if ENABLE_SPARSE_BY_DEFAULT C ?= 1 endif scriptsdir = $(pkgdatadir)/scripts completiondir = $(sysconfdir)/bash_completion.d pkgconfigdir = $(libdir)/pkgconfig # 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) ro_c = echo '/* -*- mode: c; buffer-read-only: t -*- */' ro_shell = printf '\043 Generated automatically -- do not modify! -*- buffer-read-only: t -*-\n' #submodules = $(shell grep 'path =' $(srcdir)/.gitmodules | sed -E 's/[\t ]*path =\s*(.*)/\1/g' | xargs) submodules = "ovs" SUFFIXES += .in .in: $(AM_V_GEN)PYTHONPATH=$(OVS_SRCDIR)/python$(psep)$$PYTHONPATH$(psep)$(srcdir)/python $(PYTHON3) $(srcdir)/build-aux/soexpand.py -I$(srcdir) -I$(OVS_SRCDIR) < $< | \ $(PYTHON3) $(srcdir)/build-aux/dpdkstrip.py $(DPDKSTRIP_FLAGS) | \ sed \ -e 's,[@]PKIDIR[@],$(PKIDIR),g' \ -e 's,[@]LOGDIR[@],$(LOGDIR),g' \ -e 's,[@]DBDIR[@],$(DBDIR),g' \ -e 's,[@]PYTHON3[@],$(PYTHON3),g' \ -e 's,[@]OVN_RUNDIR[@],$(OVN_RUNDIR),g' \ -e 's,[@]OVSBUILDDIR[@],$(OVSBUILDDIR),g' \ -e 's,[@]VERSION[@],$(VERSION),g' \ -e 's,[@]OVSVERSION[@],$(OVSVERSION),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 $@ SUFFIXES += .xml %: %.xml $(AM_V_GEN)$(run_python) $(srcdir)/build-aux/xml2nroff $< > $@.tmp \ -I $(srcdir) \ -I $(OVS_MANDIR) \ --version=$(VERSION) \ PKIDIR='$(PKIDIR)' \ LOGDIR='$(LOGDIR)' \ DBDIR='$(DBDIR)' \ PYTHON3='$(PYTHON3)' \ RUNDIR='$(RUNDIR)' \ OVN_RUNDIR='$(OVN_RUNDIR)' \ VERSION='$(VERSION)' \ localstatedir='$(localstatedir)' \ pkgdatadir='$(pkgdatadir)' \ sysconfdir='$(sysconfdir)' \ bindir='$(bindir)' \ sbindir='$(sbindir)' $(AM_v_at)mv $@.tmp $@ clean-pycov: cd $(srcdir) && rm -f $(PYCOV_CLEAN_FILES) CLEAN_LOCAL += clean-pycov .PHONY: clean-pycov # If we're checked out from a Git repository, make sure that every # file that is in Git is distributed. ALL_LOCAL += dist-hook-git dist-hook-git: distfiles @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1; then \ (cd $(srcdir) && git ls-files) | grep -v '\.gitignore$$' | \ grep -v '\.gitattributes$$' | \ grep -v '\.gitmodules$$' | \ grep -v "$(submodules)" | \ grep -v "^Documentation/conf.py$$" | \ LC_ALL=C sort -u > all-gitfiles; \ LC_ALL=C comm -1 -3 distfiles all-gitfiles > missing-distfiles; \ if test -s missing-distfiles; then \ echo "The following files are in git but not the distribution:"; \ cat missing-distfiles; \ exit 1; \ fi; \ if LC_ALL=C grep '\.gitignore$$' distfiles; then \ echo "See above for list of files that are distributed but"; \ echo "should not be."; \ exit 1; \ fi \ fi CLEANFILES += distfiles all-gitfiles missing-distfiles # The following is based on commands for the Automake "distdir" target. distfiles: Makefile @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t" | \ LC_ALL=C sort -u > $@ CLEANFILES += distfiles .PHONY: dist-hook-git # Check that every .c file includes . ALL_LOCAL += config-h-check 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 -v $(submodules) | grep '\.c$$' | \ grep -vE '^python'`; \ 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 # Check for printf() type modifiers that MSVC doesn't support. ALL_LOCAL += printf-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 -v $(submodules) | grep '\.[ch]$$'`; \ then \ echo "See above for list of violations of the rule that"; \ echo "'z', 't', 'j', 'hh' printf() type modifiers are"; \ echo "forbidden. See coding-style.rst for replacements."; \ exit 1; \ fi .PHONY: printf-check # Check that certain data structures are always declared "static". ALL_LOCAL += static-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 that assert.h is not used outside a whitelist of files. ALL_LOCAL += check-assert-h-usage 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 '^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 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.) ALL_LOCAL += check-endian 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'); \ 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 ALL_LOCAL += check-echo-n check-echo-n: @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1 && \ git --no-pager grep -n 'echo'' -n' $(srcdir); \ then \ echo "See above for uses for \"echo"" -n\", which is non-POSIX"; \ echo "and does not work with all shells. Use \"printf\" instead."; \ exit 1; \ fi .PHONY: check-echo-n ALL_LOCAL += check-tabs check-tabs: @cd $(srcdir); \ if test -e .git && (git --version) >/dev/null 2>&1 && \ grep -ln "^ " \ `git ls-files | grep -v $(submodules) \ | grep -v -f build-aux/initial-tab-whitelist` /dev/null \ | $(EGREP) -v ':[ ]*/?\*'; \ then \ echo "See above for files that use tabs for indentation."; \ echo "Please use spaces instead."; \ exit 1; \ fi .PHONY: check-tabs ALL_LOCAL += thread-safety-check 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 -v $(submodules) | grep '\.[ch]$$'` /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 EXTRA_DIST += build-aux/thread-safety-blacklist .PHONY: thread-safety-check # Check that "ip" is used in preference to "ifconfig", because # "ifconfig" is not installed ubiquitously anymore. ALL_LOCAL += check-ifconfig check-ifconfig: @if test -e $(srcdir)/.git && (git --version) >/dev/null 2>&1 && \ (cd $(srcdir) && git --no-pager grep -l -E -e 'ifconfig' | \ $(EGREP) -v 'Makefile.am|ovs-vsctl-bashcomp|openvswitch-custom\.te'); \ then \ echo "See above for list of files that use or reference"; \ echo "'ifconfig'. Please use 'ip' instead."; \ exit 1; \ fi .PHONY: check-ifconfig clang-analyze: clean @which clang scan-build >/dev/null 2>&1 || \ (echo "Unable to find clang/scan-build, Install clang,clang-analyzer packages"; exit 1) @$(MKDIR_P) "$(srcdir)/tests/clang-analyzer-results" @scan-build -o $(srcdir)/tests/clang-analyzer-results --use-cc=$(CC) $(MAKE) .PHONY: clang-analyze 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) dist-docs: VERSION=$(VERSION) MAKE='$(MAKE)' $(srcdir)/build-aux/dist-docs $(srcdir) $(docs) .PHONY: dist-docs include automake.mk include Documentation/automake.mk include m4/automake.mk include include/automake.mk include lib/automake.mk include tests/automake.mk include build-aux/automake.mk include utilities/automake.mk ovn-vif-25.09.0~git20250813.23884f5/NEWS000066400000000000000000000024221476622600000164260ustar00rootroot00000000000000Post v25.03.0 ------------- OVN VIF v25.03.0 - 18 Mar 2025 ------------------------------ OVN VIF v24.09.0 - 16 Sep 2024 ------------------------------ OVN VIF v24.03.0 - 04 Mar 2024 ------------------------------ OVN VIF v23.09.0 - 18 Sep 2023 ------------------------------ - Log reason for failure to initialize udev monitoring and lower the severity of logging on failure to set udev recv buffer size. OVN VIF v23.03.0 - 06 Mar 2023 ------------------------------ OVN VIF v22.12.0 - 19 Dec 2022 ------------------------------ OVN VIF v22.09.0 - 19 Sep 2022 ------------------------------ OVN VIF v22.06.0 - 06 Jul 2022 ------------------------------ OVN VIF v22.03.0 - 11 Mar 2022 ------------------------------ - Introduced runtime update of lookup tables. Before this change lookup tables were populated on initial startup of the ovn-controller only, and as such any representors created after ovn-controller startup would not be available until restart of the ovn-controller. Systems using systemd and udev should install libudev header- and library- files prior to compiling ovn-vif to enable handling of systemd predictable network interface name functionality. OVN VIF v21.12.0 - 23 Dec 2021 ------------------------------ - Initial release. ovn-vif-25.09.0~git20250813.23884f5/README.rst000066400000000000000000000033261476622600000174220ustar00rootroot00000000000000.. Copyright (c) 2021 Canonical 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. Convention for heading levels in OVN documentation: ======= Heading 0 (reserved for the title in a document) ------- Heading 1 ~~~~~~~ Heading 2 +++++++ Heading 3 ''''''' Heading 4 Avoid deeper levels because they do not render well. ======= OVN VIF ======= What is OVN VIF? ---------------- The OVN VIF repository contains OVN VIF plug provider implementations. For more information, please refer to the `OVN VIF Plug Providers`_ page which is part of the `OVN Deep Dive`_ section of the `OVN Documentation`_. What's here? ------------ Have a look at each individual `VIF plug provider implementation documentation `__ for details on usage and available options. License ------- OVN VIF is licensed under the open source Apache 2 license. Contact ------- bugs@openvswitch.org .. LINKS .. _OVN VIF Plug Providers: https://docs.ovn.org/en/latest/topics/vif-plug-providers/vif-plug-providers.html .. _OVN Deep Dive: https://docs.ovn.org/en/latest/topics/index.html .. _OVN Documentation: https://docs.ovn.org/en/latest/index.html ovn-vif-25.09.0~git20250813.23884f5/acinclude.m4000066400000000000000000000370031476622600000201230ustar00rootroot00000000000000# -*- autoconf -*- # Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 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. dnl OVS_ENABLE_WERROR AC_DEFUN([OVS_ENABLE_WERROR], [AC_ARG_ENABLE( [Werror], [AC_HELP_STRING([--enable-Werror], [Add -Werror to CFLAGS])], [], [enable_Werror=no]) AC_CONFIG_COMMANDS_PRE( [if test "X$enable_Werror" = Xyes; then OVS_CFLAGS="$OVS_CFLAGS -Werror" fi]) # Unless --enable-Werror is specified, report but do not fail the build # for errors reported by flake8. if test "X$enable_Werror" = Xyes; then FLAKE8_WERROR= else FLAKE8_WERROR=- fi AC_SUBST([FLAKE8_WERROR]) # If --enable-Werror is specified, fail the build on sparse warnings. if test "X$enable_Werror" = Xyes; then SPARSE_WERROR=-Wsparse-error else SPARSE_WERROR= fi AC_SUBST([SPARSE_WERROR])]) dnl Checks for net/if_dl.h. dnl dnl (We use this as a proxy for checking whether we're building on FreeBSD dnl or NetBSD.) AC_DEFUN([OVS_CHECK_IF_DL], [AC_CHECK_HEADER([net/if_dl.h], [HAVE_IF_DL=yes], [HAVE_IF_DL=no]) AM_CONDITIONAL([HAVE_IF_DL], [test "$HAVE_IF_DL" = yes]) if test "$HAVE_IF_DL" = yes; then AC_DEFINE([HAVE_IF_DL], [1], [Define to 1 if net/if_dl.h is available.]) # On these platforms we use libpcap to access network devices. AC_SEARCH_LIBS([pcap_open_live], [pcap]) fi]) dnl Checks for buggy strtok_r. dnl dnl Some versions of glibc 2.7 has a bug in strtok_r when compiling dnl with optimization that can cause segfaults: dnl dnl http://sources.redhat.com/bugzilla/show_bug.cgi?id=5614. AC_DEFUN([OVS_CHECK_STRTOK_R], [AC_CACHE_CHECK( [whether strtok_r macro segfaults on some inputs], [ovs_cv_strtok_r_bug], [AC_RUN_IFELSE( [AC_LANG_PROGRAM([#include #include ], [[#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 /* Assume bug is present, because relatively minor changes in compiler settings (e.g. optimization level) can make it crop up. */ return 1; #else char string[] = ":::"; char *save_ptr = (char *) 0xc0ffee; char *token1, *token2; token1 = strtok_r(string, ":", &save_ptr); token2 = strtok_r(NULL, ":", &save_ptr); freopen ("/dev/null", "w", stdout); printf ("%s %s\n", token1, token2); return 0; #endif ]])], [ovs_cv_strtok_r_bug=no], [ovs_cv_strtok_r_bug=yes], [ovs_cv_strtok_r_bug=yes])]) if test $ovs_cv_strtok_r_bug = yes; then AC_DEFINE([HAVE_STRTOK_R_BUG], [1], [Define if strtok_r macro segfaults on some inputs]) fi ]) dnl ---------------------------------------------------------------------- dnl These macros are from GNU PSPP, with the following original license: dnl Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. AC_DEFUN([_OVS_CHECK_CC_OPTION], [dnl m4_define([ovs_cv_name], [ovs_cv_[]m4_translit([$1], [-= ], [__])])dnl AC_CACHE_CHECK([whether $CC accepts $1], [ovs_cv_name], [ovs_save_CFLAGS="$CFLAGS" dnl Include -Werror in the compiler options, because without -Werror dnl clang's GCC-compatible compiler driver does not return a failure dnl exit status even though it complains about options it does not dnl understand. dnl dnl Also, check stderr as gcc exits with status 0 for options dnl rejected at getopt level. dnl % touch /tmp/a.c dnl % gcc -g -c -Werror -Qunused-arguments /tmp/a.c; echo $? dnl gcc: unrecognized option '-Qunused-arguments' dnl 0 dnl % dnl dnl In addition, GCC does not complain about a -Wno- option that dnl it does not understand, unless it has another error to report, so dnl instead of testing for -Wno-, test for the positive version. CFLAGS="$CFLAGS $WERROR m4_bpatsubst([$1], [-Wno-], [-W])" AC_COMPILE_IFELSE( [AC_LANG_SOURCE([int x;])], [if test -s conftest.err && grep "unrecognized option" conftest.err then ovs_cv_name[]=no else ovs_cv_name[]=yes fi], [ovs_cv_name[]=no]) CFLAGS="$ovs_save_CFLAGS"]) if test $ovs_cv_name = yes; then m4_if([$2], [], [:], [$2]) else m4_if([$3], [], [:], [$3]) fi ]) dnl OVS_CHECK_WERROR dnl dnl Check whether the C compiler accepts -Werror. dnl Sets $WERROR to "-Werror", if so, and otherwise to the empty string. AC_DEFUN([OVS_CHECK_WERROR], [WERROR= _OVS_CHECK_CC_OPTION([-Werror], [WERROR=-Werror])]) dnl OVS_CHECK_CC_OPTION([OPTION], [ACTION-IF-ACCEPTED], [ACTION-IF-REJECTED]) dnl Check whether the given C compiler OPTION is accepted. dnl If so, execute ACTION-IF-ACCEPTED, otherwise ACTION-IF-REJECTED. AC_DEFUN([OVS_CHECK_CC_OPTION], [AC_REQUIRE([OVS_CHECK_WERROR]) _OVS_CHECK_CC_OPTION([$1], [$2], [$3])]) dnl OVS_ENABLE_OPTION([OPTION]) dnl Check whether the given C compiler OPTION is accepted. dnl If so, add it to WARNING_FLAGS. dnl Example: OVS_ENABLE_OPTION([-Wdeclaration-after-statement]) AC_DEFUN([OVS_ENABLE_OPTION], [OVS_CHECK_CC_OPTION([$1], [WARNING_FLAGS="$WARNING_FLAGS $1"]) AC_SUBST([WARNING_FLAGS])]) dnl OVS_CONDITIONAL_CC_OPTION([OPTION], [CONDITIONAL]) dnl Check whether the given C compiler OPTION is accepted. dnl If so, enable the given Automake CONDITIONAL. dnl Example: OVS_CONDITIONAL_CC_OPTION([-Wno-unused], [HAVE_WNO_UNUSED]) AC_DEFUN([OVS_CONDITIONAL_CC_OPTION], [OVS_CHECK_CC_OPTION( [$1], [ovs_have_cc_option=yes], [ovs_have_cc_option=no]) AM_CONDITIONAL([$2], [test $ovs_have_cc_option = yes])]) dnl ---------------------------------------------------------------------- dnl OVS_CHECK_SPARSE_TARGET dnl dnl The "cgcc" script from "sparse" isn't very good at detecting the dnl target for which the code is being built. This helps it out. AC_DEFUN([OVS_CHECK_SPARSE_TARGET], [AC_CACHE_CHECK( [target hint for cgcc], [ac_cv_sparse_target], [AS_CASE([`$CC -dumpmachine 2>/dev/null`], [i?86-* | athlon-*], [ac_cv_sparse_target=x86], [x86_64-*], [ac_cv_sparse_target=x86_64], [ac_cv_sparse_target=other])]) AS_CASE([$ac_cv_sparse_target], [x86], [SPARSEFLAGS= CGCCFLAGS=-target=i86], [x86_64], [SPARSEFLAGS=-m64 CGCCFLAGS=-target=x86_64], [SPARSEFLAGS= CGCCFLAGS=]) AC_SUBST([SPARSEFLAGS]) AC_SUBST([CGCCFLAGS])]) dnl OVS_SPARSE_EXTRA_INCLUDES dnl dnl The cgcc script from "sparse" does not search gcc's default dnl search path. Get the default search path from GCC and pass dnl them to sparse. AC_DEFUN([OVS_SPARSE_EXTRA_INCLUDES], AC_SUBST([SPARSE_EXTRA_INCLUDES], [`$CC -v -E - &1 >/dev/null | sed -n -e '/^#include.*search.*starts.*here:/,/^End.*of.*search.*list\./s/^ \(.*\)/-I \1/p' |grep -v /usr/lib | grep -x -v '\-I /usr/include' | tr \\\n ' ' `] )) dnl OVS_ENABLE_SPARSE AC_DEFUN([OVS_ENABLE_SPARSE], [AC_REQUIRE([OVS_CHECK_SPARSE_TARGET]) AC_REQUIRE([OVS_SPARSE_EXTRA_INCLUDES]) : ${SPARSE=sparse} AC_SUBST([SPARSE]) AC_CONFIG_COMMANDS_PRE( [CC='$(if $(C:0=),env REAL_CC="'"$CC"'" CHECK="$(SPARSE) $(SPARSE_WERROR) -I $(ovs_srcdir)/include/sparse $(SPARSEFLAGS) $(SPARSE_EXTRA_INCLUDES) " cgcc $(CGCCFLAGS),'"$CC"')']) AC_ARG_ENABLE( [sparse], [AC_HELP_STRING([--enable-sparse], [Run "sparse" by default])], [], [enable_sparse=no]) AM_CONDITIONAL([ENABLE_SPARSE_BY_DEFAULT], [test $enable_sparse = yes])]) dnl OVS_CTAGS_IDENTIFIERS dnl dnl ctags ignores symbols with extras identifiers. This builds a list of dnl specially handled identifiers to be ignored. AC_DEFUN([OVS_CTAGS_IDENTIFIERS], AC_SUBST([OVS_CTAGS_IDENTIFIERS_LIST], [`printf %s '-I "'; sed -n 's/^#define \(OVS_[A-Z_]\+\)(\.\.\.)$/\1+/p' ${OVSDIR}/include/openvswitch/compiler.h | tr \\\n ' ' ; printf '"'`] )) dnl OVS_PTHREAD_SET_NAME dnl dnl This checks for three known variants of pthreads functions for setting dnl the name of the current thread: dnl dnl glibc: int pthread_setname_np(pthread_t, const char *name); dnl NetBSD: int pthread_setname_np(pthread_t, const char *format, void *arg); dnl FreeBSD: int pthread_set_name_np(pthread_t, const char *name); dnl dnl For glibc and FreeBSD, the arguments are just a thread and its name. For dnl NetBSD, 'format' is a printf() format string and 'arg' is an argument to dnl provide to it. dnl dnl This macro defines: dnl dnl glibc: HAVE_GLIBC_PTHREAD_SETNAME_NP dnl NetBSD: HAVE_NETBSD_PTHREAD_SETNAME_NP dnl FreeBSD: HAVE_PTHREAD_SET_NAME_NP AC_DEFUN([OVS_CHECK_PTHREAD_SET_NAME], [AC_CHECK_FUNCS([pthread_set_name_np]) if test $ac_cv_func_pthread_set_name_np != yes; then AC_CACHE_CHECK( [for pthread_setname_np() variant], [ovs_cv_pthread_setname_np], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include ], [pthread_setname_np(pthread_self(), "name");])], [ovs_cv_pthread_setname_np=glibc], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include ], [pthread_setname_np(pthread_self(), "%s", "name");])], [ovs_cv_pthread_setname_np=netbsd], [ovs_cv_pthread_setname_np=none])])]) case $ovs_cv_pthread_setname_np in # ( glibc) AC_DEFINE( [HAVE_GLIBC_PTHREAD_SETNAME_NP], [1], [Define to 1 if pthread_setname_np() is available and takes 2 parameters (like glibc).]) ;; # ( netbsd) AC_DEFINE( [HAVE_NETBSD_PTHREAD_SETNAME_NP], [1], [Define to 1 if pthread_setname_np() is available and takes 3 parameters (like NetBSD).]) ;; esac fi]) dnl OVS_CHECK_LINUX_HOST. dnl dnl Checks whether we're building for a Linux host, based on the presence of dnl the __linux__ preprocessor symbol, and sets up an Automake conditional dnl LINUX based on the result. AC_DEFUN([OVS_CHECK_LINUX_HOST], [AC_CACHE_CHECK( [whether __linux__ is defined], [ovs_cv_linux], [AC_COMPILE_IFELSE( [AC_LANG_PROGRAM([enum { LINUX = __linux__};], [])], [ovs_cv_linux=true], [ovs_cv_linux=false])]) AM_CONDITIONAL([LINUX], [$ovs_cv_linux])]) dnl OVN_VIF_CHECK_OVS dnl dnl Check for OVS sources AC_DEFUN([OVN_VIF_CHECK_OVS], [ AC_ARG_WITH([ovs-source], [AC_HELP_STRING([--with-ovs-source=/path/to/ovs/src/dir], [Specify the OVS src directory])]) AC_ARG_WITH([ovs-build], [AC_HELP_STRING([--with-ovs-build=/path/to/ovs/build/dir], [Specify the OVS build directory])]) AC_MSG_CHECKING([for OVS source directory]) if test X"$with_ovs_source" = X; then with_ovs_source="$srcdir/ovs" fi OVSDIR=$(cd "$(eval echo "$with_ovs_source")"; pwd) if test ! -f "$OVSDIR/vswitchd/bridge.c"; then AC_ERROR([$OVSDIR is not an OVS source directory]) fi AC_MSG_RESULT([$OVSDIR]) AC_SUBST(OVSDIR) AC_MSG_CHECKING([for OVS build directory]) if test X"$with_ovs_build" != X; then OVSBUILDDIR=`eval echo "$with_ovs_build"` case $OVSBUILDDIR in /*) ;; *) OVSBUILDDIR=`pwd`/$OVSBUILDDIR ;; esac if test ! -f "$OVSBUILDDIR/config.h"; then AC_ERROR([$OVSBUILDDIR is not a configured OVS build directory]) fi elif test -f "$OVSDIR/config.h"; then # If separate build dir is not specified, use src dir. OVSBUILDDIR=$OVSDIR else AC_ERROR([OVS source dir $OVSDIR is not configured as a build directory (either run configure there or use --with-ovs-build to point to the build directory)]) fi AC_MSG_RESULT([$OVSBUILDDIR]) AC_SUBST(OVSBUILDDIR) OVSVERSION=`sed -n 's/^#define PACKAGE_VERSION//p' $OVSBUILDDIR/config.h | tr \\\n ' ' | sed 's/^[ \t]*//;s/[ \t]*$//' | sed 's/\"//g'` AC_SUBST(OVSVERSION) AC_MSG_CHECKING([OVS version]) AC_MSG_RESULT([$OVSVERSION]) ]) dnl OVN_VIF_CHECK_OVN dnl dnl Check for OVN sources AC_DEFUN([OVN_VIF_CHECK_OVN], [ AC_ARG_WITH([ovn-source], [AC_HELP_STRING([--with-ovn-source=/path/to/ovn/src/dir], [Specify the OVN src directory])]) AC_ARG_WITH([ovn-build], [AC_HELP_STRING([--with-ovn-build=/path/to/ovn/build/dir], [Specify the OVN build directory])]) AC_MSG_CHECKING([for OVN source directory]) if test X"$with_ovn_source" = X; then with_ovn_source="$srcdir/ovn" fi OVNDIR=$(cd "$(eval echo "$with_ovn_source")"; pwd) if test ! -f "$OVNDIR/lib/vif-plug-provider.c"; then AC_ERROR([$OVNDIR is not an OVN source directory]) fi AC_MSG_RESULT([$OVNDIR]) AC_SUBST(OVNDIR) AC_MSG_CHECKING([for OVN build directory]) if test X"$with_ovn_build" != X; then OVNBUILDDIR=`eval echo "$with_ovn_build"` case $OVNBUILDDIR in /*) ;; *) OVNBUILDDIR=`pwd`/$OVNBUILDDIR ;; esac if test ! -f "$OVNBUILDDIR/config.h"; then AC_ERROR([$OVNBUILDDIR is not a configured OVN build directory]) fi elif test -f "$OVNDIR/config.h"; then # If separate build dir is not specified, use src dir. OVNBUILDDIR=$OVNDIR else AC_ERROR([OVN source dir $OVNDIR is not configured as a build directory (either run configure there or use --with-ovn-build to point to the build directory)]) fi AC_MSG_RESULT([$OVNBUILDDIR]) AC_SUBST(OVNBUILDDIR) OVNVERSION=`sed -n 's/^#define PACKAGE_VERSION//p' $OVNBUILDDIR/config.h | tr \\\n ' ' | sed 's/^[ \t]*//;s/[ \t]*$//' | sed 's/\"//g'` AC_SUBST(OVNVERSION) AC_MSG_CHECKING([OVN version]) AC_MSG_RESULT([$OVNVERSION]) ]) dnl OVS_CHECK_LINUX_NETLINK dnl dnl Configure Linux netlink compat. AC_DEFUN([OVS_CHECK_LINUX_NETLINK], [ AC_COMPILE_IFELSE([ AC_LANG_PROGRAM([#include ], [ struct nla_bitfield32 x = { 0 }; ])], [AC_DEFINE([HAVE_NLA_BITFIELD32], [1], [Define to 1 if struct nla_bitfield32 is available.])]) ]) dnl OVN_VIF_CHECK_UDEV dnl dnl Check for udev enabled system AC_DEFUN([OVN_VIF_CHECK_UDEV], [ PKG_CHECK_MODULES([UDEV], [libudev], [AC_DEFINE([HAVE_UDEV], [1], [Use UDEV])]) AM_CONDITIONAL(HAVE_UDEV, test x$HAVE_UDEV=xyes) ]) dnl OVN_VIF_ENABLE_PLUG_REPRESENTOR dnl dnl Enable the representor plug provider AC_DEFUN([OVN_VIF_ENABLE_PLUG_REPRESENTOR], [ AC_ARG_ENABLE( [plug-representor], [AC_HELP_STRING([--enable-plug-representor], [Enable the representor plug provider])], [], [enable_plug_representor=no]) AM_CONDITIONAL([ENABLE_PLUG_REPRESENTOR], [test "$enable_plug_representor" != no]) if test "$enable_plug" != no; then AC_DEFINE([ENABLE_PLUG_REPRESENTOR], [1], [Build the representor plug provider]) fi ]) ovn-vif-25.09.0~git20250813.23884f5/automake.mk000066400000000000000000000001471476622600000200700ustar00rootroot00000000000000DISTCLEANFILES += \ Makefile.in \ config.h \ config.h.in \ config.h.in~ \ configure \ package.m4 ovn-vif-25.09.0~git20250813.23884f5/boot.sh000077500000000000000000000000501476622600000172240ustar00rootroot00000000000000#! /bin/sh autoreconf --install --force ovn-vif-25.09.0~git20250813.23884f5/build-aux/000077500000000000000000000000001476622600000176215ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/build-aux/.gitattributes000066400000000000000000000000161476622600000225110ustar00rootroot00000000000000* text eol=lf ovn-vif-25.09.0~git20250813.23884f5/build-aux/.gitignore000066400000000000000000000001141476622600000216050ustar00rootroot00000000000000/compile /config.guess /config.sub /depcomp /install-sh /ltmain.sh /missing ovn-vif-25.09.0~git20250813.23884f5/build-aux/automake.mk000066400000000000000000000001261476622600000217570ustar00rootroot00000000000000EXTRA_DIST += \ build-aux/initial-tab-whitelist \ build-aux/thread-safety-blacklist ovn-vif-25.09.0~git20250813.23884f5/build-aux/initial-tab-whitelist000066400000000000000000000001011476622600000237430ustar00rootroot00000000000000\.am$ \.m4$ \.mk$ Documentation/_static/logo.png ^include/linux/ ovn-vif-25.09.0~git20250813.23884f5/build-aux/thread-safety-blacklist000066400000000000000000000021431476622600000242520ustar00rootroot00000000000000\basctime( \bbasename( \bcatgets( \bcrypt( \bctermid( \bctime( \bdbm_clearerr( \bdbm_close( \bdbm_delete( \bdbm_error( \bdbm_fetch( \bdbm_firstkey( \bdbm_nextkey( \bdbm_open( \bdbm_store( \bdirname( \bdlerror( \bdrand48( \becvt( \bencrypt( \bendgrent( \bendpwent( \bendutxent( \bfcvt( \bftw( \bgcvt( \bgetc_unlocked( \bgetchar_unlocked( \bgetdate( \bgetgrent( \bgetgrgid( \bgetgrnam( \bgethostbyaddr( \bgethostbyname( \bgethostent( \bgetlogin( \bgetmntent( \bgetnetbyaddr( \bgetnetbyname( \bgetnetent( \bgetprotobyname( \bgetprotobynumber( \bgetprotoent( \bgetpwent( \bgetpwnam( \bgetpwuid( \bgetservbyname( \bgetservbyport( \bgetservent( \bgetutxent( \bgetutxid( \bgetutxline( \bgmtime( \bhcreate( \bhdestroy( \bhsearch( \binet_ntoa( \bl64a( \blgamma( \blgammaf( \blgammal( \blocaleconv( \blocaltime( \blrand48( \bmrand48( \bnftw( \bnl_langinfo( \bptsname( \bputc_unlocked( \bputchar_unlocked( \bputenv( \bpututxline( \brand( \bsetenv( \bsetgrent( \bsetkey( \bsetpwent( \bsetutxent( \bsigprocmask( \bstrerror( \bstrsignal( \bstrtok( \bsystem( \btmpnam( \bttyname( \bunsetenv( \bwcrtomb( \bwcsrtombs( \bwcstombs( \bwctomb( ovn-vif-25.09.0~git20250813.23884f5/configure.ac000066400000000000000000000143731476622600000202250ustar00rootroot00000000000000# Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 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(ovn-vif, 25.03.90, bugs@openvswitch.org) 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_CXX AC_PROG_CPP AC_PROG_MKDIR_P AC_PROG_FGREP AC_PROG_EGREP PKG_PROG_PKG_CONFIG 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([libovn_vif_lt_current], [0]) m4_define([libovn_vif_lt_revision], [0]) m4_define([libovn_vif_lt_age], [0]) LT_CURRENT=libovn_vif_lt_current AC_SUBST([LT_CURRENT]) LT_REVISION=libovn_vif_lt_revision AC_SUBST([LT_REVISION]) LT_AGE=libovn_vif_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_rwlock_tryrdlock], [pthread]) AC_SEARCH_LIBS([pthread_rwlockattr_destroy], [pthread]) AC_FUNC_STRERROR_R OVN_CHECK_COVERAGE OVS_CHECK_NDEBUG OVS_CHECK_NETLINK OVN_CHECK_LOGDIR OVN_CHECK_SPHINX OVS_CHECK_IF_DL OVS_CHECK_STRTOK_R AC_CHECK_DECLS([sys_siglist], [], [], [[#include ]]) AC_CHECK_DECLS([malloc_trim], [], [], [[#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_MEMBERS([struct mmsghdr.msg_len], [], [], [[#include ]]) AC_CHECK_MEMBERS([struct sockaddr_in6.sin6_scope_id], [], [], [[#include #include #include ]]) AC_CHECK_FUNCS([strnlen getloadavg statvfs getmntent_r sendmmsg clock_gettime]) AC_CHECK_HEADERS([mntent.h sys/statvfs.h linux/types.h linux/if_ether.h]) AC_CHECK_HEADERS([linux/net_namespace.h stdatomic.h bits/floatn-common.h]) AC_CHECK_HEADERS([net/if_mib.h], [], [], [[#include #include ]]) 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 OVS_LIBTOOL_VERSIONS OVS_CHECK_CXX AX_FUNC_POSIX_MEMALIGN OVS_CHECK_INCLUDE_NEXT([stdio.h string.h]) AC_CONFIG_FILES([lib/libovn-vif.sym]) OVS_ENABLE_OPTION([-Wall]) OVS_ENABLE_OPTION([-Wextra]) OVS_ENABLE_OPTION([-Wno-sign-compare]) OVS_ENABLE_OPTION([-Wpointer-arith]) OVS_ENABLE_OPTION([-Wformat -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([-Wswitch-bool]) OVS_ENABLE_OPTION([-Wlogical-not-parentheses]) OVS_ENABLE_OPTION([-Wsizeof-array-argument]) OVS_ENABLE_OPTION([-Wbool-compare]) OVS_ENABLE_OPTION([-Wshift-negative-value]) OVS_ENABLE_OPTION([-Wduplicated-cond]) OVS_ENABLE_OPTION([-Qunused-arguments]) OVS_ENABLE_OPTION([-Wshadow]) OVS_ENABLE_OPTION([-Wmultistatement-macros]) OVS_ENABLE_OPTION([-Wcast-align=strict]) OVS_ENABLE_OPTION([-Wno-null-pointer-arithmetic]) OVS_ENABLE_OPTION([-Warray-bounds-pointer-arithmetic]) 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 OVS_CHECK_LINUX_NETLINK OVS_CHECK_PRAGMA_MESSAGE OVN_VIF_CHECK_OVS OVN_VIF_CHECK_OVN OVN_VIF_CHECK_UDEV OVN_VIF_ENABLE_PLUG_REPRESENTOR OVS_CTAGS_IDENTIFIERS AC_SUBST([OVS_CFLAGS]) AC_SUBST([OVS_LDFLAGS]) AC_SUBST([OVN_CFLAGS]) AC_SUBST([OVN_LDFLAGS]) AC_SUBST([ovs_srcdir], ['${OVSDIR}']) AC_SUBST([ovs_builddir], ['${OVSBUILDDIR}']) AC_SUBST([ovs_libdir], ['${OVSBUILDDIR}/lib']) AC_SUBST([ovsdb_libdir], ['${OVSBUILDDIR}/ovsdb']) AC_SUBST([ovs_mandir], ['${OVSDIR}']) AC_SUBST([ovn_srcdir], ['${OVNDIR}']) AC_SUBST([ovn_builddir], ['${OVNBUILDDIR}']) AC_SUBST([ovn_libdir], ['${OVNBUILDDIR}/lib']) AC_SUBST([ovn_mandir], ['${OVNDIR}']) AC_CONFIG_FILES(Makefile) AC_CONFIG_FILES(tests/atlocal) AC_CONFIG_FILES(include/ovn-vif/version.h) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) AC_OUTPUT ovn-vif-25.09.0~git20250813.23884f5/include/000077500000000000000000000000001476622600000173525ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/include/automake.mk000066400000000000000000000000421476622600000215050ustar00rootroot00000000000000include include/linux/automake.mk ovn-vif-25.09.0~git20250813.23884f5/include/linux/000077500000000000000000000000001476622600000205115ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/include/linux/automake.mk000066400000000000000000000000551476622600000226500ustar00rootroot00000000000000noinst_HEADERS += \ include/linux/devlink.h ovn-vif-25.09.0~git20250813.23884f5/include/linux/devlink.h000066400000000000000000000500551476622600000223230ustar00rootroot00000000000000/* * The kernel devlink interface has gained a number of additions in recent * kernel versions. To allow Open vSwitch to consume these interfaces in its * runtime environment regardless of what kernel version was available at build * time, and also avoiding an elaborate set of autoconf macros to check for * presence of individual pieces, we include the entire file here. * * Source: * https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/devlink.h @ a556dded9c23c51c82654f1ebe389cbc0bc22057 */ #if !defined(__KERNEL__) #ifndef __UAPI_LINUX_DEVLINK_WRAPPER_H #define __UAPI_LINUX_DEVLINK_WRAPPER_H 1 /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ /* * include/uapi/linux/devlink.h - Network physical device Netlink interface * Copyright (c) 2016 Mellanox Technologies. All rights reserved. * Copyright (c) 2016 Jiri Pirko * * This program is free software; you can 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 of the License, or * (at your option) any later version. */ #ifndef _UAPI_LINUX_DEVLINK_H_ #define _UAPI_LINUX_DEVLINK_H_ #include #define DEVLINK_GENL_NAME "devlink" #define DEVLINK_GENL_VERSION 0x1 #define DEVLINK_GENL_MCGRP_CONFIG_NAME "config" enum devlink_command { /* don't change the order or add anything between, this is ABI! */ DEVLINK_CMD_UNSPEC, DEVLINK_CMD_GET, /* can dump */ DEVLINK_CMD_SET, DEVLINK_CMD_NEW, DEVLINK_CMD_DEL, DEVLINK_CMD_PORT_GET, /* can dump */ DEVLINK_CMD_PORT_SET, DEVLINK_CMD_PORT_NEW, DEVLINK_CMD_PORT_DEL, DEVLINK_CMD_PORT_SPLIT, DEVLINK_CMD_PORT_UNSPLIT, DEVLINK_CMD_SB_GET, /* can dump */ DEVLINK_CMD_SB_SET, DEVLINK_CMD_SB_NEW, DEVLINK_CMD_SB_DEL, DEVLINK_CMD_SB_POOL_GET, /* can dump */ DEVLINK_CMD_SB_POOL_SET, DEVLINK_CMD_SB_POOL_NEW, DEVLINK_CMD_SB_POOL_DEL, DEVLINK_CMD_SB_PORT_POOL_GET, /* can dump */ DEVLINK_CMD_SB_PORT_POOL_SET, DEVLINK_CMD_SB_PORT_POOL_NEW, DEVLINK_CMD_SB_PORT_POOL_DEL, DEVLINK_CMD_SB_TC_POOL_BIND_GET, /* can dump */ DEVLINK_CMD_SB_TC_POOL_BIND_SET, DEVLINK_CMD_SB_TC_POOL_BIND_NEW, DEVLINK_CMD_SB_TC_POOL_BIND_DEL, /* Shared buffer occupancy monitoring commands */ DEVLINK_CMD_SB_OCC_SNAPSHOT, DEVLINK_CMD_SB_OCC_MAX_CLEAR, DEVLINK_CMD_ESWITCH_GET, #define DEVLINK_CMD_ESWITCH_MODE_GET /* obsolete, never use this! */ \ DEVLINK_CMD_ESWITCH_GET DEVLINK_CMD_ESWITCH_SET, #define DEVLINK_CMD_ESWITCH_MODE_SET /* obsolete, never use this! */ \ DEVLINK_CMD_ESWITCH_SET DEVLINK_CMD_DPIPE_TABLE_GET, DEVLINK_CMD_DPIPE_ENTRIES_GET, DEVLINK_CMD_DPIPE_HEADERS_GET, DEVLINK_CMD_DPIPE_TABLE_COUNTERS_SET, DEVLINK_CMD_RESOURCE_SET, DEVLINK_CMD_RESOURCE_DUMP, /* Hot driver reload, makes configuration changes take place. The * devlink instance is not released during the process. */ DEVLINK_CMD_RELOAD, DEVLINK_CMD_PARAM_GET, /* can dump */ DEVLINK_CMD_PARAM_SET, DEVLINK_CMD_PARAM_NEW, DEVLINK_CMD_PARAM_DEL, DEVLINK_CMD_REGION_GET, DEVLINK_CMD_REGION_SET, DEVLINK_CMD_REGION_NEW, DEVLINK_CMD_REGION_DEL, DEVLINK_CMD_REGION_READ, DEVLINK_CMD_PORT_PARAM_GET, /* can dump */ DEVLINK_CMD_PORT_PARAM_SET, DEVLINK_CMD_PORT_PARAM_NEW, DEVLINK_CMD_PORT_PARAM_DEL, DEVLINK_CMD_INFO_GET, /* can dump */ DEVLINK_CMD_HEALTH_REPORTER_GET, DEVLINK_CMD_HEALTH_REPORTER_SET, DEVLINK_CMD_HEALTH_REPORTER_RECOVER, DEVLINK_CMD_HEALTH_REPORTER_DIAGNOSE, DEVLINK_CMD_HEALTH_REPORTER_DUMP_GET, DEVLINK_CMD_HEALTH_REPORTER_DUMP_CLEAR, DEVLINK_CMD_FLASH_UPDATE, DEVLINK_CMD_FLASH_UPDATE_END, /* notification only */ DEVLINK_CMD_FLASH_UPDATE_STATUS, /* notification only */ DEVLINK_CMD_TRAP_GET, /* can dump */ DEVLINK_CMD_TRAP_SET, DEVLINK_CMD_TRAP_NEW, DEVLINK_CMD_TRAP_DEL, DEVLINK_CMD_TRAP_GROUP_GET, /* can dump */ DEVLINK_CMD_TRAP_GROUP_SET, DEVLINK_CMD_TRAP_GROUP_NEW, DEVLINK_CMD_TRAP_GROUP_DEL, DEVLINK_CMD_TRAP_POLICER_GET, /* can dump */ DEVLINK_CMD_TRAP_POLICER_SET, DEVLINK_CMD_TRAP_POLICER_NEW, DEVLINK_CMD_TRAP_POLICER_DEL, DEVLINK_CMD_HEALTH_REPORTER_TEST, /* add new commands above here */ __DEVLINK_CMD_MAX, DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 }; enum devlink_port_type { DEVLINK_PORT_TYPE_NOTSET, DEVLINK_PORT_TYPE_AUTO, DEVLINK_PORT_TYPE_ETH, DEVLINK_PORT_TYPE_IB, }; enum devlink_sb_pool_type { DEVLINK_SB_POOL_TYPE_INGRESS, DEVLINK_SB_POOL_TYPE_EGRESS, }; /* static threshold - limiting the maximum number of bytes. * dynamic threshold - limiting the maximum number of bytes * based on the currently available free space in the shared buffer pool. * In this mode, the maximum quota is calculated based * on the following formula: * max_quota = alpha / (1 + alpha) * Free_Buffer * While Free_Buffer is the amount of none-occupied buffer associated to * the relevant pool. * The value range which can be passed is 0-20 and serves * for computation of alpha by following formula: * alpha = 2 ^ (passed_value - 10) */ enum devlink_sb_threshold_type { DEVLINK_SB_THRESHOLD_TYPE_STATIC, DEVLINK_SB_THRESHOLD_TYPE_DYNAMIC, }; #define DEVLINK_SB_THRESHOLD_TO_ALPHA_MAX 20 enum devlink_eswitch_mode { DEVLINK_ESWITCH_MODE_LEGACY, DEVLINK_ESWITCH_MODE_SWITCHDEV, }; enum devlink_eswitch_inline_mode { DEVLINK_ESWITCH_INLINE_MODE_NONE, DEVLINK_ESWITCH_INLINE_MODE_LINK, DEVLINK_ESWITCH_INLINE_MODE_NETWORK, DEVLINK_ESWITCH_INLINE_MODE_TRANSPORT, }; enum devlink_eswitch_encap_mode { DEVLINK_ESWITCH_ENCAP_MODE_NONE, DEVLINK_ESWITCH_ENCAP_MODE_BASIC, }; enum devlink_port_flavour { DEVLINK_PORT_FLAVOUR_PHYSICAL, /* Any kind of a port physically * facing the user. */ DEVLINK_PORT_FLAVOUR_CPU, /* CPU port */ DEVLINK_PORT_FLAVOUR_DSA, /* Distributed switch architecture * interconnect port. */ DEVLINK_PORT_FLAVOUR_PCI_PF, /* Represents eswitch port for * the PCI PF. It is an internal * port that faces the PCI PF. */ DEVLINK_PORT_FLAVOUR_PCI_VF, /* Represents eswitch port * for the PCI VF. It is an internal * port that faces the PCI VF. */ DEVLINK_PORT_FLAVOUR_VIRTUAL, /* Any virtual port facing the user. */ DEVLINK_PORT_FLAVOUR_UNUSED, /* Port which exists in the switch, but * is not used in any way. */ DEVLINK_PORT_FLAVOUR_PCI_SF, /* Represents eswitch port * for the PCI SF. It is an internal * port that faces the PCI SF. */ }; enum devlink_param_cmode { DEVLINK_PARAM_CMODE_RUNTIME, DEVLINK_PARAM_CMODE_DRIVERINIT, DEVLINK_PARAM_CMODE_PERMANENT, /* Add new configuration modes above */ __DEVLINK_PARAM_CMODE_MAX, DEVLINK_PARAM_CMODE_MAX = __DEVLINK_PARAM_CMODE_MAX - 1 }; enum devlink_param_fw_load_policy_value { DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DRIVER, DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_FLASH, DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_DISK, DEVLINK_PARAM_FW_LOAD_POLICY_VALUE_UNKNOWN, }; enum devlink_param_reset_dev_on_drv_probe_value { DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_UNKNOWN, DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_ALWAYS, DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_NEVER, DEVLINK_PARAM_RESET_DEV_ON_DRV_PROBE_VALUE_DISK, }; enum { DEVLINK_ATTR_STATS_RX_PACKETS, /* u64 */ DEVLINK_ATTR_STATS_RX_BYTES, /* u64 */ DEVLINK_ATTR_STATS_RX_DROPPED, /* u64 */ __DEVLINK_ATTR_STATS_MAX, DEVLINK_ATTR_STATS_MAX = __DEVLINK_ATTR_STATS_MAX - 1 }; /* Specify what sections of a flash component can be overwritten when * performing an update. Overwriting of firmware binary sections is always * implicitly assumed to be allowed. * * Each section must be documented in * Documentation/networking/devlink/devlink-flash.rst * */ enum { DEVLINK_FLASH_OVERWRITE_SETTINGS_BIT, DEVLINK_FLASH_OVERWRITE_IDENTIFIERS_BIT, __DEVLINK_FLASH_OVERWRITE_MAX_BIT, DEVLINK_FLASH_OVERWRITE_MAX_BIT = __DEVLINK_FLASH_OVERWRITE_MAX_BIT - 1 }; #define DEVLINK_FLASH_OVERWRITE_SETTINGS _BITUL(DEVLINK_FLASH_OVERWRITE_SETTINGS_BIT) #define DEVLINK_FLASH_OVERWRITE_IDENTIFIERS _BITUL(DEVLINK_FLASH_OVERWRITE_IDENTIFIERS_BIT) #define DEVLINK_SUPPORTED_FLASH_OVERWRITE_SECTIONS \ (_BITUL(__DEVLINK_FLASH_OVERWRITE_MAX_BIT) - 1) /** * enum devlink_trap_action - Packet trap action. * @DEVLINK_TRAP_ACTION_DROP: Packet is dropped by the device and a copy is not * sent to the CPU. * @DEVLINK_TRAP_ACTION_TRAP: The sole copy of the packet is sent to the CPU. * @DEVLINK_TRAP_ACTION_MIRROR: Packet is forwarded by the device and a copy is * sent to the CPU. */ enum devlink_trap_action { DEVLINK_TRAP_ACTION_DROP, DEVLINK_TRAP_ACTION_TRAP, DEVLINK_TRAP_ACTION_MIRROR, }; /** * enum devlink_trap_type - Packet trap type. * @DEVLINK_TRAP_TYPE_DROP: Trap reason is a drop. Trapped packets are only * processed by devlink and not injected to the * kernel's Rx path. * @DEVLINK_TRAP_TYPE_EXCEPTION: Trap reason is an exception. Packet was not * forwarded as intended due to an exception * (e.g., missing neighbour entry) and trapped to * control plane for resolution. Trapped packets * are processed by devlink and injected to * the kernel's Rx path. * @DEVLINK_TRAP_TYPE_CONTROL: Packet was trapped because it is required for * the correct functioning of the control plane. * For example, an ARP request packet. Trapped * packets are injected to the kernel's Rx path, * but not reported to drop monitor. */ enum devlink_trap_type { DEVLINK_TRAP_TYPE_DROP, DEVLINK_TRAP_TYPE_EXCEPTION, DEVLINK_TRAP_TYPE_CONTROL, }; enum { /* Trap can report input port as metadata */ DEVLINK_ATTR_TRAP_METADATA_TYPE_IN_PORT, /* Trap can report flow action cookie as metadata */ DEVLINK_ATTR_TRAP_METADATA_TYPE_FA_COOKIE, }; enum devlink_reload_action { DEVLINK_RELOAD_ACTION_UNSPEC, DEVLINK_RELOAD_ACTION_DRIVER_REINIT, /* Driver entities re-instantiation */ DEVLINK_RELOAD_ACTION_FW_ACTIVATE, /* FW activate */ /* Add new reload actions above */ __DEVLINK_RELOAD_ACTION_MAX, DEVLINK_RELOAD_ACTION_MAX = __DEVLINK_RELOAD_ACTION_MAX - 1 }; enum devlink_reload_limit { DEVLINK_RELOAD_LIMIT_UNSPEC, /* unspecified, no constraints */ DEVLINK_RELOAD_LIMIT_NO_RESET, /* No reset allowed, no down time allowed, * no link flap and no configuration is lost. */ /* Add new reload limit above */ __DEVLINK_RELOAD_LIMIT_MAX, DEVLINK_RELOAD_LIMIT_MAX = __DEVLINK_RELOAD_LIMIT_MAX - 1 }; #define DEVLINK_RELOAD_LIMITS_VALID_MASK (_BITUL(__DEVLINK_RELOAD_LIMIT_MAX) - 1) enum devlink_attr { /* don't change the order or add anything between, this is ABI! */ DEVLINK_ATTR_UNSPEC, /* bus name + dev name together are a handle for devlink entity */ DEVLINK_ATTR_BUS_NAME, /* string */ DEVLINK_ATTR_DEV_NAME, /* string */ DEVLINK_ATTR_PORT_INDEX, /* u32 */ DEVLINK_ATTR_PORT_TYPE, /* u16 */ DEVLINK_ATTR_PORT_DESIRED_TYPE, /* u16 */ DEVLINK_ATTR_PORT_NETDEV_IFINDEX, /* u32 */ DEVLINK_ATTR_PORT_NETDEV_NAME, /* string */ DEVLINK_ATTR_PORT_IBDEV_NAME, /* string */ DEVLINK_ATTR_PORT_SPLIT_COUNT, /* u32 */ DEVLINK_ATTR_PORT_SPLIT_GROUP, /* u32 */ DEVLINK_ATTR_SB_INDEX, /* u32 */ DEVLINK_ATTR_SB_SIZE, /* u32 */ DEVLINK_ATTR_SB_INGRESS_POOL_COUNT, /* u16 */ DEVLINK_ATTR_SB_EGRESS_POOL_COUNT, /* u16 */ DEVLINK_ATTR_SB_INGRESS_TC_COUNT, /* u16 */ DEVLINK_ATTR_SB_EGRESS_TC_COUNT, /* u16 */ DEVLINK_ATTR_SB_POOL_INDEX, /* u16 */ DEVLINK_ATTR_SB_POOL_TYPE, /* u8 */ DEVLINK_ATTR_SB_POOL_SIZE, /* u32 */ DEVLINK_ATTR_SB_POOL_THRESHOLD_TYPE, /* u8 */ DEVLINK_ATTR_SB_THRESHOLD, /* u32 */ DEVLINK_ATTR_SB_TC_INDEX, /* u16 */ DEVLINK_ATTR_SB_OCC_CUR, /* u32 */ DEVLINK_ATTR_SB_OCC_MAX, /* u32 */ DEVLINK_ATTR_ESWITCH_MODE, /* u16 */ DEVLINK_ATTR_ESWITCH_INLINE_MODE, /* u8 */ DEVLINK_ATTR_DPIPE_TABLES, /* nested */ DEVLINK_ATTR_DPIPE_TABLE, /* nested */ DEVLINK_ATTR_DPIPE_TABLE_NAME, /* string */ DEVLINK_ATTR_DPIPE_TABLE_SIZE, /* u64 */ DEVLINK_ATTR_DPIPE_TABLE_MATCHES, /* nested */ DEVLINK_ATTR_DPIPE_TABLE_ACTIONS, /* nested */ DEVLINK_ATTR_DPIPE_TABLE_COUNTERS_ENABLED, /* u8 */ DEVLINK_ATTR_DPIPE_ENTRIES, /* nested */ DEVLINK_ATTR_DPIPE_ENTRY, /* nested */ DEVLINK_ATTR_DPIPE_ENTRY_INDEX, /* u64 */ DEVLINK_ATTR_DPIPE_ENTRY_MATCH_VALUES, /* nested */ DEVLINK_ATTR_DPIPE_ENTRY_ACTION_VALUES, /* nested */ DEVLINK_ATTR_DPIPE_ENTRY_COUNTER, /* u64 */ DEVLINK_ATTR_DPIPE_MATCH, /* nested */ DEVLINK_ATTR_DPIPE_MATCH_VALUE, /* nested */ DEVLINK_ATTR_DPIPE_MATCH_TYPE, /* u32 */ DEVLINK_ATTR_DPIPE_ACTION, /* nested */ DEVLINK_ATTR_DPIPE_ACTION_VALUE, /* nested */ DEVLINK_ATTR_DPIPE_ACTION_TYPE, /* u32 */ DEVLINK_ATTR_DPIPE_VALUE, DEVLINK_ATTR_DPIPE_VALUE_MASK, DEVLINK_ATTR_DPIPE_VALUE_MAPPING, /* u32 */ DEVLINK_ATTR_DPIPE_HEADERS, /* nested */ DEVLINK_ATTR_DPIPE_HEADER, /* nested */ DEVLINK_ATTR_DPIPE_HEADER_NAME, /* string */ DEVLINK_ATTR_DPIPE_HEADER_ID, /* u32 */ DEVLINK_ATTR_DPIPE_HEADER_FIELDS, /* nested */ DEVLINK_ATTR_DPIPE_HEADER_GLOBAL, /* u8 */ DEVLINK_ATTR_DPIPE_HEADER_INDEX, /* u32 */ DEVLINK_ATTR_DPIPE_FIELD, /* nested */ DEVLINK_ATTR_DPIPE_FIELD_NAME, /* string */ DEVLINK_ATTR_DPIPE_FIELD_ID, /* u32 */ DEVLINK_ATTR_DPIPE_FIELD_BITWIDTH, /* u32 */ DEVLINK_ATTR_DPIPE_FIELD_MAPPING_TYPE, /* u32 */ DEVLINK_ATTR_PAD, DEVLINK_ATTR_ESWITCH_ENCAP_MODE, /* u8 */ DEVLINK_ATTR_RESOURCE_LIST, /* nested */ DEVLINK_ATTR_RESOURCE, /* nested */ DEVLINK_ATTR_RESOURCE_NAME, /* string */ DEVLINK_ATTR_RESOURCE_ID, /* u64 */ DEVLINK_ATTR_RESOURCE_SIZE, /* u64 */ DEVLINK_ATTR_RESOURCE_SIZE_NEW, /* u64 */ DEVLINK_ATTR_RESOURCE_SIZE_VALID, /* u8 */ DEVLINK_ATTR_RESOURCE_SIZE_MIN, /* u64 */ DEVLINK_ATTR_RESOURCE_SIZE_MAX, /* u64 */ DEVLINK_ATTR_RESOURCE_SIZE_GRAN, /* u64 */ DEVLINK_ATTR_RESOURCE_UNIT, /* u8 */ DEVLINK_ATTR_RESOURCE_OCC, /* u64 */ DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_ID, /* u64 */ DEVLINK_ATTR_DPIPE_TABLE_RESOURCE_UNITS,/* u64 */ DEVLINK_ATTR_PORT_FLAVOUR, /* u16 */ DEVLINK_ATTR_PORT_NUMBER, /* u32 */ DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, /* u32 */ DEVLINK_ATTR_PARAM, /* nested */ DEVLINK_ATTR_PARAM_NAME, /* string */ DEVLINK_ATTR_PARAM_GENERIC, /* flag */ DEVLINK_ATTR_PARAM_TYPE, /* u8 */ DEVLINK_ATTR_PARAM_VALUES_LIST, /* nested */ DEVLINK_ATTR_PARAM_VALUE, /* nested */ DEVLINK_ATTR_PARAM_VALUE_DATA, /* dynamic */ DEVLINK_ATTR_PARAM_VALUE_CMODE, /* u8 */ DEVLINK_ATTR_REGION_NAME, /* string */ DEVLINK_ATTR_REGION_SIZE, /* u64 */ DEVLINK_ATTR_REGION_SNAPSHOTS, /* nested */ DEVLINK_ATTR_REGION_SNAPSHOT, /* nested */ DEVLINK_ATTR_REGION_SNAPSHOT_ID, /* u32 */ DEVLINK_ATTR_REGION_CHUNKS, /* nested */ DEVLINK_ATTR_REGION_CHUNK, /* nested */ DEVLINK_ATTR_REGION_CHUNK_DATA, /* binary */ DEVLINK_ATTR_REGION_CHUNK_ADDR, /* u64 */ DEVLINK_ATTR_REGION_CHUNK_LEN, /* u64 */ DEVLINK_ATTR_INFO_DRIVER_NAME, /* string */ DEVLINK_ATTR_INFO_SERIAL_NUMBER, /* string */ DEVLINK_ATTR_INFO_VERSION_FIXED, /* nested */ DEVLINK_ATTR_INFO_VERSION_RUNNING, /* nested */ DEVLINK_ATTR_INFO_VERSION_STORED, /* nested */ DEVLINK_ATTR_INFO_VERSION_NAME, /* string */ DEVLINK_ATTR_INFO_VERSION_VALUE, /* string */ DEVLINK_ATTR_SB_POOL_CELL_SIZE, /* u32 */ DEVLINK_ATTR_FMSG, /* nested */ DEVLINK_ATTR_FMSG_OBJ_NEST_START, /* flag */ DEVLINK_ATTR_FMSG_PAIR_NEST_START, /* flag */ DEVLINK_ATTR_FMSG_ARR_NEST_START, /* flag */ DEVLINK_ATTR_FMSG_NEST_END, /* flag */ DEVLINK_ATTR_FMSG_OBJ_NAME, /* string */ DEVLINK_ATTR_FMSG_OBJ_VALUE_TYPE, /* u8 */ DEVLINK_ATTR_FMSG_OBJ_VALUE_DATA, /* dynamic */ DEVLINK_ATTR_HEALTH_REPORTER, /* nested */ DEVLINK_ATTR_HEALTH_REPORTER_NAME, /* string */ DEVLINK_ATTR_HEALTH_REPORTER_STATE, /* u8 */ DEVLINK_ATTR_HEALTH_REPORTER_ERR_COUNT, /* u64 */ DEVLINK_ATTR_HEALTH_REPORTER_RECOVER_COUNT, /* u64 */ DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS, /* u64 */ DEVLINK_ATTR_HEALTH_REPORTER_GRACEFUL_PERIOD, /* u64 */ DEVLINK_ATTR_HEALTH_REPORTER_AUTO_RECOVER, /* u8 */ DEVLINK_ATTR_FLASH_UPDATE_FILE_NAME, /* string */ DEVLINK_ATTR_FLASH_UPDATE_COMPONENT, /* string */ DEVLINK_ATTR_FLASH_UPDATE_STATUS_MSG, /* string */ DEVLINK_ATTR_FLASH_UPDATE_STATUS_DONE, /* u64 */ DEVLINK_ATTR_FLASH_UPDATE_STATUS_TOTAL, /* u64 */ DEVLINK_ATTR_PORT_PCI_PF_NUMBER, /* u16 */ DEVLINK_ATTR_PORT_PCI_VF_NUMBER, /* u16 */ DEVLINK_ATTR_STATS, /* nested */ DEVLINK_ATTR_TRAP_NAME, /* string */ /* enum devlink_trap_action */ DEVLINK_ATTR_TRAP_ACTION, /* u8 */ /* enum devlink_trap_type */ DEVLINK_ATTR_TRAP_TYPE, /* u8 */ DEVLINK_ATTR_TRAP_GENERIC, /* flag */ DEVLINK_ATTR_TRAP_METADATA, /* nested */ DEVLINK_ATTR_TRAP_GROUP_NAME, /* string */ DEVLINK_ATTR_RELOAD_FAILED, /* u8 0 or 1 */ DEVLINK_ATTR_HEALTH_REPORTER_DUMP_TS_NS, /* u64 */ DEVLINK_ATTR_NETNS_FD, /* u32 */ DEVLINK_ATTR_NETNS_PID, /* u32 */ DEVLINK_ATTR_NETNS_ID, /* u32 */ DEVLINK_ATTR_HEALTH_REPORTER_AUTO_DUMP, /* u8 */ DEVLINK_ATTR_TRAP_POLICER_ID, /* u32 */ DEVLINK_ATTR_TRAP_POLICER_RATE, /* u64 */ DEVLINK_ATTR_TRAP_POLICER_BURST, /* u64 */ DEVLINK_ATTR_PORT_FUNCTION, /* nested */ DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER, /* string */ DEVLINK_ATTR_PORT_LANES, /* u32 */ DEVLINK_ATTR_PORT_SPLITTABLE, /* u8 */ DEVLINK_ATTR_PORT_EXTERNAL, /* u8 */ DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, /* u32 */ DEVLINK_ATTR_FLASH_UPDATE_STATUS_TIMEOUT, /* u64 */ DEVLINK_ATTR_FLASH_UPDATE_OVERWRITE_MASK, /* bitfield32 */ DEVLINK_ATTR_RELOAD_ACTION, /* u8 */ DEVLINK_ATTR_RELOAD_ACTIONS_PERFORMED, /* bitfield32 */ DEVLINK_ATTR_RELOAD_LIMITS, /* bitfield32 */ DEVLINK_ATTR_DEV_STATS, /* nested */ DEVLINK_ATTR_RELOAD_STATS, /* nested */ DEVLINK_ATTR_RELOAD_STATS_ENTRY, /* nested */ DEVLINK_ATTR_RELOAD_STATS_LIMIT, /* u8 */ DEVLINK_ATTR_RELOAD_STATS_VALUE, /* u32 */ DEVLINK_ATTR_REMOTE_RELOAD_STATS, /* nested */ DEVLINK_ATTR_RELOAD_ACTION_INFO, /* nested */ DEVLINK_ATTR_RELOAD_ACTION_STATS, /* nested */ DEVLINK_ATTR_PORT_PCI_SF_NUMBER, /* u32 */ /* add new attributes above here, update the policy in devlink.c */ __DEVLINK_ATTR_MAX, DEVLINK_ATTR_MAX = __DEVLINK_ATTR_MAX - 1 }; /* Mapping between internal resource described by the field and system * structure */ enum devlink_dpipe_field_mapping_type { DEVLINK_DPIPE_FIELD_MAPPING_TYPE_NONE, DEVLINK_DPIPE_FIELD_MAPPING_TYPE_IFINDEX, }; /* Match type - specify the type of the match */ enum devlink_dpipe_match_type { DEVLINK_DPIPE_MATCH_TYPE_FIELD_EXACT, }; /* Action type - specify the action type */ enum devlink_dpipe_action_type { DEVLINK_DPIPE_ACTION_TYPE_FIELD_MODIFY, }; enum devlink_dpipe_field_ethernet_id { DEVLINK_DPIPE_FIELD_ETHERNET_DST_MAC, }; enum devlink_dpipe_field_ipv4_id { DEVLINK_DPIPE_FIELD_IPV4_DST_IP, }; enum devlink_dpipe_field_ipv6_id { DEVLINK_DPIPE_FIELD_IPV6_DST_IP, }; enum devlink_dpipe_header_id { DEVLINK_DPIPE_HEADER_ETHERNET, DEVLINK_DPIPE_HEADER_IPV4, DEVLINK_DPIPE_HEADER_IPV6, }; enum devlink_resource_unit { DEVLINK_RESOURCE_UNIT_ENTRY, }; enum devlink_port_function_attr { DEVLINK_PORT_FUNCTION_ATTR_UNSPEC, DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR, /* binary */ DEVLINK_PORT_FN_ATTR_STATE, /* u8 */ DEVLINK_PORT_FN_ATTR_OPSTATE, /* u8 */ __DEVLINK_PORT_FUNCTION_ATTR_MAX, DEVLINK_PORT_FUNCTION_ATTR_MAX = __DEVLINK_PORT_FUNCTION_ATTR_MAX - 1 }; enum devlink_port_fn_state { DEVLINK_PORT_FN_STATE_INACTIVE, DEVLINK_PORT_FN_STATE_ACTIVE, }; /** * enum devlink_port_fn_opstate - indicates operational state of the function * @DEVLINK_PORT_FN_OPSTATE_ATTACHED: Driver is attached to the function. * For graceful tear down of the function, after inactivation of the * function, user should wait for operational state to turn DETACHED. * @DEVLINK_PORT_FN_OPSTATE_DETACHED: Driver is detached from the function. * It is safe to delete the port. */ enum devlink_port_fn_opstate { DEVLINK_PORT_FN_OPSTATE_DETACHED, DEVLINK_PORT_FN_OPSTATE_ATTACHED, }; #endif /* _UAPI_LINUX_DEVLINK_H_ */ #endif /* __UAPI_LINUX_DEVLINK_WRAPPER_H */ #endif /* !__KERNEL__ */ ovn-vif-25.09.0~git20250813.23884f5/include/ovn-vif/000077500000000000000000000000001476622600000207365ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/include/ovn-vif/.gitignore000066400000000000000000000000131476622600000227200ustar00rootroot00000000000000/version.h ovn-vif-25.09.0~git20250813.23884f5/include/ovn-vif/version.h.in000066400000000000000000000005031476622600000231770ustar00rootroot00000000000000#ifndef OVN_VIF_VERSION_H #define OVN_VIF_VERSION_H 1 #define OVN_VIF_PACKAGE_STRING "@PACKAGE_STRING@" #define OVN_VIF_PACKAGE_VERSION "@PACKAGE_VERSION@" #define OVN_VIF_LIB_VERSION @LT_CURRENT@ #define OVN_VIF_LIB_REVISION @LT_REVISION@ #define OVN_VIF_LIB_AGE @LT_AGE@ #endif /* ovn-vif/version.h */ ovn-vif-25.09.0~git20250813.23884f5/lib/000077500000000000000000000000001476622600000164755ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/lib/automake.mk000066400000000000000000000007721476622600000206420ustar00rootroot00000000000000lib_LTLIBRARIES += lib/libovn-vif.la lib_libovn_vif_la_LDFLAGS = \ $(OVS_LTINFO) \ -Wl,--version-script=$(top_builddir)/lib/libovn-vif.sym \ $(AM_LDFLAGS) if HAVE_UDEV lib_libovn_vif_la_LDFLAGS += \ -ludev endif lib_libovn_vif_la_SOURCES = \ lib/netlink-devlink.h \ lib/netlink-devlink.c \ lib/ovn-vif.c DISTCLEANFILES += lib/.deps/netlink-devlink.Po if ENABLE_PLUG_REPRESENTOR lib_libovn_vif_la_SOURCES += \ lib/vif-plug-providers/representor/vif-plug-representor.c endif ovn-vif-25.09.0~git20250813.23884f5/lib/libovn-vif.sym.in000066400000000000000000000000601476622600000217030ustar00rootroot00000000000000libovn-vif_@LT_CURRENT@ { global: *; }; ovn-vif-25.09.0~git20250813.23884f5/lib/netlink-devlink.c000066400000000000000000000440571476622600000217510ustar00rootroot00000000000000/* * Copyright (c) 2021 Canonical * * 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 "netlink.h" #include "netlink-socket.h" #include "netlink-devlink.h" #include "openvswitch/vlog.h" #include "packets.h" VLOG_DEFINE_THIS_MODULE(netlink_devlink); /* Initialized by nl_devlink_init() */ static int ovs_devlink_family; struct nl_dl_dump_state { struct nl_dump dump; struct ofpbuf buf; int error; }; static int nl_devlink_init(void); const char *dl_str_not_present = ""; /* Allocates memory for and returns a pointer to devlink dump state object. * * One-time initialization and lookup of the devlink generic netlink family is * also performed, and the caller should check for error condition with a call * to nl_dl_dump_init_error before attempting to dump devlink data. * * The caller owns the allocated object and is responsible for freeing the * allocated memory with a call to nl_dl_dump_destroy when done. */ struct nl_dl_dump_state * nl_dl_dump_init(void) { struct nl_dl_dump_state *dump_state; dump_state = xmalloc(sizeof(*dump_state)); dump_state->error = nl_devlink_init(); return dump_state; } /* Get error indicator from the devlink initialization process. */ int nl_dl_dump_init_error(struct nl_dl_dump_state *dump_state) { return dump_state->error; } /* Free memory previously allocated by call to nl_dl_dump_init. * * Note that the caller is responsible for making a call to nl_dl_dump_finish * to free up resources associated with any in-flight dump process prior to * destroying the dump state object. */ void nl_dl_dump_destroy(struct nl_dl_dump_state *dump_state) { free(dump_state); } void nl_msg_put_dlgenmsg(struct ofpbuf *msg, size_t expected_payload, int family, uint8_t cmd, uint32_t flags) { nl_msg_put_genlmsghdr(msg, expected_payload, family, flags, cmd, DEVLINK_GENL_VERSION); } /* Starts a Netlink-devlink "dump" operation, by sending devlink request with * command 'cmd' to the kernel on a Netlink socket, and initializes 'state' * with buffer and dump state. */ void nl_dl_dump_start(uint8_t cmd, struct nl_dl_dump_state *state) { struct ofpbuf *request; request = ofpbuf_new(NLMSG_HDRLEN + GENL_HDRLEN); nl_msg_put_dlgenmsg(request, 0, ovs_devlink_family, cmd, NLM_F_REQUEST); nl_dump_start(&state->dump, NETLINK_GENERIC, request); ofpbuf_delete(request); ofpbuf_init(&state->buf, NL_DUMP_BUFSIZE); } static bool nl_dl_dump_next__(struct nl_dl_dump_state *state, bool (*parse_function)(struct ofpbuf *, void *), void *entry) { struct ofpbuf msg; if (!nl_dump_next(&state->dump, &msg, &state->buf)) { return false; } if (!parse_function(&msg, entry)) { ovs_mutex_lock(&state->dump.mutex); state->dump.status = EPROTO; ovs_mutex_unlock(&state->dump.mutex); return false; } return true; } /* Attempts to retrieve and parse another reply in on-going dump operation. * * If successful, returns true and assignes values or pointers to data in * 'port_entry'. The caller must not modify 'port_entry' (because it may * contain pointers to data within the buffer which will be used by future * calls to this function. * * On failure, returns false. Failure might indicate an actual error or merely * the end of replies. An error status for the entire dump operation is * provided when it is completed by calling nl_dl_dump_finish() */ bool nl_dl_port_dump_next(struct nl_dl_dump_state *state, struct dl_port *port_entry) { return nl_dl_dump_next__( state, (bool ( * )(struct ofpbuf *, void *)) &nl_dl_parse_port_policy, (void *) port_entry); } bool nl_dl_info_dump_next(struct nl_dl_dump_state *state, struct dl_info *info_entry) { return nl_dl_dump_next__( state, (bool ( * )(struct ofpbuf *, void *)) &nl_dl_parse_info_policy, (void *) info_entry); } int nl_dl_dump_finish(struct nl_dl_dump_state *state) { ofpbuf_uninit(&state->buf); return nl_dump_done(&state->dump); } static uint64_t attr_get_up_to_u64(size_t attr_idx, struct nlattr *attrs[], const struct nl_policy policy[], size_t policy_len) { if (attr_idx < policy_len && attrs[attr_idx]) { switch (policy[attr_idx].type) { case NL_A_U8: return nl_attr_get_u8(attrs[attr_idx]); break; case NL_A_U16: return nl_attr_get_u16(attrs[attr_idx]); break; case NL_A_U32: return nl_attr_get_u32(attrs[attr_idx]); break; case NL_A_U64: return nl_attr_get_u64(attrs[attr_idx]); break; case NL_A_U128: case NL_A_STRING: case NL_A_NO_ATTR: case NL_A_UNSPEC: case NL_A_FLAG: case NL_A_IPV6: case NL_A_NESTED: case NL_A_LL_ADDR: case N_NL_ATTR_TYPES: default: OVS_NOT_REACHED(); }; } return -1; } static const char * attr_get_str(size_t attr_idx, struct nlattr *attrs[], const struct nl_policy policy[], size_t policy_len) { if (attr_idx < policy_len && attrs[attr_idx]) { ovs_assert(policy[attr_idx].type == NL_A_STRING); return nl_attr_get_string(attrs[attr_idx]); } return dl_str_not_present; } bool nl_dl_parse_port_function(struct nlattr *nla, struct dl_port_function *port_fn) { static const struct nl_policy policy[] = { /* Appeared in Linux v5.9 */ [DEVLINK_PORT_FUNCTION_ATTR_UNSPEC] = { .type = NL_A_UNSPEC, .optional = true, }, [DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR] = { .type = NL_A_LL_ADDR, .optional = true, }, /* Appeared in Linnux v5.12 */ [DEVLINK_PORT_FN_ATTR_STATE] = { .type = NL_A_U8, .optional = true, }, [DEVLINK_PORT_FN_ATTR_OPSTATE] = { .type = NL_A_U8, .optional = true, }, }; struct nlattr *attrs[ARRAY_SIZE(policy)]; bool parsed; parsed = nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy)); if (parsed) { if (attrs[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]) { size_t hw_addr_size = nl_attr_get_size( attrs[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]); if (hw_addr_size == sizeof(struct eth_addr)) { port_fn->eth_addr = nl_attr_get_eth_addr( attrs[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]); } else if (hw_addr_size == sizeof(struct ib_addr)) { port_fn->ib_addr = nl_attr_get_ib_addr( attrs[DEVLINK_PORT_FUNCTION_ATTR_HW_ADDR]); } else { return false; } } else { memset(&port_fn->eth_addr, 0, sizeof(port_fn->eth_addr)); memset(&port_fn->ib_addr, 0, sizeof(port_fn->ib_addr)); } port_fn->state = attr_get_up_to_u64( DEVLINK_PORT_FN_ATTR_STATE, attrs, policy, ARRAY_SIZE(policy)); port_fn->opstate = attr_get_up_to_u64( DEVLINK_PORT_FN_ATTR_OPSTATE, attrs, policy, ARRAY_SIZE(policy)); } return parsed; } bool nl_dl_parse_port_policy(struct ofpbuf *msg, struct dl_port *port) { static const struct nl_policy policy[] = { /* Appeared in Linux v4.6 */ [DEVLINK_ATTR_BUS_NAME] = { .type = NL_A_STRING, .optional = false, }, [DEVLINK_ATTR_DEV_NAME] = { .type = NL_A_STRING, .optional = false, }, [DEVLINK_ATTR_PORT_INDEX] = { .type = NL_A_U32, .optional = false, }, [DEVLINK_ATTR_PORT_TYPE] = { .type = NL_A_U16, .optional = true, }, [DEVLINK_ATTR_PORT_DESIRED_TYPE] = { .type = NL_A_U16, .optional = true, }, [DEVLINK_ATTR_PORT_NETDEV_IFINDEX] = { .type = NL_A_U32, .optional = true, }, [DEVLINK_ATTR_PORT_NETDEV_NAME] = { .type = NL_A_STRING, .optional = true, }, [DEVLINK_ATTR_PORT_IBDEV_NAME] = { .type = NL_A_STRING, .optional = true, }, [DEVLINK_ATTR_PORT_SPLIT_COUNT] = { .type = NL_A_U32, .optional = true, }, [DEVLINK_ATTR_PORT_SPLIT_GROUP] = { .type = NL_A_U32, .optional = true, }, /* Appeared in Linux v4.18 */ [DEVLINK_ATTR_PORT_FLAVOUR] = { .type = NL_A_U16, .optional = true, }, [DEVLINK_ATTR_PORT_NUMBER] = { .type = NL_A_U32, .optional = true, }, [DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER] = { .type = NL_A_U32, .optional = true, }, /* Appeared in Linux v5.3 */ [DEVLINK_ATTR_PORT_PCI_PF_NUMBER] = { .type = NL_A_U16, .optional = true, }, [DEVLINK_ATTR_PORT_PCI_VF_NUMBER] = { .type = NL_A_U16, .optional = true, }, /* Appeared in Linux v5.9 */ [DEVLINK_ATTR_PORT_FUNCTION] = { .type = NL_A_NESTED, .optional = true, }, [DEVLINK_ATTR_PORT_LANES] = { .type = NL_A_U32, .optional = true, }, [DEVLINK_ATTR_PORT_SPLITTABLE] = { .type = NL_A_U8, .optional = true, }, /* Appeared in Linux v5.10 */ [DEVLINK_ATTR_PORT_EXTERNAL] = { .type = NL_A_U8, .optional = true }, [DEVLINK_ATTR_PORT_CONTROLLER_NUMBER] = { .type = NL_A_U32, .optional = true}, /* Appeared in Linux v5.12 */ [DEVLINK_ATTR_PORT_PCI_SF_NUMBER] = { .type = NL_A_U32, .optional = true }, }; struct nlattr *attrs[ARRAY_SIZE(policy)]; if (!nl_policy_parse(msg, NLMSG_HDRLEN + GENL_HDRLEN, policy, attrs, ARRAY_SIZE(policy))) { return false; } port->bus_name = nl_attr_get_string(attrs[DEVLINK_ATTR_BUS_NAME]); port->dev_name = nl_attr_get_string(attrs[DEVLINK_ATTR_DEV_NAME]); port->index = nl_attr_get_u32(attrs[DEVLINK_ATTR_PORT_INDEX]); port->type = attr_get_up_to_u64( DEVLINK_ATTR_PORT_TYPE, attrs, policy, ARRAY_SIZE(policy)); port->desired_type = attr_get_up_to_u64( DEVLINK_ATTR_PORT_DESIRED_TYPE, attrs, policy, ARRAY_SIZE(policy)); port->netdev_ifindex = attr_get_up_to_u64( DEVLINK_ATTR_PORT_NETDEV_IFINDEX, attrs, policy, ARRAY_SIZE(policy)); if (port->type == DEVLINK_PORT_TYPE_ETH && attrs[DEVLINK_ATTR_PORT_NETDEV_NAME]) { port->netdev_name = nl_attr_get_string( attrs[DEVLINK_ATTR_PORT_NETDEV_NAME]); } else if (port->type == DEVLINK_PORT_TYPE_IB && attrs[DEVLINK_ATTR_PORT_IBDEV_NAME]) { port->ibdev_name = nl_attr_get_string( attrs[DEVLINK_ATTR_PORT_IBDEV_NAME]); } else { port->netdev_name = dl_str_not_present; } port->split_count = attr_get_up_to_u64( DEVLINK_ATTR_PORT_SPLIT_COUNT, attrs, policy, ARRAY_SIZE(policy)); port->split_group = attr_get_up_to_u64( DEVLINK_ATTR_PORT_SPLIT_GROUP, attrs, policy, ARRAY_SIZE(policy)); port->flavour = attr_get_up_to_u64( DEVLINK_ATTR_PORT_FLAVOUR, attrs, policy, ARRAY_SIZE(policy)); port->number = attr_get_up_to_u64( DEVLINK_ATTR_PORT_NUMBER, attrs, policy, ARRAY_SIZE(policy)); port->split_subport_number = attr_get_up_to_u64( DEVLINK_ATTR_PORT_SPLIT_SUBPORT_NUMBER, attrs, policy, ARRAY_SIZE(policy)); port->pci_pf_number = attr_get_up_to_u64( DEVLINK_ATTR_PORT_PCI_PF_NUMBER, attrs, policy, ARRAY_SIZE(policy)); port->pci_vf_number = attr_get_up_to_u64( DEVLINK_ATTR_PORT_PCI_VF_NUMBER, attrs, policy, ARRAY_SIZE(policy)); port->lanes = attr_get_up_to_u64( DEVLINK_ATTR_PORT_LANES, attrs, policy, ARRAY_SIZE(policy)); port->splittable = attr_get_up_to_u64( DEVLINK_ATTR_PORT_SPLITTABLE, attrs, policy, ARRAY_SIZE(policy)); port->external = attr_get_up_to_u64( DEVLINK_ATTR_PORT_EXTERNAL, attrs, policy, ARRAY_SIZE(policy)); port->controller_number = attr_get_up_to_u64( DEVLINK_ATTR_PORT_CONTROLLER_NUMBER, attrs, policy, ARRAY_SIZE(policy)); port->pci_sf_number = attr_get_up_to_u64( DEVLINK_ATTR_PORT_PCI_SF_NUMBER, attrs, policy, ARRAY_SIZE(policy)); if (attrs[DEVLINK_ATTR_PORT_FUNCTION]) { if (!nl_dl_parse_port_function(attrs[DEVLINK_ATTR_PORT_FUNCTION], &port->function)) { return false; } } else { memset(&port->function, 0, sizeof(port->function)); port->function.state = UINT8_MAX; port->function.opstate = UINT8_MAX; } return true; } bool nl_dl_parse_info_version(struct nlattr *nla, struct dl_info_version *info_ver) { static const struct nl_policy policy[] = { /* Appeared in Linux v5.1 */ [DEVLINK_ATTR_INFO_VERSION_NAME] = { .type = NL_A_STRING, .optional = true, }, [DEVLINK_ATTR_INFO_VERSION_VALUE] = { .type = NL_A_STRING, .optional = true, }, }; struct nlattr *attrs[ARRAY_SIZE(policy)]; bool parsed; parsed = nl_parse_nested(nla, policy, attrs, ARRAY_SIZE(policy)); if (parsed) { info_ver->name = attr_get_str( DEVLINK_ATTR_INFO_VERSION_NAME, attrs, policy, ARRAY_SIZE(policy)); info_ver->value = attr_get_str( DEVLINK_ATTR_INFO_VERSION_NAME, attrs, policy, ARRAY_SIZE(policy)); } return parsed; } static bool attr_fill_version(size_t attr_idx, struct nlattr *attrs[], size_t attrs_len, struct dl_info_version *version) { if (attr_idx < attrs_len && attrs[attr_idx]) { if (!nl_dl_parse_info_version(attrs[attr_idx], version)) { return false; } } else { version->name = dl_str_not_present; version->value = dl_str_not_present; } return true; } bool nl_dl_parse_info_policy(struct ofpbuf *msg, struct dl_info *info) { static const struct nl_policy policy[] = { /* Appeared in Linux v5.1 */ [DEVLINK_ATTR_INFO_DRIVER_NAME] = { .type = NL_A_STRING, .optional = false, }, [DEVLINK_ATTR_INFO_SERIAL_NUMBER] = { .type = NL_A_STRING, .optional = true, }, [DEVLINK_ATTR_INFO_VERSION_FIXED] = { .type = NL_A_NESTED, .optional = true, }, [DEVLINK_ATTR_INFO_VERSION_RUNNING] = { .type = NL_A_NESTED, .optional = true, }, [DEVLINK_ATTR_INFO_VERSION_STORED] = { .type = NL_A_NESTED, .optional = true, }, /* Appeared in Linux v5.9 */ [DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER] = { .type = NL_A_STRING, .optional = true, }, }; struct nlattr *attrs[ARRAY_SIZE(policy)]; if (!nl_policy_parse(msg, NLMSG_HDRLEN + GENL_HDRLEN, policy, attrs, ARRAY_SIZE(policy))) { return false; } info->driver_name = attr_get_str( DEVLINK_ATTR_INFO_DRIVER_NAME, attrs, policy, ARRAY_SIZE(policy)); info->serial_number = attr_get_str( DEVLINK_ATTR_INFO_SERIAL_NUMBER, attrs, policy, ARRAY_SIZE(policy)); info->board_serial_number = attr_get_str( DEVLINK_ATTR_INFO_BOARD_SERIAL_NUMBER, attrs, policy, ARRAY_SIZE(policy)); if (!attr_fill_version(DEVLINK_ATTR_INFO_VERSION_FIXED, attrs, ARRAY_SIZE(policy), &info->version_fixed) || !attr_fill_version(DEVLINK_ATTR_INFO_VERSION_RUNNING, attrs, ARRAY_SIZE(policy), &info->version_running) || !attr_fill_version(DEVLINK_ATTR_INFO_VERSION_STORED, attrs, ARRAY_SIZE(policy), &info->version_stored)) { return false; } return true; } static int nl_devlink_init(void) { static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER; static int error; if (ovsthread_once_start(&once)) { error = nl_lookup_genl_family(DEVLINK_GENL_NAME, &ovs_devlink_family); if (error) { VLOG_INFO("Generic Netlink family '%s' does not exist. " "Linux version 4.6 or newer required.", DEVLINK_GENL_NAME); } ovsthread_once_done(&once); } return error; } ovn-vif-25.09.0~git20250813.23884f5/lib/netlink-devlink.h000066400000000000000000000075641476622600000217600ustar00rootroot00000000000000/* * Copyright (c) 2021 Canonical * * 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_DEVLINK_H #define NETLINK_DEVLINK_H 1 /* Presence of each individual value in these structs is determined at runtime * and depends on which kernel version we are communicating with as well as * which driver implementation is filling in the information for each * individual device or port. * * To signal non-presence of values the library follows the following * convention: * * - integer type values will be set to their maximum value * (e.g. UNIT8_MAX for a unit8_t) * * - hardware address type values will be set to all zero * * - string type values will be set to a pointer to dl_str_not_present * (an empty string). */ extern const char *dl_str_not_present; struct dl_port_function { struct eth_addr eth_addr; struct ib_addr ib_addr; uint8_t state; uint8_t opstate; }; struct dl_port { const char *bus_name; const char *dev_name; uint32_t index; uint16_t type; uint16_t desired_type; uint32_t netdev_ifindex; union { const char *netdev_name; /* type DEVLINK_PORT_TYPE_ETH */ const char *ibdev_name; /* type DEVLINK_PORT_TYPE_IB */ }; uint32_t split_count; uint32_t split_group; uint16_t flavour; uint32_t number; uint32_t split_subport_number; uint16_t pci_pf_number; uint16_t pci_vf_number; struct dl_port_function function; uint32_t lanes; uint8_t splittable; uint8_t external; uint32_t controller_number; uint32_t pci_sf_number; }; struct dl_info_version { const char *name; const char *value; }; struct dl_info { const char *driver_name; const char *serial_number; const char *board_serial_number; struct dl_info_version version_fixed; struct dl_info_version version_running; struct dl_info_version version_stored; }; struct eth_addr nl_attr_get_eth_addr(const struct nlattr *nla); struct ib_addr nl_attr_get_ib_addr(const struct nlattr *nla); /* The nl_dl_dump_state record declaration refers to types declared in * netlink-socket.h, which requires OVS internal autoconf macros and * definitions to be present for successful compilation. * * To enable friction free consumtion of these interfaces from programs * external to Open vSwitch, such as OVN, we keep the declaration of * nl_dl_dump_state private. * * Use the nl_dl_dump_init function to allocate memory for and get a pointer to * a devlink dump state object. The caller owns the allocated object and is * responsible for freeing the allocated memory when done. */ struct nl_dl_dump_state; struct nl_dl_dump_state * nl_dl_dump_init(void); int nl_dl_dump_init_error(struct nl_dl_dump_state *); void nl_dl_dump_destroy(struct nl_dl_dump_state *); void nl_msg_put_dlgenmsg(struct ofpbuf *, size_t, int, uint8_t, uint32_t); void nl_dl_dump_start(uint8_t, struct nl_dl_dump_state *); bool nl_dl_port_dump_next(struct nl_dl_dump_state *, struct dl_port *); bool nl_dl_info_dump_next(struct nl_dl_dump_state *, struct dl_info *); int nl_dl_dump_finish(struct nl_dl_dump_state *); bool nl_dl_parse_port_policy(struct ofpbuf *, struct dl_port *); bool nl_dl_parse_port_function(struct nlattr *, struct dl_port_function *); bool nl_dl_parse_info_policy(struct ofpbuf *, struct dl_info *); bool nl_dl_parse_info_version(struct nlattr *, struct dl_info_version *); #endif /* NETLINK_DEVLINK_H */ ovn-vif-25.09.0~git20250813.23884f5/lib/ovn-vif.c000066400000000000000000000003241476622600000202240ustar00rootroot00000000000000#include #include "vif-plug-provider.h" extern const struct vif_plug_class vif_plug_representor; const struct vif_plug_class *vif_plug_provider_classes[] = { &vif_plug_representor, NULL, }; ovn-vif-25.09.0~git20250813.23884f5/lib/vif-plug-providers/000077500000000000000000000000001476622600000222415ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/lib/vif-plug-providers/representor/000077500000000000000000000000001476622600000246115ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/lib/vif-plug-providers/representor/vif-plug-representor.c000066400000000000000000001115721476622600000310630ustar00rootroot00000000000000/* Copyright (c) 2021 Canonical * * 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 #ifdef HAVE_UDEV #include #endif /* HAVE_UDEV */ #include "vif-plug-provider.h" #include "hash.h" #include "openvswitch/hmap.h" #include "openvswitch/vlog.h" #include "netlink.h" #include "netlink-socket.h" #include "netlink-devlink.h" #include "packets.h" #include "random.h" #include "openvswitch/shash.h" VLOG_DEFINE_THIS_MODULE(vif_plug_representor); enum port_node_source { PORT_NODE_SOURCE_DUMP, PORT_NODE_SOURCE_RUNTIME, }; struct port_node { struct hmap_node mac_vf_node; struct hmap_node ifindex_node; struct hmap_node bus_dev_node; uint32_t netdev_ifindex; char *netdev_name; bool netdev_renamed; /* Which attribute is stored here depends on the value of 'flavour'. * * Flavour: Devlink attrbiute: * DEVLINK_PORT_FLAVOUR_PHYSICAL DEVLINK_ATTR_PORT_NUMBER * DEVLINK_PORT_FLAVOUR_PCI_PF DEVLINK_ATTR_PORT_PCI_PF_NUMBER * DEVLINK_PORT_FLAVOUR_PCI_VF DEVLINK_ATTR_PORT_PCI_VF_NUMBER */ uint32_t number; uint16_t flavour; struct eth_addr mac; struct port_node *pf; enum port_node_source port_node_source; }; /* Port table. * * This data structure contains three indexes: * * mac_vf_table - port_node by PF MAC and VF number. * ifindex_table - port_node by netdev ifindex. * bus_dev_table - port_node by bus/dev name (only contains PHYSICAL and * PCI_PF ports). * * There is a small number of PHYSICAL and PF flavoured ports per device. We * will need to refer to these for every update we get to a VF in order to * maintain the PF MAC+VF number index. * * Note that there is not really any association between PHYSICAL and PF * representor ports from the devlink data structure point of view. However * for systems running a kernel that does not provide the host facing MAC * through devlink on the PF representor there is a compatibility interface in * sysfs which is relative to a PHYSICAL ports netdev name (see the * compat_get_host_pf_mac function). */ struct port_table { struct hmap mac_vf_table; /* Hash table for lookups by mac+vf_num */ uint32_t mac_seed; /* We reuse the OVS mac+vlan hash functions for the * PF MAC+VF number, and they require a uint32_t seed */ struct hmap ifindex_table; /* Hash table for lookups by ifindex */ struct hmap bus_dev_table; /* Hash table for lookup of PHYSICAL and PF * ports by their bus_name/dev_name string. * While there is a large number of VFs or SFs * they will be associated with a small number * of PFs */ }; static struct port_table *port_table; static struct port_node * port_node_create(uint32_t netdev_ifindex, const char *netdev_name, uint32_t number, uint16_t flavour, struct eth_addr mac, struct port_node *pf, enum port_node_source port_node_source) { struct port_node *pn; pn = xmalloc(sizeof *pn); pn->netdev_ifindex = netdev_ifindex; pn->netdev_name = xstrdup(netdev_name); pn->netdev_renamed = false; pn->number = number; pn->flavour = flavour; pn->mac = mac; pn->pf = pf; pn->port_node_source = port_node_source; return pn; } static void port_node_destroy(struct port_node *pn) { if (pn->netdev_name) { free(pn->netdev_name); } free(pn); } static void port_node_update(struct port_node *pn, const char *netdev_name) { if (pn->netdev_name) { free (pn->netdev_name); pn->netdev_renamed = true; } pn->netdev_name = xstrdup(netdev_name); } static bool port_node_rename_expected(struct port_node *pn) { #ifdef HAVE_UDEV return pn->port_node_source == PORT_NODE_SOURCE_RUNTIME && pn->netdev_renamed == false; #else return false; #endif /* HAVE_UDEV */ } static struct port_table * port_table_create(void) { struct port_table *tbl; tbl = xmalloc(sizeof *tbl); hmap_init(&tbl->mac_vf_table); tbl->mac_seed = random_uint32(); hmap_init(&tbl->ifindex_table); hmap_init(&tbl->bus_dev_table); return tbl; } static void port_table_destroy(struct port_table *tbl) { struct port_node *port_node; HMAP_FOR_EACH_POP (port_node, mac_vf_node, &tbl->mac_vf_table) { port_node_destroy(port_node); } hmap_destroy(&tbl->mac_vf_table); /* The PHYSICAL and PF ports are stored in both ifindex_table and * bus_dev_table */ HMAP_FOR_EACH_POP (port_node, bus_dev_node, &tbl->bus_dev_table) { port_node_destroy(port_node); } hmap_destroy(&tbl->bus_dev_table); /* All entries in the ifindex table are also in the mac_vf table or * bus_dev_table which nodes were destroyed above, so we only * need to destroy the hmap data for the ifindex table. */ hmap_destroy(&tbl->ifindex_table); free(tbl); } static uint32_t port_table_hash_mac_vf(const struct port_table *tbl, const struct eth_addr mac, uint16_t vf_num) { return hash_mac(mac, vf_num, tbl->mac_seed); } static struct port_node * port_table_lookup_ifindex(struct port_table *tbl, uint32_t netdev_ifindex) { struct port_node *pn; HMAP_FOR_EACH_WITH_HASH (pn, ifindex_node, netdev_ifindex, &tbl->ifindex_table) { if (pn->netdev_ifindex == netdev_ifindex) { return pn; } } return NULL; } static struct port_node * port_table_lookup_pf_mac_vf(struct port_table *tbl, struct eth_addr mac, uint16_t vf_num) { struct port_node *pn; HMAP_FOR_EACH_WITH_HASH (pn, mac_vf_node, port_table_hash_mac_vf(tbl, mac, vf_num), &tbl->mac_vf_table) { if (pn->number == vf_num && pn->pf && eth_addr_equals(pn->pf->mac, mac)) { return pn; } } return NULL; } static uint32_t hash_bus_dev(const char *bus_name, const char *dev_name) { char bus_dev[128]; if (snprintf(bus_dev, sizeof(bus_dev), "%s/%s", bus_name, dev_name) >= sizeof(bus_dev)) { VLOG_WARN("bus_dev key buffer overflow, bus_name=%s dev_name=%s", bus_name, dev_name); } return hash_string(bus_dev, 0); } static struct port_node * port_table_lookup_phy_bus_dev(struct port_table *tbl, const char *bus_name, const char *dev_name, uint16_t flavour, uint32_t number) { struct port_node *pn; HMAP_FOR_EACH_WITH_HASH (pn, bus_dev_node, hash_bus_dev(bus_name, dev_name), &tbl->bus_dev_table) { if (pn->flavour == flavour && pn->number == number) { return pn; } } return NULL; } static struct port_node * port_table_update_phy__(struct port_table *tbl, const char *bus_name, const char *dev_name, uint32_t netdev_ifindex, const char *netdev_name, uint32_t number, uint16_t flavour, struct eth_addr mac, enum port_node_source port_node_source) { struct port_node *pn; pn = port_table_lookup_phy_bus_dev(tbl, bus_name, dev_name, flavour, number); if (!pn) { pn = port_node_create(netdev_ifindex, netdev_name, number, flavour, mac, NULL, port_node_source); hmap_insert(&tbl->ifindex_table, &pn->ifindex_node, netdev_ifindex); hmap_insert(&tbl->bus_dev_table, &pn->bus_dev_node, hash_bus_dev(bus_name, dev_name)); } else { port_node_update(pn, netdev_name); } return pn; } static struct port_node * port_table_update_function__(struct port_table *tbl, struct port_node *pf, uint32_t netdev_ifindex, const char *netdev_name, uint32_t number, uint16_t flavour, struct eth_addr mac, enum port_node_source port_node_source) { struct port_node *pn = port_table_lookup_ifindex(tbl, netdev_ifindex); if (!pn) { pn = port_node_create( netdev_ifindex, netdev_name, number, flavour, mac, pf, port_node_source); hmap_insert(&tbl->ifindex_table, &pn->ifindex_node, netdev_ifindex); hmap_insert(&tbl->mac_vf_table, &pn->mac_vf_node, port_table_hash_mac_vf(tbl, pf->mac, number)); } else { port_node_update(pn, netdev_name); } return pn; } /* Inserts or updates an entry in the table. */ static struct port_node * port_table_update_entry(struct port_table *tbl, const char *bus_name, const char *dev_name, uint32_t netdev_ifindex, const char *netdev_name, uint32_t number, uint16_t pci_pf_number, uint16_t pci_vf_number, uint16_t flavour, struct eth_addr mac, enum port_node_source port_node_source) { if (flavour == DEVLINK_PORT_FLAVOUR_PHYSICAL || flavour == DEVLINK_PORT_FLAVOUR_PCI_PF) { return port_table_update_phy__( tbl, bus_name, dev_name, netdev_ifindex, netdev_name, flavour == DEVLINK_PORT_FLAVOUR_PHYSICAL ? number : pci_pf_number, flavour, mac, port_node_source); } struct port_node *phy; phy = port_table_lookup_phy_bus_dev(tbl, bus_name, dev_name, DEVLINK_PORT_FLAVOUR_PCI_PF, pci_pf_number); if (!phy) { VLOG_WARN("attempt to add function before having knowledge about PF"); return NULL; } return port_table_update_function__(tbl, phy, netdev_ifindex, netdev_name, pci_vf_number, flavour, mac, port_node_source); } static void port_table_delete_phy__(struct port_table *tbl, const char *bus_name, const char *dev_name, uint32_t number, uint16_t flavour) { struct port_node *phy; phy = port_table_lookup_phy_bus_dev(tbl, bus_name, dev_name, flavour, number); if (!phy) { VLOG_WARN("attempt to remove non-existing device %s/%s %d", bus_name, dev_name, number); return; } hmap_remove(&tbl->ifindex_table, &phy->ifindex_node); hmap_remove(&tbl->bus_dev_table, &phy->bus_dev_node); port_node_destroy(phy); } static void port_table_delete_function__(struct port_table *tbl, struct port_node *pf, uint16_t pci_vf_number) { struct port_node *pn; pn = port_table_lookup_pf_mac_vf(tbl, pf->mac, pci_vf_number); if (!pn) { VLOG_WARN("attempt to remove non-existing function %s-%d", pf->netdev_name, pci_vf_number); return; } hmap_remove(&tbl->ifindex_table, &pn->ifindex_node); hmap_remove(&tbl->mac_vf_table, &pn->mac_vf_node); port_node_destroy(pn); } static void port_table_delete_entry(struct port_table *tbl, const char *bus_name, const char *dev_name, uint32_t number, uint16_t pci_pf_number, uint16_t pci_vf_number, uint16_t flavour) { if (flavour == DEVLINK_PORT_FLAVOUR_PHYSICAL || flavour == DEVLINK_PORT_FLAVOUR_PCI_PF) { port_table_delete_phy__( tbl, bus_name, dev_name, flavour == DEVLINK_PORT_FLAVOUR_PHYSICAL ? number : pci_pf_number, flavour); } else { struct port_node *phy; phy = port_table_lookup_phy_bus_dev(tbl, bus_name, dev_name, DEVLINK_PORT_FLAVOUR_PCI_PF, pci_pf_number); if (!phy) { VLOG_WARN("attempt to remove function with non-existing PF " "bus_dev %s/%s pci_pf_number %d", bus_name, dev_name, pci_pf_number); return; } port_table_delete_function__(tbl, phy, pci_vf_number); } } static struct nl_sock *devlink_monitor_sock; #ifdef HAVE_UDEV static struct udev *udev; static struct udev_monitor *udev_monitor; #endif /* HAVE_UDEV */ static bool compat_get_host_pf_mac(const char *, struct eth_addr *); static void port_table_update_devlink_port(struct dl_port *port_entry, enum port_node_source port_node_source) { if (port_entry->flavour != DEVLINK_PORT_FLAVOUR_PHYSICAL && port_entry->flavour != DEVLINK_PORT_FLAVOUR_PCI_PF && port_entry->flavour != DEVLINK_PORT_FLAVOUR_PCI_VF) { VLOG_WARN("Unsupported flavour for port '%s': %s", port_entry->netdev_name, port_entry->flavour == DEVLINK_PORT_FLAVOUR_CPU ? "CPU" : port_entry->flavour == DEVLINK_PORT_FLAVOUR_DSA ? "DSA" : port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF ? "PCI_PF": port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_VF ? "PCI_VF": port_entry->flavour == DEVLINK_PORT_FLAVOUR_VIRTUAL ? "VIRTUAL": port_entry->flavour == DEVLINK_PORT_FLAVOUR_UNUSED ? "UNUSED": port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF ? "PCI_SF": "UNKNOWN"); return; }; struct eth_addr fallback_mac; if (port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF && eth_addr_is_zero(port_entry->function.eth_addr)) { /* PF representor does not have host facing MAC address set. * * For kernel versions where the devlink-port infrastructure does * not provide MAC address for PCI_PF flavoured ports, there exists * a interim interface in sysfs which is relative to the name of a * PHYSICAL port netdev name. * * Note that there is not really any association between PHYSICAL and * PF representor ports from the devlink data structure point of view. * But we have found them to correlate on the devices where this is * necessary. * * Attempt to retrieve host facing MAC address from the compatibility * interface */ struct port_node *phy; phy = port_table_lookup_phy_bus_dev(port_table, port_entry->bus_name, port_entry->dev_name, DEVLINK_PORT_FLAVOUR_PHYSICAL, port_entry->pci_pf_number); if (!phy) { VLOG_WARN("Unable to find PHYSICAL representor for fallback " "lookup of host PF MAC address."); return; } if (!compat_get_host_pf_mac(phy->netdev_name, &fallback_mac)) { VLOG_WARN("Fallback lookup of host PF MAC address failed."); return; } } port_table_update_entry( port_table, port_entry->bus_name, port_entry->dev_name, port_entry->netdev_ifindex, port_entry->netdev_name, port_entry->number, port_entry->pci_pf_number, port_entry->pci_vf_number, port_entry->flavour, port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF && eth_addr_is_zero(port_entry->function.eth_addr) ? fallback_mac : port_entry->function.eth_addr, port_node_source); } static void port_table_delete_devlink_port(struct dl_port *port_entry) { port_table_delete_entry(port_table, port_entry->bus_name, port_entry->dev_name, port_entry->number, port_entry->pci_pf_number, port_entry->pci_vf_number, port_entry->flavour); } static int devlink_port_dump(void) { struct nl_dl_dump_state *port_dump; struct dl_port port_entry; int error; port_table = port_table_create(); port_dump = nl_dl_dump_init(); if ((error = nl_dl_dump_init_error(port_dump))) { VLOG_WARN( "unable to start dump of ports from devlink-port interface"); return error; } nl_dl_dump_start(DEVLINK_CMD_PORT_GET, port_dump); while (nl_dl_port_dump_next(port_dump, &port_entry)) { port_table_update_devlink_port(&port_entry, PORT_NODE_SOURCE_DUMP); } nl_dl_dump_finish(port_dump); nl_dl_dump_destroy(port_dump); return 0; } static int devlink_monitor_init(void) { unsigned int devlink_mcgroup; int error; error = nl_lookup_genl_mcgroup(DEVLINK_GENL_NAME, DEVLINK_GENL_MCGRP_CONFIG_NAME, &devlink_mcgroup); if (error) { return error; } error = nl_sock_create(NETLINK_GENERIC, &devlink_monitor_sock); if (error) { return error; } error = nl_sock_join_mcgroup(devlink_monitor_sock, devlink_mcgroup); if (error) { return error; } return 0; } static bool devlink_monitor_run(void) { uint64_t buf_stub[4096 / 64]; struct ofpbuf buf; int error; bool changed = false; ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); for (;;) { error = nl_sock_recv(devlink_monitor_sock, &buf, NULL, false); if (error == EAGAIN) { /* Nothing to do. */ break; } else if (error == ENOBUFS) { VLOG_WARN("devlink monitor socket overflowed: %s", ovs_strerror(error)); } else if (error) { VLOG_ERR("error on devlink monitor socket: %s", ovs_strerror(error)); break; } else { struct genlmsghdr *genl; struct dl_port port_entry; genl = nl_msg_genlmsghdr(&buf); if (genl->cmd == DEVLINK_CMD_PORT_NEW || genl->cmd == DEVLINK_CMD_PORT_DEL) { if (!nl_dl_parse_port_policy(&buf, &port_entry)) { VLOG_WARN("could not parse devlink port entry"); continue; } if (genl->cmd == DEVLINK_CMD_PORT_NEW) { if (port_entry.netdev_ifindex == UINT32_MAX) { /* When ports are removed we receive both a NEW CMD * without data, followed by a DEL CMD. Ignore the * empty NEW CMD */ continue; } changed = true; port_table_update_devlink_port(&port_entry, PORT_NODE_SOURCE_RUNTIME); } else if (genl->cmd == DEVLINK_CMD_PORT_DEL) { port_table_delete_devlink_port(&port_entry); } } } } return changed; } #ifdef HAVE_UDEV static void udev_monitor_init(void) { udev = udev_new(); if (!udev) { VLOG_ERR("unable to initialize udev context: %s", ovs_strerror(errno)); return; } udev_monitor = udev_monitor_new_from_netlink(udev, "kernel"); if (!udev_monitor) { VLOG_ERR("unable to initialize udev monitor: %s", ovs_strerror(errno)); return; } int err; err = udev_monitor_filter_add_match_subsystem_devtype( udev_monitor, "net", NULL); if (err < 0) { VLOG_WARN("unable to initialize udev monitor filter: %s", ovs_strerror(-err)); } err = udev_monitor_enable_receiving(udev_monitor); if (err < 0) { VLOG_ERR("unable to initialize udev monitor: %s", ovs_strerror(-err)); return; } err = udev_monitor_set_receive_buffer_size(udev_monitor, 128 * 1024 * 1024); if (err < 0) { VLOG_INFO("unable to set udev receive buffer size: %s", ovs_strerror(-err)); return; } } #endif /* HAVE_UDEV */ static bool udev_monitor_run(void) { bool changed = false; #ifdef HAVE_UDEV int fd; char buf[1]; size_t n_recv; struct udev_device *dev; fd = udev_monitor_get_fd(udev_monitor); for (;;) { n_recv = recv(fd, buf, 1, MSG_DONTWAIT | MSG_PEEK); if (n_recv == -1) { if (errno == EAGAIN) { /* Nothing to do. */ break; } else { VLOG_ERR("error on udev monitor socket: %s", ovs_strerror(errno)); } } else { dev = udev_monitor_receive_device(udev_monitor); if (!dev) { /* Nothing to do. */ break; } const char *udev_action = udev_device_get_action(dev); if (udev_action && !strcmp(udev_action, "move")) { const char *ifindex_str, *sysname; char *cp = NULL; uint32_t ifindex; struct port_node *pn; ifindex_str = udev_device_get_sysattr_value(dev, "ifindex"); if (!ifindex_str) { VLOG_WARN("udev: unable to get ifindex of moved netdev."); goto next; } sysname = udev_device_get_sysname(dev); if (!sysname) { VLOG_ERR("Unable to lookup netdev name from udev."); goto next; } ifindex = strtol(ifindex_str, &cp, 10); if (cp && cp != ifindex_str && *cp != '\0') { VLOG_WARN("udev provided malformed ifindex: '%s'", ifindex_str); goto next; } pn = port_table_lookup_ifindex(port_table, ifindex); if (!pn) { VLOG_DBG("udev move event on port we do not know about " "ifindex=%s", ifindex_str); goto next; } port_node_update(pn, sysname); changed = true; } next: udev_device_unref(dev); } } #endif /* HAVE_UDEV */ return changed; } static int vif_plug_representor_init(void) { int error; error = devlink_monitor_init(); if (error) { return error; } error = devlink_port_dump(); if (error) { return error; } #ifdef HAVE_UDEV udev_monitor_init(); #endif /* HAVE_UDEV */ return 0; } static bool vif_plug_representor_run(struct vif_plug_class *plug_class OVS_UNUSED) { return devlink_monitor_run() & udev_monitor_run(); } static int vif_plug_representor_destroy(void) { port_table_destroy(port_table); return 0; } static bool vif_plug_representor_port_prepare(const struct vif_plug_port_ctx_in *ctx_in, struct vif_plug_port_ctx_out *ctx_out) { if (ctx_in->op_type == PLUG_OP_REMOVE) { return true; } const char *opt_pf_mac = smap_get(&ctx_in->lport_options, "vif-plug:representor:pf-mac"); const char *opt_vf_num = smap_get(&ctx_in->lport_options, "vif-plug:representor:vf-num"); if (!opt_pf_mac || !opt_vf_num) { return false; } /* Ensure lookup tables are up to date */ vif_plug_representor_run(NULL); struct eth_addr pf_mac; if (!eth_addr_from_string(opt_pf_mac, &pf_mac)) { VLOG_WARN("Unable to parse option as Ethernet address for lport: %s " "pf-mac: '%s' vf-num: '%s'", ctx_in->lport_name, opt_pf_mac, opt_vf_num); return false; } char *cp = NULL; uint16_t vf_num = strtol(opt_vf_num, &cp, 10); if (cp && cp != opt_vf_num && *cp != '\0') { VLOG_WARN("Unable to parse option as VF number for lport: %s " "pf-mac: '%s' vf-num: '%s'", ctx_in->lport_name, opt_pf_mac, opt_vf_num); } struct port_node *pn; pn = port_table_lookup_pf_mac_vf(port_table, pf_mac, vf_num); if (!pn || !pn->netdev_name) { VLOG_INFO("No representor port found for " "lport: %s pf-mac: '%s' vf-num: '%s'", ctx_in->lport_name, opt_pf_mac, opt_vf_num); return false; } else if (port_node_rename_expected(pn)) { VLOG_INFO("Lookup of representor port successful, but we anticipate " "the netdev name to change, refusing plug/update of " "lport: %s current netdev_name: %s", ctx_in->lport_name, pn->netdev_name); return false; } if (ctx_out) { ctx_out->name = pn->netdev_name; ctx_out->type = NULL; } return true; } static void vif_plug_representor_port_finish( const struct vif_plug_port_ctx_in *ctx_in OVS_UNUSED, struct vif_plug_port_ctx_out *ctx_out OVS_UNUSED) { /* Nothing to be done here for now */ } static void vif_plug_representor_port_ctx_destroy( const struct vif_plug_port_ctx_in *ctx_in OVS_UNUSED, struct vif_plug_port_ctx_out *ctx_out OVS_UNUSED) { /* Noting to be done here for now */ } const struct vif_plug_class vif_plug_representor = { .type = "representor", .init = vif_plug_representor_init, .destroy = vif_plug_representor_destroy, .vif_plug_get_maintained_iface_options = NULL, /* TODO */ .run = vif_plug_representor_run, .vif_plug_port_prepare = vif_plug_representor_port_prepare, .vif_plug_port_finish = vif_plug_representor_port_finish, .vif_plug_port_ctx_destroy = vif_plug_representor_port_ctx_destroy, }; /* The kernel devlink-port interface provides a vendor neutral and standard way * of discovering host visible resources such as MAC address of interfaces from * a program running on the NIC SoC side. * * However a fairly recent kernel version is required for it to work, so until * this is widely available we provide this helper to retrieve the same * information from the interim sysfs solution. */ #ifndef OVSTEST static bool compat_get_host_pf_mac(const char *netdev_name, struct eth_addr *ea) { char file_name[IFNAMSIZ + 35 + 1]; FILE *stream; char line[128]; bool retval = false; snprintf(file_name, sizeof(file_name), "/sys/class/net/%s/smart_nic/pf/config", netdev_name); stream = fopen(file_name, "r"); if (!stream) { VLOG_WARN("%s: open failed (%s)", file_name, ovs_strerror(errno)); *ea = eth_addr_zero; return false; } while (fgets(line, sizeof(line), stream)) { char key[16]; char *cp; if (ovs_scan(line, "%15[^:]: ", key) && key[0] == 'M' && key[1] == 'A' && key[2] == 'C') { /* strip any newline character */ if ((cp = strchr(line, '\n')) != NULL) { *cp = '\0'; } /* point cp at end of key + ': ', i.e. start of MAC address */ cp = line + strnlen(key, sizeof(key)) + 2; retval = eth_addr_from_string(cp, ea); break; } } fclose(stream); return retval; } #endif /* OVSTEST */ #ifdef OVSTEST #include "tests/ovstest.h" static bool compat_get_host_pf_mac(const char *netdev_name, struct eth_addr *ea) { ovs_assert(!strcmp(netdev_name, "p0")); *ea = (struct eth_addr)ETH_ADDR_C(00,53,00,00,00,51); return true; } static void _init_store(void) { port_table = port_table_create(); port_table_update_entry( port_table, "pci", "0000:03:00.0", 10, "p0", 0, UINT16_MAX, UINT16_MAX, DEVLINK_PORT_FLAVOUR_PHYSICAL, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,00), PORT_NODE_SOURCE_DUMP); port_table_update_entry( port_table, "pci", "0000:03:00.0", 100, "p0hpf", UINT32_MAX, 0, UINT16_MAX, DEVLINK_PORT_FLAVOUR_PCI_PF, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,42), PORT_NODE_SOURCE_DUMP); } static void _destroy_store(void) { port_table_destroy(port_table); } static void test_phy_store(struct ovs_cmdl_context *ctx OVS_UNUSED) { struct port_node *pn; _init_store(); pn = port_table_lookup_phy_bus_dev(port_table, "pci", "0000:03:00.0", DEVLINK_PORT_FLAVOUR_PHYSICAL, 0); ovs_assert(pn); ovs_assert(pn->netdev_ifindex == 10); ovs_assert(!strcmp(pn->netdev_name, "p0")); ovs_assert( eth_addr_equals(pn->mac, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,00))); ovs_assert(pn->flavour == DEVLINK_PORT_FLAVOUR_PHYSICAL); ovs_assert(pn->number == 0); ovs_assert(pn == port_table_lookup_ifindex(port_table, 10)); pn = port_table_lookup_phy_bus_dev(port_table, "pci", "0000:03:00.0", DEVLINK_PORT_FLAVOUR_PCI_PF, 0); ovs_assert(pn); ovs_assert(pn->netdev_ifindex == 100); ovs_assert(!strcmp(pn->netdev_name, "p0hpf")); ovs_assert( eth_addr_equals(pn->mac, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,42))); ovs_assert(pn == port_table_lookup_ifindex(port_table, 100)); port_table_delete_entry(port_table, "pci", "0000:03:00.0", UINT32_MAX, 0, UINT16_MAX, DEVLINK_PORT_FLAVOUR_PCI_PF); pn = port_table_lookup_phy_bus_dev(port_table, "pci", "0000:03:00.0", DEVLINK_PORT_FLAVOUR_PCI_PF, 0); ovs_assert(!pn); port_table_delete_entry(port_table, "pci", "0000:03:00.0", 0, UINT16_MAX, UINT16_MAX, DEVLINK_PORT_FLAVOUR_PHYSICAL); pn = port_table_lookup_phy_bus_dev(port_table, "pci", "0000:03:00.0", DEVLINK_PORT_FLAVOUR_PHYSICAL, 0); ovs_assert(!pn); /* confirm that we would not misbehave on attempt to delete non-existing * entries. */ port_table_delete_entry(port_table, "nonexistent", "device", UINT32_MAX, 0, UINT16_MAX, DEVLINK_PORT_FLAVOUR_PCI_PF); port_table_delete_entry(port_table, "nonexistent", "device", 0, UINT16_MAX, UINT16_MAX, DEVLINK_PORT_FLAVOUR_PHYSICAL); _destroy_store(); } static void test_port_store(struct ovs_cmdl_context *ctx OVS_UNUSED) { struct port_node *pn; _init_store(); port_table_update_entry( port_table, "pci", "0000:03:00.0", 1000, "pf0vf0", UINT32_MAX, 0, 0, DEVLINK_PORT_FLAVOUR_PCI_VF, (struct eth_addr) ETH_ADDR_C(00,53,00,00,10,00), PORT_NODE_SOURCE_RUNTIME); pn = port_table_lookup_ifindex(port_table, 1000); ovs_assert(pn); ovs_assert(pn->netdev_ifindex == 1000); ovs_assert(!strcmp(pn->netdev_name, "pf0vf0")); ovs_assert( eth_addr_equals(pn->mac, (struct eth_addr) ETH_ADDR_C(00,53,00,00,10,00))); ovs_assert(pn->flavour == DEVLINK_PORT_FLAVOUR_PCI_VF); ovs_assert(pn->number == 0); ovs_assert(pn->port_node_source == PORT_NODE_SOURCE_RUNTIME); ovs_assert(pn->pf); ovs_assert(!strcmp(pn->pf->netdev_name, "p0hpf")); pn = port_table_lookup_pf_mac_vf( port_table, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,42), 0); ovs_assert(pn); ovs_assert(pn->netdev_ifindex == 1000); ovs_assert(!strcmp(pn->netdev_name, "pf0vf0")); ovs_assert( eth_addr_equals(pn->mac, (struct eth_addr) ETH_ADDR_C(00,53,00,00,10,00))); port_table_delete_entry(port_table, "pci", "0000:03:00.0", UINT32_MAX, 0, 0, DEVLINK_PORT_FLAVOUR_PCI_VF); pn = port_table_lookup_ifindex(port_table, 1000); ovs_assert(!pn); pn = port_table_lookup_pf_mac_vf( port_table, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,42), 0); ovs_assert(!pn); /* confirm that we would not misbehave on attempt to delete non-existing * entries. */ port_table_delete_entry(port_table, "non", "existing", UINT32_MAX, 0, 0, DEVLINK_PORT_FLAVOUR_PCI_VF); _destroy_store(); } static void test_port_node_rename_expected(struct ovs_cmdl_context *ctx OVS_UNUSED) { struct port_node *pn; _init_store(); pn = port_table_lookup_ifindex(port_table, 100); ovs_assert(port_node_rename_expected(pn) == false); pn = port_table_update_entry( port_table, "pci", "0000:03:00.0", 1000, "eth0", UINT32_MAX, 0, 0, DEVLINK_PORT_FLAVOUR_PCI_VF, (struct eth_addr) ETH_ADDR_C(00,53,00,00,10,00), PORT_NODE_SOURCE_RUNTIME); ovs_assert(port_node_rename_expected(pn) == true); _destroy_store(); } static void test_port_table_update_devlink_port(struct ovs_cmdl_context *ctx OVS_UNUSED) { struct dl_port dl_port = { .bus_name = "pci", .dev_name = "0000:03:00.0", .netdev_ifindex = 1000, .netdev_name = "pf0vf0", .number = UINT32_MAX, .pci_pf_number = 0, .pci_vf_number = 0, .flavour = DEVLINK_PORT_FLAVOUR_PCI_VF, }; struct port_node *pn; _init_store(); port_table_update_devlink_port(&dl_port, PORT_NODE_SOURCE_RUNTIME); pn = port_table_lookup_ifindex(port_table, 1000); ovs_assert(pn); ovs_assert(pn->pf); ovs_assert( eth_addr_equals(pn->pf->mac, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,42))); ovs_assert(pn->port_node_source == PORT_NODE_SOURCE_RUNTIME); pn = port_table_lookup_pf_mac_vf( port_table, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,42), 0); ovs_assert(pn); ovs_assert(pn->netdev_ifindex == 1000); _destroy_store(); } static void test_port_table_delete_devlink_port(struct ovs_cmdl_context *ctx OVS_UNUSED) { struct dl_port dl_port = { .bus_name = "pci", .dev_name = "0000:03:00.0", .netdev_ifindex = 1000, .netdev_name = "pf0vf0", .number = UINT32_MAX, .pci_pf_number = 0, .pci_vf_number = 0, .flavour = DEVLINK_PORT_FLAVOUR_PCI_VF, }; struct port_node *pn; _init_store(); port_table_update_devlink_port(&dl_port, PORT_NODE_SOURCE_DUMP); pn = port_table_lookup_ifindex(port_table, 1000); ovs_assert(pn); ovs_assert(pn->port_node_source == PORT_NODE_SOURCE_DUMP); port_table_delete_devlink_port(&dl_port); pn = port_table_lookup_ifindex(port_table, 1000); ovs_assert(!pn); _destroy_store(); } static void test_port_table_update_devlink_port_compat( struct ovs_cmdl_context *ctx OVS_UNUSED) { struct dl_port dl_pf_port = { .bus_name = "pci", .dev_name = "0000:03:00.0", .netdev_ifindex = 100, .netdev_name = "pf0hpf", .number = UINT32_MAX, .pci_pf_number = 0, .pci_vf_number = UINT16_MAX, .flavour = DEVLINK_PORT_FLAVOUR_PCI_PF, }; struct port_node *pn; _init_store(); port_table_delete_entry(port_table, "pci", "0000:03:00.0", UINT32_MAX, 0, UINT16_MAX, DEVLINK_PORT_FLAVOUR_PCI_PF); /* check that when we add a PF with zero MAC address, the compat sysfs * interface is used to retrieve the MAC. */ port_table_update_devlink_port(&dl_pf_port, PORT_NODE_SOURCE_DUMP); pn = port_table_lookup_phy_bus_dev(port_table, "pci", "0000:03:00.0", DEVLINK_PORT_FLAVOUR_PCI_PF, 0); ovs_assert(pn); ovs_assert( eth_addr_equals(pn->mac, (struct eth_addr) ETH_ADDR_C(00,53,00,00,00,51))); _destroy_store(); } static void test_vif_plug_representor_main(int argc, char **argv) { set_program_name(*argv); static const struct ovs_cmdl_command commands[] = { {"store-phy", NULL, 0, 0, test_phy_store, OVS_RO}, {"store-port", NULL, 0, 0, test_port_store, OVS_RO}, {"store-devlink-port-update", NULL, 0, 0, test_port_table_update_devlink_port, OVS_RO}, {"store-devlink-port-delete", NULL, 0, 0, test_port_table_delete_devlink_port, OVS_RO}, {"store-devlink-port-update-compat", NULL, 0, 0, test_port_table_update_devlink_port_compat, OVS_RO}, {"store-rename-expected", NULL, 0, 0, test_port_node_rename_expected, OVS_RO}, {NULL, NULL, 0, 0, NULL, OVS_RO}, }; struct ovs_cmdl_context ctx; ctx.argc = argc - 1; ctx.argv = argv + 1; ovs_cmdl_run_command(&ctx, commands); } OVSTEST_REGISTER("test-vif-plug-representor", test_vif_plug_representor_main); #endif /* OVSTEST */ ovn-vif-25.09.0~git20250813.23884f5/m4/000077500000000000000000000000001476622600000162475ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/m4/.gitignore000066400000000000000000000001041476622600000202320ustar00rootroot00000000000000/libtool.m4 /ltoptions.m4 /ltsugar.m4 /ltversion.m4 /lt~obsolete.m4 ovn-vif-25.09.0~git20250813.23884f5/m4/absolute-header.m4000066400000000000000000000103561476622600000215620ustar00rootroot00000000000000# absolute-header.m4 serial 16 dnl Copyright (C) 2006-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Derek Price. # gl_ABSOLUTE_HEADER(HEADER1 HEADER2 ...) # --------------------------------------- # Find the absolute name of a header file, testing first if the header exists. # If the header were sys/inttypes.h, this macro would define # ABSOLUTE_SYS_INTTYPES_H to the '""' quoted absolute name of sys/inttypes.h # in config.h # (e.g. '#define ABSOLUTE_SYS_INTTYPES_H "///usr/include/sys/inttypes.h"'). # The three "///" are to pacify Sun C 5.8, which otherwise would say # "warning: #include of /usr/include/... may be non-portable". # Use '""', not '<>', so that the /// cannot be confused with a C99 comment. # Note: This macro assumes that the header file is not empty after # preprocessing, i.e. it does not only define preprocessor macros but also # provides some type/enum definitions or function/variable declarations. AC_DEFUN([gl_ABSOLUTE_HEADER], [AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_PREPROC_REQUIRE()dnl dnl FIXME: gl_absolute_header and ac_header_exists must be used unquoted dnl until we can assume autoconf 2.64 or newer. m4_foreach_w([gl_HEADER_NAME], [$1], [AS_VAR_PUSHDEF([gl_absolute_header], [gl_cv_absolute_]m4_defn([gl_HEADER_NAME]))dnl AC_CACHE_CHECK([absolute name of <]m4_defn([gl_HEADER_NAME])[>], m4_defn([gl_absolute_header]), [AS_VAR_PUSHDEF([ac_header_exists], [ac_cv_header_]m4_defn([gl_HEADER_NAME]))dnl AC_CHECK_HEADERS_ONCE(m4_defn([gl_HEADER_NAME]))dnl if test AS_VAR_GET(ac_header_exists) = yes; then gl_ABSOLUTE_HEADER_ONE(m4_defn([gl_HEADER_NAME])) fi AS_VAR_POPDEF([ac_header_exists])dnl ])dnl AC_DEFINE_UNQUOTED(AS_TR_CPP([ABSOLUTE_]m4_defn([gl_HEADER_NAME])), ["AS_VAR_GET(gl_absolute_header)"], [Define this to an absolute name of <]m4_defn([gl_HEADER_NAME])[>.]) AS_VAR_POPDEF([gl_absolute_header])dnl ])dnl ])# gl_ABSOLUTE_HEADER # gl_ABSOLUTE_HEADER_ONE(HEADER) # ------------------------------ # Like gl_ABSOLUTE_HEADER, except that: # - it assumes that the header exists, # - it uses the current CPPFLAGS, # - it does not cache the result, # - it is silent. AC_DEFUN([gl_ABSOLUTE_HEADER_ONE], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_CONFTEST([AC_LANG_SOURCE([[#include <]]m4_dquote([$1])[[>]])]) dnl AIX "xlc -E" and "cc -E" omit #line directives for header files dnl that contain only a #include of other header files and no dnl non-comment tokens of their own. This leads to a failure to dnl detect the absolute name of , , dnl and others. The workaround is to force preservation of comments dnl through option -C. This ensures all necessary #line directives dnl are present. GCC supports option -C as well. case "$host_os" in aix*) gl_absname_cpp="$ac_cpp -C" ;; *) gl_absname_cpp="$ac_cpp" ;; esac changequote(,) case "$host_os" in (mingw*|msys*) dnl For the sake of native Windows compilers (excluding gcc), dnl treat backslash as a directory separator, like /. dnl Actually, these compilers use a double-backslash as dnl directory separator, inside the dnl # line "filename" dnl directives. gl_dirsep_regex='[/\\]' ;; *) gl_dirsep_regex='\/' ;; esac dnl A sed expression that turns a string into a basic regular dnl expression, for use within "/.../". gl_make_literal_regex_sed='s,[]$^\\.*/[],\\&,g' gl_header_literal_regex=`echo '$1' \ | sed -e "$gl_make_literal_regex_sed"` gl_absolute_header_sed="/${gl_dirsep_regex}${gl_header_literal_regex}/"'{ s/.*"\(.*'"${gl_dirsep_regex}${gl_header_literal_regex}"'\)".*/\1/ s|^/[^/]|//&| p q }' changequote([,]) dnl eval is necessary to expand gl_absname_cpp. dnl Ultrix and Pyramid sh refuse to redirect output of eval, dnl so use subshell. AS_VAR_SET([gl_cv_absolute_]AS_TR_SH([[$1]]), [`(eval "$gl_absname_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | sed -n "$gl_absolute_header_sed"`]) ]) ovn-vif-25.09.0~git20250813.23884f5/m4/automake.mk000066400000000000000000000005401476622600000204050ustar00rootroot00000000000000# 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. EXTRA_DIST += \ m4/absolute-header.m4 \ m4/include_next.m4 \ m4/pkg.m4 ovn-vif-25.09.0~git20250813.23884f5/m4/ax_cxx_compile_stdcxx.m4000066400000000000000000000474241476622600000231230ustar00rootroot00000000000000# =========================================================================== # https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== # # SYNOPSIS # # AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the specified # version of the C++ standard. If necessary, add switches to CXX and # CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) # or '14' (for the C++14 standard). # # The second argument, if specified, indicates whether you insist on an # extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. # -std=c++11). If neither is specified, you get whatever works, with # preference for an extended mode. # # The third argument, if specified 'mandatory' or if left unspecified, # indicates that baseline support for the specified C++ standard is # required and that the macro should error out if no mode with that # support is found. If specified 'optional', then configuration proceeds # regardless, after defining HAVE_CXX${VERSION} if and only if a # supporting mode is found. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner # Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov # Copyright (c) 2015 Paul Norman # Copyright (c) 2015 Moritz Klammler # Copyright (c) 2016 Krzesimir Nowak # # 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 any # warranty. #serial 7 dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro dnl (serial version number 13). AX_REQUIRE_DEFINED([AC_MSG_WARN]) AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], [$1], [14], [ax_cxx_compile_alternatives="14 1y"], [$1], [17], [ax_cxx_compile_alternatives="17 1z"], [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$2], [], [], [$2], [ext], [], [$2], [noext], [], [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl ac_success=no AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, ax_cv_cxx_compile_cxx$1, [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [ax_cv_cxx_compile_cxx$1=yes], [ax_cv_cxx_compile_cxx$1=no])]) if test x$ax_cv_cxx_compile_cxx$1 = xyes; then ac_success=yes fi m4_if([$2], [noext], [], [dnl if test x$ac_success = xno; then for alternative in ${ax_cxx_compile_alternatives}; do switch="-std=gnu++${alternative}" cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done fi]) m4_if([$2], [ext], [], [dnl if test x$ac_success = xno; then dnl HP's aCC needs +std=c++11 according to: dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf dnl Cray's crayCC needs "-h std=c++11" for alternative in ${ax_cxx_compile_alternatives}; do for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, $cachevar, [ac_save_CXX="$CXX" CXX="$CXX $switch" AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], [eval $cachevar=yes], [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then CXX="$CXX $switch" if test -n "$CXXCPP" ; then CXXCPP="$CXXCPP $switch" fi ac_success=yes break fi done if test x$ac_success = xyes; then break fi done fi]) AC_LANG_POP([C++]) if test x$ax_cxx_compile_cxx$1_required = xtrue; then if test x$ac_success = xno; then AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) fi fi if test x$ac_success = xno; then HAVE_CXX$1=0 AC_MSG_NOTICE([No compiler with C++$1 support was found]) else HAVE_CXX$1=1 AC_DEFINE(HAVE_CXX$1,1, [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])]) ]) dnl Test body for checking C++11 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 ) dnl Test body for checking C++14 support m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 ) m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 ) dnl Tests for new features in C++11 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ // If the compiler admits that it is not ready for C++11, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201103L #error "This is not a C++11 compiler" #else namespace cxx11 { namespace test_static_assert { template struct check { static_assert(sizeof(int) <= sizeof(T), "not big enough"); }; } namespace test_final_override { struct Base { virtual void f() {} }; struct Derived : public Base { virtual void f() override {} }; } namespace test_double_right_angle_brackets { template < typename T > struct check {}; typedef check single_type; typedef check> double_type; typedef check>> triple_type; typedef check>>> quadruple_type; } namespace test_decltype { int f() { int a = 1; decltype(a) b = 2; return a + b; } } namespace test_type_deduction { template < typename T1, typename T2 > struct is_same { static const bool value = false; }; template < typename T > struct is_same { static const bool value = true; }; template < typename T1, typename T2 > auto add(T1 a1, T2 a2) -> decltype(a1 + a2) { return a1 + a2; } int test(const int c, volatile int v) { static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == false, ""); auto ac = c; auto av = v; auto sumi = ac + av + 'x'; auto sumf = ac + av + 1.0; static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == true, ""); static_assert(is_same::value == false, ""); static_assert(is_same::value == true, ""); return (sumf > 0.0) ? sumi : add(c, v); } } namespace test_noexcept { int f() { return 0; } int g() noexcept { return 0; } static_assert(noexcept(f()) == false, ""); static_assert(noexcept(g()) == true, ""); } namespace test_constexpr { template < typename CharT > unsigned long constexpr strlen_c_r(const CharT *const s, const unsigned long acc) noexcept { return *s ? strlen_c_r(s + 1, acc + 1) : acc; } template < typename CharT > unsigned long constexpr strlen_c(const CharT *const s) noexcept { return strlen_c_r(s, 0UL); } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("1") == 1UL, ""); static_assert(strlen_c("example") == 7UL, ""); static_assert(strlen_c("another\0example") == 7UL, ""); } namespace test_rvalue_references { template < int N > struct answer { static constexpr int value = N; }; answer<1> f(int&) { return answer<1>(); } answer<2> f(const int&) { return answer<2>(); } answer<3> f(int&&) { return answer<3>(); } void test() { int i = 0; const int c = 0; static_assert(decltype(f(i))::value == 1, ""); static_assert(decltype(f(c))::value == 2, ""); static_assert(decltype(f(0))::value == 3, ""); } } namespace test_uniform_initialization { struct test { static const int zero {}; static const int one {1}; }; static_assert(test::zero == 0, ""); static_assert(test::one == 1, ""); } namespace test_lambdas { void test1() { auto lambda1 = [](){}; auto lambda2 = lambda1; lambda1(); lambda2(); } int test2() { auto a = [](int i, int j){ return i + j; }(1, 2); auto b = []() -> int { return '0'; }(); auto c = [=](){ return a + b; }(); auto d = [&](){ return c; }(); auto e = [a, &b](int x) mutable { const auto identity = [](int y){ return y; }; for (auto i = 0; i < a; ++i) a += b--; return x + identity(a + b); }(0); return a + b + c + d + e; } int test3() { const auto nullary = [](){ return 0; }; const auto unary = [](int x){ return x; }; using nullary_t = decltype(nullary); using unary_t = decltype(unary); const auto higher1st = [](nullary_t f){ return f(); }; const auto higher2nd = [unary](nullary_t f1){ return [unary, f1](unary_t f2){ return f2(unary(f1())); }; }; return higher1st(nullary) + higher2nd(nullary)(unary); } } namespace test_variadic_templates { template struct sum; template struct sum { static constexpr auto value = N0 + sum::value; }; template <> struct sum<> { static constexpr auto value = 0; }; static_assert(sum<>::value == 0, ""); static_assert(sum<1>::value == 1, ""); static_assert(sum<23>::value == 23, ""); static_assert(sum<1, 2>::value == 3, ""); static_assert(sum<5, 5, 11>::value == 21, ""); static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); } // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function // because of this. namespace test_template_alias_sfinae { struct foo {}; template using member = typename T::member_type; template void func(...) {} template void func(member*) {} void test(); void test() { func(0); } } } // namespace cxx11 #endif // __cplusplus >= 201103L ]]) dnl Tests for new features in C++14 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ // If the compiler admits that it is not ready for C++14, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus < 201402L #error "This is not a C++14 compiler" #else namespace cxx14 { namespace test_polymorphic_lambdas { int test() { const auto lambda = [](auto&&... args){ const auto istiny = [](auto x){ return (sizeof(x) == 1UL) ? 1 : 0; }; const int aretiny[] = { istiny(args)... }; return aretiny[0]; }; return lambda(1, 1L, 1.0f, '1'); } } namespace test_binary_literals { constexpr auto ivii = 0b0000000000101010; static_assert(ivii == 42, "wrong value"); } namespace test_generalized_constexpr { template < typename CharT > constexpr unsigned long strlen_c(const CharT *const s) noexcept { auto length = 0UL; for (auto p = s; *p; ++p) ++length; return length; } static_assert(strlen_c("") == 0UL, ""); static_assert(strlen_c("x") == 1UL, ""); static_assert(strlen_c("test") == 4UL, ""); static_assert(strlen_c("another\0test") == 7UL, ""); } namespace test_lambda_init_capture { int test() { auto x = 0; const auto lambda1 = [a = x](int b){ return a + b; }; const auto lambda2 = [a = lambda1(x)](){ return a; }; return lambda2(); } } namespace test_digit_separators { constexpr auto ten_million = 100'000'000; static_assert(ten_million == 100000000, ""); } namespace test_return_type_deduction { auto f(int& x) { return x; } decltype(auto) g(int& x) { return x; } template < typename T1, typename T2 > struct is_same { static constexpr auto value = false; }; template < typename T > struct is_same { static constexpr auto value = true; }; int test() { auto x = 0; static_assert(is_same::value, ""); static_assert(is_same::value, ""); return x; } } } // namespace cxx14 #endif // __cplusplus >= 201402L ]]) dnl Tests for new features in C++17 m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ // If the compiler admits that it is not ready for C++17, why torture it? // Hopefully, this will speed up the test. #ifndef __cplusplus #error "This is not a C++ compiler" #elif __cplusplus <= 201402L #error "This is not a C++17 compiler" #else #if defined(__clang__) #define REALLY_CLANG #else #if defined(__GNUC__) #define REALLY_GCC #endif #endif #include #include #include namespace cxx17 { #if !defined(REALLY_CLANG) namespace test_constexpr_lambdas { // TODO: test it with clang++ from git constexpr int foo = [](){return 42;}(); } #endif // !defined(REALLY_CLANG) namespace test::nested_namespace::definitions { } namespace test_fold_expression { template int multiply(Args... args) { return (args * ... * 1); } template bool all(Args... args) { return (args && ...); } } namespace test_extended_static_assert { static_assert (true); } namespace test_auto_brace_init_list { auto foo = {5}; auto bar {5}; static_assert(std::is_same, decltype(foo)>::value); static_assert(std::is_same::value); } namespace test_typename_in_template_template_parameter { template typename X> struct D; } namespace test_fallthrough_nodiscard_maybe_unused_attributes { int f1() { return 42; } [[nodiscard]] int f2() { [[maybe_unused]] auto unused = f1(); switch (f1()) { case 17: f1(); [[fallthrough]]; case 42: f1(); } return f1(); } } namespace test_extended_aggregate_initialization { struct base1 { int b1, b2 = 42; }; struct base2 { base2() { b3 = 42; } int b3; }; struct derived : base1, base2 { int d; }; derived d1 {{1, 2}, {}, 4}; // full initialization derived d2 {{}, {}, 4}; // value-initialized bases } namespace test_general_range_based_for_loop { struct iter { int i; int& operator* () { return i; } const int& operator* () const { return i; } iter& operator++() { ++i; return *this; } }; struct sentinel { int i; }; bool operator== (const iter& i, const sentinel& s) { return i.i == s.i; } bool operator!= (const iter& i, const sentinel& s) { return !(i == s); } struct range { iter begin() const { return {0}; } sentinel end() const { return {5}; } }; void f() { range r {}; for (auto i : r) { [[maybe_unused]] auto v = i; } } } namespace test_lambda_capture_asterisk_this_by_value { struct t { int i; int foo() { return [*this]() { return i; }(); } }; } namespace test_enum_class_construction { enum class byte : unsigned char {}; byte foo {42}; } namespace test_constexpr_if { template int f () { if constexpr(cond) { return 13; } else { return 42; } } } namespace test_selection_statement_with_initializer { int f() { return 13; } int f2() { if (auto i = f(); i > 0) { return 3; } switch (auto i = f(); i + 4) { case 17: return 2; default: return 1; } } } #if !defined(REALLY_CLANG) namespace test_template_argument_deduction_for_class_templates { // TODO: test it with clang++ from git template struct pair { pair (T1 p1, T2 p2) : m1 {p1}, m2 {p2} {} T1 m1; T2 m2; }; void f() { [[maybe_unused]] auto p = pair{13, 42u}; } } #endif // !defined(REALLY_CLANG) namespace test_non_type_auto_template_parameters { template struct B {}; B<5> b1; B<'a'> b2; } #if !defined(REALLY_CLANG) namespace test_structured_bindings { // TODO: test it with clang++ from git int arr[2] = { 1, 2 }; std::pair pr = { 1, 2 }; auto f1() -> int(&)[2] { return arr; } auto f2() -> std::pair& { return pr; } struct S { int x1 : 2; volatile double y1; }; S f3() { return {}; } auto [ x1, y1 ] = f1(); auto& [ xr1, yr1 ] = f1(); auto [ x2, y2 ] = f2(); auto& [ xr2, yr2 ] = f2(); const auto [ x3, y3 ] = f3(); } #endif // !defined(REALLY_CLANG) #if !defined(REALLY_CLANG) namespace test_exception_spec_type_system { // TODO: test it with clang++ from git struct Good {}; struct Bad {}; void g1() noexcept; void g2(); template Bad f(T*, T*); template Good f(T1*, T2*); static_assert (std::is_same_v); } #endif // !defined(REALLY_CLANG) namespace test_inline_variables { template void f(T) {} template inline T g(T) { return T{}; } template<> inline void f<>(int) {} template<> int g<>(int) { return 5; } } } // namespace cxx17 #endif // __cplusplus <= 201402L ]]) ovn-vif-25.09.0~git20250813.23884f5/m4/ax_func_posix_memalign.m4000066400000000000000000000027711476622600000232360ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_func_posix_memalign.html # =========================================================================== # # SYNOPSIS # # AX_FUNC_POSIX_MEMALIGN # # DESCRIPTION # # Some versions of posix_memalign (notably glibc 2.2.5) incorrectly apply # their power-of-two check to the size argument, not the alignment # argument. AX_FUNC_POSIX_MEMALIGN defines HAVE_POSIX_MEMALIGN if the # power-of-two check is correctly applied to the alignment argument. # # LICENSE # # Copyright (c) 2008 Scott Pakin # # 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 any # warranty. #serial 7 AC_DEFUN([AX_FUNC_POSIX_MEMALIGN], [AC_CACHE_CHECK([for working posix_memalign], [ax_cv_func_posix_memalign_works], [AC_TRY_RUN([ #include int main () { void *buffer; /* Some versions of glibc incorrectly perform the alignment check on * the size word. */ exit (posix_memalign (&buffer, sizeof(void *), 123) != 0); } ], [ax_cv_func_posix_memalign_works=yes], [ax_cv_func_posix_memalign_works=no], [ax_cv_func_posix_memalign_works=no])]) if test "$ax_cv_func_posix_memalign_works" = "yes" ; then AC_DEFINE([HAVE_POSIX_MEMALIGN], [1], [Define to 1 if `posix_memalign' works.]) fi ]) ovn-vif-25.09.0~git20250813.23884f5/m4/compat.m4000066400000000000000000000012461476622600000177770ustar00rootroot00000000000000# -*- autoconf -*- # 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. m4_ifndef([AS_VAR_COPY], [m4_define([AS_VAR_COPY], [AS_LITERAL_IF([$1[]$2], [$1=$$2], [eval $1=\$$2])])]) ovn-vif-25.09.0~git20250813.23884f5/m4/include_next.m4000066400000000000000000000207731476622600000212030ustar00rootroot00000000000000# include_next.m4 serial 23 dnl Copyright (C) 2006-2013 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, dnl with or without modifications, as long as this notice is preserved. dnl From Paul Eggert and Derek Price. dnl Sets INCLUDE_NEXT and PRAGMA_SYSTEM_HEADER. dnl dnl INCLUDE_NEXT expands to 'include_next' if the compiler supports it, or to dnl 'include' otherwise. dnl dnl INCLUDE_NEXT_AS_FIRST_DIRECTIVE expands to 'include_next' if the compiler dnl supports it in the special case that it is the first include directive in dnl the given file, or to 'include' otherwise. dnl dnl PRAGMA_SYSTEM_HEADER can be used in files that contain #include_next, dnl so as to avoid GCC warnings when the gcc option -pedantic is used. dnl '#pragma GCC system_header' has the same effect as if the file was found dnl through the include search path specified with '-isystem' options (as dnl opposed to the search path specified with '-I' options). Namely, gcc dnl does not warn about some things, and on some systems (Solaris and Interix) dnl __STDC__ evaluates to 0 instead of to 1. The latter is an undesired side dnl effect; we are therefore careful to use 'defined __STDC__' or '1' instead dnl of plain '__STDC__'. dnl dnl PRAGMA_COLUMNS can be used in files that override system header files, so dnl as to avoid compilation errors on HP NonStop systems when the gnulib file dnl is included by a system header file that does a "#pragma COLUMNS 80" (which dnl has the effect of truncating the lines of that file and all files that it dnl includes to 80 columns) and the gnulib file has lines longer than 80 dnl columns. AC_DEFUN([gl_INCLUDE_NEXT], [ AC_LANG_PREPROC_REQUIRE() AC_CACHE_CHECK([whether the preprocessor supports include_next], [gl_cv_have_include_next], [rm -rf conftestd1a conftestd1b conftestd2 mkdir conftestd1a conftestd1b conftestd2 dnl IBM C 9.0, 10.1 (original versions, prior to the 2009-01 updates) on dnl AIX 6.1 support include_next when used as first preprocessor directive dnl in a file, but not when preceded by another include directive. Check dnl for this bug by including . dnl Additionally, with this same compiler, include_next is a no-op when dnl used in a header file that was included by specifying its absolute dnl file name. Despite these two bugs, include_next is used in the dnl compiler's . By virtue of the second bug, we need to use dnl include_next as well in this case. cat < conftestd1a/conftest.h #define DEFINED_IN_CONFTESTD1 #include_next #ifdef DEFINED_IN_CONFTESTD2 int foo; #else #error "include_next doesn't work" #endif EOF cat < conftestd1b/conftest.h #define DEFINED_IN_CONFTESTD1 #include #include_next #ifdef DEFINED_IN_CONFTESTD2 int foo; #else #error "include_next doesn't work" #endif EOF cat < conftestd2/conftest.h #ifndef DEFINED_IN_CONFTESTD1 #error "include_next test doesn't work" #endif #define DEFINED_IN_CONFTESTD2 EOF gl_save_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1b -Iconftestd2" dnl We intentionally avoid using AC_LANG_SOURCE here. AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include ]], [gl_cv_have_include_next=yes], [CPPFLAGS="$gl_save_CPPFLAGS -Iconftestd1a -Iconftestd2" AC_COMPILE_IFELSE([AC_LANG_DEFINES_PROVIDED[#include ]], [gl_cv_have_include_next=buggy], [gl_cv_have_include_next=no]) ]) CPPFLAGS="$gl_save_CPPFLAGS" rm -rf conftestd1a conftestd1b conftestd2 ]) PRAGMA_SYSTEM_HEADER= if test $gl_cv_have_include_next = yes; then INCLUDE_NEXT=include_next INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include_next if test -n "$GCC"; then PRAGMA_SYSTEM_HEADER='#pragma GCC system_header' fi else if test $gl_cv_have_include_next = buggy; then INCLUDE_NEXT=include INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include_next else INCLUDE_NEXT=include INCLUDE_NEXT_AS_FIRST_DIRECTIVE=include fi fi AC_SUBST([INCLUDE_NEXT]) AC_SUBST([INCLUDE_NEXT_AS_FIRST_DIRECTIVE]) AC_SUBST([PRAGMA_SYSTEM_HEADER]) AC_CACHE_CHECK([whether system header files limit the line length], [gl_cv_pragma_columns], [dnl HP NonStop systems, which define __TANDEM, have this misfeature. AC_EGREP_CPP([choke me], [ #ifdef __TANDEM choke me #endif ], [gl_cv_pragma_columns=yes], [gl_cv_pragma_columns=no]) ]) if test $gl_cv_pragma_columns = yes; then PRAGMA_COLUMNS="#pragma COLUMNS 10000" else PRAGMA_COLUMNS= fi AC_SUBST([PRAGMA_COLUMNS]) ]) # gl_CHECK_NEXT_HEADERS(HEADER1 HEADER2 ...) # ------------------------------------------ # For each arg foo.h, if #include_next works, define NEXT_FOO_H to be # ''; otherwise define it to be # '"///usr/include/foo.h"', or whatever other absolute file name is suitable. # Also, if #include_next works as first preprocessing directive in a file, # define NEXT_AS_FIRST_DIRECTIVE_FOO_H to be ''; otherwise define it to # be # '"///usr/include/foo.h"', or whatever other absolute file name is suitable. # That way, a header file with the following line: # #@INCLUDE_NEXT@ @NEXT_FOO_H@ # or # #@INCLUDE_NEXT_AS_FIRST_DIRECTIVE@ @NEXT_AS_FIRST_DIRECTIVE_FOO_H@ # behaves (after sed substitution) as if it contained # #include_next # even if the compiler does not support include_next. # The three "///" are to pacify Sun C 5.8, which otherwise would say # "warning: #include of /usr/include/... may be non-portable". # Use '""', not '<>', so that the /// cannot be confused with a C99 comment. # Note: This macro assumes that the header file is not empty after # preprocessing, i.e. it does not only define preprocessor macros but also # provides some type/enum definitions or function/variable declarations. # # This macro also checks whether each header exists, by invoking # AC_CHECK_HEADERS_ONCE or AC_CHECK_HEADERS on each argument. AC_DEFUN([gl_CHECK_NEXT_HEADERS], [ gl_NEXT_HEADERS_INTERNAL([$1], [check]) ]) # gl_NEXT_HEADERS(HEADER1 HEADER2 ...) # ------------------------------------ # Like gl_CHECK_NEXT_HEADERS, except do not check whether the headers exist. # This is suitable for headers like that are standardized by C89 # and therefore can be assumed to exist. AC_DEFUN([gl_NEXT_HEADERS], [ gl_NEXT_HEADERS_INTERNAL([$1], [assume]) ]) # The guts of gl_CHECK_NEXT_HEADERS and gl_NEXT_HEADERS. AC_DEFUN([gl_NEXT_HEADERS_INTERNAL], [ AC_REQUIRE([gl_INCLUDE_NEXT]) AC_REQUIRE([AC_CANONICAL_HOST]) m4_if([$2], [check], [AC_CHECK_HEADERS_ONCE([$1]) ]) dnl FIXME: gl_next_header and gl_header_exists must be used unquoted dnl until we can assume autoconf 2.64 or newer. m4_foreach_w([gl_HEADER_NAME], [$1], [AS_VAR_PUSHDEF([gl_next_header], [gl_cv_next_]m4_defn([gl_HEADER_NAME])) if test $gl_cv_have_include_next = yes; then AS_VAR_SET(gl_next_header, ['<'gl_HEADER_NAME'>']) else AC_CACHE_CHECK( [absolute name of <]m4_defn([gl_HEADER_NAME])[>], m4_defn([gl_next_header]), [m4_if([$2], [check], [AS_VAR_PUSHDEF([gl_header_exists], [ac_cv_header_]m4_defn([gl_HEADER_NAME])) if test AS_VAR_GET(gl_header_exists) = yes; then AS_VAR_POPDEF([gl_header_exists]) ]) gl_ABSOLUTE_HEADER_ONE(gl_HEADER_NAME) AS_VAR_COPY([gl_header], [gl_cv_absolute_]AS_TR_SH(gl_HEADER_NAME)) AS_VAR_SET(gl_next_header, ['"'$gl_header'"']) m4_if([$2], [check], [else AS_VAR_SET(gl_next_header, ['<'gl_HEADER_NAME'>']) fi ]) ]) fi AC_SUBST( AS_TR_CPP([NEXT_]m4_defn([gl_HEADER_NAME])), [AS_VAR_GET(gl_next_header)]) if test $gl_cv_have_include_next = yes || test $gl_cv_have_include_next = buggy; then # INCLUDE_NEXT_AS_FIRST_DIRECTIVE='include_next' gl_next_as_first_directive='<'gl_HEADER_NAME'>' else # INCLUDE_NEXT_AS_FIRST_DIRECTIVE='include' gl_next_as_first_directive=AS_VAR_GET(gl_next_header) fi AC_SUBST( AS_TR_CPP([NEXT_AS_FIRST_DIRECTIVE_]m4_defn([gl_HEADER_NAME])), [$gl_next_as_first_directive]) AS_VAR_POPDEF([gl_next_header])]) ]) # Autoconf 2.68 added warnings for our use of AC_COMPILE_IFELSE; # this fallback is safe for all earlier autoconf versions. m4_define_default([AC_LANG_DEFINES_PROVIDED]) ovn-vif-25.09.0~git20250813.23884f5/m4/openvswitch.m4000066400000000000000000000555621476622600000210770ustar00rootroot00000000000000# -*- autoconf -*- # Copyright (c) 2008-2016, 2019 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. # m4_include([m4/compat.m4]) dnl Checks for --enable-coverage and updates CFLAGS and LDFLAGS appropriately. AC_DEFUN([OVS_CHECK_COVERAGE], [AC_REQUIRE([AC_PROG_CC]) AC_ARG_ENABLE( [coverage], [AC_HELP_STRING([--enable-coverage], [Enable gcov coverage tool.])], [case "${enableval}" in (yes) coverage=true ;; (no) coverage=false ;; (*) AC_MSG_ERROR([bad value ${enableval} for --enable-coverage]) ;; esac], [coverage=false]) if $coverage; then # Autoconf by default puts "-g -O2" in CFLAGS. We need to remove the -O2 # option for coverage to be useful. This does it without otherwise # interfering with anything that the user might have put there. old_CFLAGS=$CFLAGS CFLAGS= for option in $old_CFLAGS; do case $option in (-O2) ;; (*) CFLAGS="$CFLAGS $option" ;; esac done OVS_CFLAGS="$OVS_CFLAGS --coverage" OVS_LDFLAGS="$OVS_LDFLAGS --coverage" fi]) dnl Checks for --enable-ndebug and defines NDEBUG if it is specified. AC_DEFUN([OVS_CHECK_NDEBUG], [AC_ARG_ENABLE( [ndebug], [AC_HELP_STRING([--enable-ndebug], [Disable debugging features for max performance])], [case "${enableval}" in (yes) ndebug=true ;; (no) ndebug=false ;; (*) AC_MSG_ERROR([bad value ${enableval} for --enable-ndebug]) ;; esac], [ndebug=false]) AM_CONDITIONAL([NDEBUG], [test x$ndebug = xtrue])]) dnl Checks for MSVC x64 compiler. AC_DEFUN([OVS_CHECK_WIN64], [AC_CACHE_CHECK( [for MSVC x64 compiler], [cl_cv_x64], [dnl "cl" writes x64 output to stdin: if (cl) 2>&1 | grep 'x64' >/dev/null 2>&1; then cl_cv_x64=yes MSVC64_LDFLAGS=" /MACHINE:X64 " MSVC_PLATFORM="x64" else cl_cv_x64=no MSVC64_LDFLAGS="" MSVC_PLATFORM="x86" fi]) AC_SUBST([MSVC64_LDFLAGS]) AC_SUBST([MSVC_PLATFORM]) ]) dnl Checks for WINDOWS. AC_DEFUN([OVS_CHECK_WIN32], [AC_CHECK_HEADER([windows.h], [WIN32=yes], [WIN32=no]) AM_CONDITIONAL([WIN32], [test "$WIN32" = yes]) if test "$WIN32" = yes; then AC_ARG_WITH([pthread], [AS_HELP_STRING([--with-pthread=DIR], [root of the pthread-win32 directory])], [ case "$withval" in "" | y | ye | yes | n | no) AC_MSG_ERROR([Invalid --with-pthread value]) ;; *) PTHREAD_WIN32_DIR=$withval/lib PTHREAD_WIN32_DIR_DLL=/$(echo ${withval} | ${SED} -e 's/://')/bin PTHREAD_WIN32_DIR_DLL_WIN_FORM=$withval/bin PTHREAD_INCLUDES=-I$withval/include PTHREAD_LDFLAGS=-L$PTHREAD_WIN32_DIR PTHREAD_LIBS="-lpthreadVC3" AC_SUBST([PTHREAD_WIN32_DIR_DLL_WIN_FORM]) AC_SUBST([PTHREAD_WIN32_DIR_DLL]) AC_SUBST([PTHREAD_INCLUDES]) AC_SUBST([PTHREAD_LDFLAGS]) AC_SUBST([PTHREAD_LIBS]) ;; esac ], [ AC_MSG_ERROR([pthread directory not specified]) ] ) AC_ARG_WITH([debug], [AS_HELP_STRING([--with-debug], [Build without compiler optimizations])], [ MSVC_CFLAGS="-O0" AC_SUBST([MSVC_CFLAGS]) ], [ MSVC_CFLAGS="-O2" AC_SUBST([MSVC_CFLAGS]) ] ) AC_DEFINE([WIN32], [1], [Define to 1 if building on WIN32.]) AC_CHECK_TYPES([struct timespec], [], [], [[#include ]]) AH_BOTTOM([#ifdef WIN32 #include "include/windows/windefs.h" #endif]) fi]) dnl OVS_CHECK_WINDOWS dnl dnl Configure Visual Studio solution build AC_DEFUN([OVS_CHECK_VISUAL_STUDIO_DDK], [ if test "$WIN32" = yes; then AC_ARG_WITH([vstudiotarget], [AS_HELP_STRING([--with-vstudiotarget=target_type], [Target type: Debug/Release])], [ case "$withval" in "Release") ;; "Debug") ;; *) AC_MSG_ERROR([No valid Visual Studio configuration found]) ;; esac VSTUDIO_CONFIG=$withval ], [ VSTUDIO_CONFIG="Debug" ] ) AC_SUBST([VSTUDIO_CONFIG]) AC_ARG_WITH([vstudiotargetver], [AS_HELP_STRING([--with-vstudiotargetver=target_ver1,target_ver2], [Target versions: Win8,Win8.1,Win10])], [ targetver=`echo "$withval" | tr -s , ' ' ` for ver in $targetver; do case "$ver" in "Win8") VSTUDIO_WIN8=true ;; "Win8.1") VSTUDIO_WIN8_1=true ;; "Win10") VSTUDIO_WIN10=true ;; *) AC_MSG_ERROR([No valid Visual Studio target version found]) ;; esac done ], [ VSTUDIO_WIN8=true VSTUDIO_WIN8_1=true VSTUDIO_WIN10=true ] ) AC_DEFINE([VSTUDIO_DDK], [1], [System uses the Visual Studio build target.]) fi AM_CONDITIONAL([VSTUDIO_WIN8], [test -n "$VSTUDIO_WIN8"]) AM_CONDITIONAL([VSTUDIO_WIN8_1], [test -n "$VSTUDIO_WIN8_1"]) AM_CONDITIONAL([VSTUDIO_WIN10], [test -n "$VSTUDIO_WIN10"]) AM_CONDITIONAL([VSTUDIO_DDK], [test -n "$VSTUDIO_CONFIG"]) ]) dnl Checks for Netlink support. AC_DEFUN([OVS_CHECK_NETLINK], [AC_CHECK_HEADER([linux/netlink.h], [HAVE_NETLINK=yes], [HAVE_NETLINK=no], [#include ]) AM_CONDITIONAL([HAVE_NETLINK], [test "$HAVE_NETLINK" = yes]) if test "$HAVE_NETLINK" = yes; then AC_DEFINE([HAVE_NETLINK], [1], [Define to 1 if Netlink protocol is available.]) fi]) dnl Checks for libcap-ng. AC_DEFUN([OVS_CHECK_LIBCAPNG], [AC_ARG_ENABLE( [libcapng], [AC_HELP_STRING([--disable-libcapng], [Disable Linux capability support])], [case "${enableval}" in (yes) libcapng=true ;; (no) libcapng=false ;; (*) AC_MSG_ERROR([bad value ${enableval} for --enable-libcapng]) ;; esac], [libcapng=check]) if test "$libcapng" != false; then AC_CHECK_LIB([cap-ng], [capng_clear], [HAVE_LIBCAPNG=yes]) if test "$HAVE_LIBCAPNG" != yes; then if test "$libcapng" = true ; then AC_MSG_ERROR([libcap-ng support requested, but not found]) fi if test "$libcapng" = check ; then AC_MSG_WARN([cannot find libcap-ng. --user option will not be supported on Linux. (you may use --disable-libcapng to suppress this warning). ]) fi fi fi AC_SUBST([HAVE_LIBCAPNG]) AM_CONDITIONAL([HAVE_LIBCAPNG], [test "$HAVE_LIBCAPNG" = yes]) if test "$HAVE_LIBCAPNG" = yes; then AC_DEFINE([HAVE_LIBCAPNG], [1], [Define to 1 if libcap-ng is available.]) CAPNG_LDADD="-lcap-ng" AC_SUBST([CAPNG_LDADD]) fi]) dnl Checks for OpenSSL. AC_DEFUN([OVS_CHECK_OPENSSL], [AC_ARG_ENABLE( [ssl], [AC_HELP_STRING([--disable-ssl], [Disable OpenSSL support])], [case "${enableval}" in (yes) ssl=true ;; (no) ssl=false ;; (*) AC_MSG_ERROR([bad value ${enableval} for --enable-ssl]) ;; esac], [ssl=check]) if test "$ssl" != false; then AX_CHECK_OPENSSL( [HAVE_OPENSSL=yes], [HAVE_OPENSSL=no if test "$ssl" = check; then AC_MSG_WARN([Cannot find openssl: $SSL_PKG_ERRORS OpenFlow connections over SSL will not be supported. (You may use --disable-ssl to suppress this warning.)]) else AC_MSG_ERROR([Cannot find openssl (use --disable-ssl to configure without SSL support)]) fi]) else HAVE_OPENSSL=no fi AC_SUBST([HAVE_OPENSSL]) AM_CONDITIONAL([HAVE_OPENSSL], [test "$HAVE_OPENSSL" = yes]) if test "$HAVE_OPENSSL" = yes; then AC_DEFINE([HAVE_OPENSSL], [1], [Define to 1 if OpenSSL is installed.]) fi OPENSSL_SUPPORTS_SNI=no if test $HAVE_OPENSSL = yes; then save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $SSL_INCLUDES" AC_CHECK_DECL([SSL_set_tlsext_host_name], [OPENSSL_SUPPORTS_SNI=yes], [], [#include ]) if test $OPENSSL_SUPPORTS_SNI = yes; then AC_DEFINE( [OPENSSL_SUPPORTS_SNI], [1], [Define to 1 if OpenSSL supports Server Name Indication (SNI).]) fi CPPFLAGS=$save_CPPFLAGS fi AC_SUBST([OPENSSL_SUPPORTS_SNI]) ]) dnl Checks for libraries needed by lib/socket-util.c. AC_DEFUN([OVS_CHECK_SOCKET_LIBS], [AC_CHECK_LIB([socket], [connect]) AC_SEARCH_LIBS([gethostbyname], [resolv])]) dnl Checks for the directory in which to store the PKI. AC_DEFUN([OVS_CHECK_PKIDIR], [AC_ARG_WITH( [pkidir], AC_HELP_STRING([--with-pkidir=DIR], [PKI hierarchy directory [[LOCALSTATEDIR/lib/openvswitch/pki]]]), [PKIDIR=$withval], [PKIDIR='${localstatedir}/lib/openvswitch/pki']) AC_SUBST([PKIDIR])]) dnl Checks for the directory in which to store pidfiles. AC_DEFUN([OVS_CHECK_RUNDIR], [AC_ARG_WITH( [rundir], AC_HELP_STRING([--with-rundir=DIR], [directory used for pidfiles [[LOCALSTATEDIR/run/openvswitch]]]), [RUNDIR=$withval], [RUNDIR='${localstatedir}/run/openvswitch']) AC_SUBST([RUNDIR])]) dnl Checks for the directory in which to store logs. AC_DEFUN([OVS_CHECK_LOGDIR], [AC_ARG_WITH( [logdir], AC_HELP_STRING([--with-logdir=DIR], [directory used for logs [[LOCALSTATEDIR/log/PACKAGE]]]), [LOGDIR=$withval], [LOGDIR='${localstatedir}/log/${PACKAGE}']) AC_SUBST([LOGDIR])]) dnl Checks for the directory in which to store the Open vSwitch database. AC_DEFUN([OVS_CHECK_DBDIR], [AC_ARG_WITH( [dbdir], AC_HELP_STRING([--with-dbdir=DIR], [directory used for conf.db [[SYSCONFDIR/PACKAGE]]]), [DBDIR=$withval], [DBDIR='${sysconfdir}/${PACKAGE}']) AC_SUBST([DBDIR])]) dnl Defines HAVE_BACKTRACE if backtrace() is found. AC_DEFUN([OVS_CHECK_BACKTRACE], [AC_SEARCH_LIBS([backtrace], [execinfo ubacktrace], [AC_DEFINE([HAVE_BACKTRACE], [1], [Define to 1 if you have backtrace(3).])])]) dnl Defines HAVE_PERF_EVENT if linux/perf_event.h is found. AC_DEFUN([OVS_CHECK_PERF_EVENT], [AC_CHECK_HEADERS([linux/perf_event.h])]) dnl Checks for valgrind/valgrind.h. AC_DEFUN([OVS_CHECK_VALGRIND], [AC_CHECK_HEADERS([valgrind/valgrind.h])]) dnl Checks for Python 3.4 or later. AC_DEFUN([OVS_CHECK_PYTHON3], [AC_CACHE_CHECK( [for Python 3 (version 3.4 or later)], [ovs_cv_python3], [if test -n "$PYTHON3"; then ovs_cv_python3=$PYTHON3 else ovs_cv_python3=no for binary in python3 python3.4 python3.5 python3.6 python3.7; do ovs_save_IFS=$IFS; IFS=$PATH_SEPARATOR for dir in $PATH; do IFS=$ovs_save_IFS test -z "$dir" && dir=. if test -x "$dir"/"$binary" && "$dir"/"$binary" -c 'import sys if sys.hexversion >= 0x03040000 and sys.hexversion < 0x04000000: sys.exit(0) else: sys.exit(1)'; then ovs_cv_python3=$dir/$binary break 2 fi done done fi]) if test "$ovs_cv_python3" = no; then AC_MSG_ERROR([Python 3.4 or later is required but not found in $PATH, please install it or set $PYTHON3 to point to it]) fi AC_ARG_VAR([PYTHON3]) PYTHON3=$ovs_cv_python3]) dnl Checks for flake8. AC_DEFUN([OVS_CHECK_FLAKE8], [AC_CACHE_CHECK( [for flake8], [ovs_cv_flake8], [if flake8 --version >/dev/null 2>&1; then ovs_cv_flake8=yes else ovs_cv_flake8=no fi]) AM_CONDITIONAL([HAVE_FLAKE8], [test "$ovs_cv_flake8" = yes])]) dnl Checks for sphinx. AC_DEFUN([OVS_CHECK_SPHINX], [AC_CHECK_PROGS( [SPHINXBUILD], [sphinx-build-3 sphinx-build-2 sphinx-build], [none]) AC_ARG_VAR([SPHINXBUILD]) AM_CONDITIONAL([HAVE_SPHINX], [test "$SPHINXBUILD" != none])]) dnl Checks for binutils/assembler known issue with AVX512. dnl Due to backports, we probe assembling a reproducer instead of checking dnl binutils version string. More details, including ASM dumps and debug here: dnl GCC: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90028 dnl The checking of binutils funcationality instead of LD version is similar dnl to as how DPDK proposes to solve this issue: dnl http://patches.dpdk.org/patch/71723/ AC_DEFUN([OVS_CHECK_BINUTILS_AVX512], [AC_CACHE_CHECK( [binutils avx512 assembler checks passing], [ovs_cv_binutils_avx512_good], [dnl Assemble a short snippet to test for issue in "build-aux" dir: mkdir -p build-aux OBJFILE=build-aux/binutils_avx512_check.o GATHER_PARAMS='0x8(,%ymm1,1),%ymm0{%k2}' echo "vpgatherqq $GATHER_PARAMS" | as --64 -o $OBJFILE - if ($CC -dumpmachine | grep x86_64) >/dev/null 2>&1; then if (objdump -d --no-show-raw-insn $OBJFILE | grep -q $GATHER_PARAMS) >/dev/null 2>&1; then ovs_cv_binutils_avx512_good=yes else ovs_cv_binutils_avx512_good=no dnl Explicitly disallow avx512f to stop compiler auto-vectorizing dnl and causing zmm usage with buggy binutils versions. CFLAGS="$CFLAGS -mno-avx512f" fi else dnl non x86_64 architectures don't have avx512, so not affected ovs_cv_binutils_avx512_good=no fi]) rm $OBJFILE if test "$ovs_cv_binutils_avx512_good" = yes; then AC_DEFINE([HAVE_LD_AVX512_GOOD], [1], [Define to 1 if binutils correctly supports AVX512.]) fi AM_CONDITIONAL([HAVE_LD_AVX512_GOOD], [test "$ovs_cv_binutils_avx512_good" = yes])]) dnl Checks for dot. AC_DEFUN([OVS_CHECK_DOT], [AC_CACHE_CHECK( [for dot], [ovs_cv_dot], [dnl "dot" writes -V output to stderr: if (dot -V) 2>&1 | grep '^dot - [[gG]]raphviz version' >/dev/null 2>&1; then ovs_cv_dot=yes else ovs_cv_dot=no fi]) AM_CONDITIONAL([HAVE_DOT], [test "$ovs_cv_dot" = yes])]) dnl Checks for groff. AC_DEFUN([OVS_CHECK_GROFF], [AC_CACHE_CHECK( [for groff], [ovs_cv_groff], [if (groff -v) >/dev/null 2>&1; then ovs_cv_groff=yes else ovs_cv_groff=no fi]) AM_CONDITIONAL([HAVE_GROFF], [test "$ovs_cv_groff" = yes])]) dnl Checks for thread-local storage support. dnl dnl Checks whether the compiler and linker support the C11 dnl thread_local macro from , and if so defines dnl HAVE_THREAD_LOCAL. If not, checks whether the compiler and linker dnl support the GCC __thread extension, and if so defines dnl HAVE___THREAD. AC_DEFUN([OVS_CHECK_TLS], [AC_CACHE_CHECK( [whether $CC has that supports thread_local], [ovs_cv_thread_local], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include static thread_local int var;], [return var;])], [ovs_cv_thread_local=yes], [ovs_cv_thread_local=no])]) if test $ovs_cv_thread_local = yes; then AC_DEFINE([HAVE_THREAD_LOCAL], [1], [Define to 1 if the C compiler and linker supports the C11 thread_local matcro defined in .]) else AC_CACHE_CHECK( [whether $CC supports __thread], [ovs_cv___thread], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([static __thread int var;], [return var;])], [ovs_cv___thread=yes], [ovs_cv___thread=no])]) if test $ovs_cv___thread = yes; then AC_DEFINE([HAVE___THREAD], [1], [Define to 1 if the C compiler and linker supports the GCC __thread extenions.]) fi fi]) dnl OVS_CHECK_ATOMIC_LIBS dnl dnl Check to see if -latomic is need for GCC atomic built-ins. AC_DEFUN([OVS_CHECK_ATOMIC_LIBS], [AC_SEARCH_LIBS([__atomic_load_8], [atomic])]) dnl OVS_CHECK_GCC4_ATOMICS dnl dnl Checks whether the compiler and linker support GCC 4.0+ atomic built-ins. dnl A compile-time only check is not enough because the compiler defers dnl unimplemented built-ins to libgcc, which sometimes also lacks dnl implementations. AC_DEFUN([OVS_CHECK_GCC4_ATOMICS], [AC_CACHE_CHECK( [whether $CC supports GCC 4.0+ atomic built-ins], [ovs_cv_gcc4_atomics], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([[#include #define ovs_assert(expr) if (!(expr)) abort(); #define TEST_ATOMIC_TYPE(TYPE) \ { \ TYPE x = 1; \ TYPE orig; \ \ __sync_synchronize(); \ ovs_assert(x == 1); \ \ __sync_synchronize(); \ x = 3; \ __sync_synchronize(); \ ovs_assert(x == 3); \ \ orig = __sync_fetch_and_add(&x, 1); \ ovs_assert(orig == 3); \ __sync_synchronize(); \ ovs_assert(x == 4); \ \ orig = __sync_fetch_and_sub(&x, 2); \ ovs_assert(orig == 4); \ __sync_synchronize(); \ ovs_assert(x == 2); \ \ orig = __sync_fetch_and_or(&x, 6); \ ovs_assert(orig == 2); \ __sync_synchronize(); \ ovs_assert(x == 6); \ \ orig = __sync_fetch_and_and(&x, 10); \ ovs_assert(orig == 6); \ __sync_synchronize(); \ ovs_assert(x == 2); \ \ orig = __sync_fetch_and_xor(&x, 10); \ ovs_assert(orig == 2); \ __sync_synchronize(); \ ovs_assert(x == 8); \ }]], [dnl TEST_ATOMIC_TYPE(char); TEST_ATOMIC_TYPE(unsigned char); TEST_ATOMIC_TYPE(signed char); TEST_ATOMIC_TYPE(short); TEST_ATOMIC_TYPE(unsigned short); TEST_ATOMIC_TYPE(int); TEST_ATOMIC_TYPE(unsigned int); TEST_ATOMIC_TYPE(long int); TEST_ATOMIC_TYPE(unsigned long int); TEST_ATOMIC_TYPE(long long int); TEST_ATOMIC_TYPE(unsigned long long int); ])], [ovs_cv_gcc4_atomics=yes], [ovs_cv_gcc4_atomics=no])]) if test $ovs_cv_gcc4_atomics = yes; then AC_DEFINE([HAVE_GCC4_ATOMICS], [1], [Define to 1 if the C compiler and linker supports the GCC 4.0+ atomic built-ins.]) fi]) dnl OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(SIZE) dnl dnl Checks __atomic_always_lock_free(SIZE, 0) AC_DEFUN([OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE], [AC_CACHE_CHECK( [value of __atomic_always_lock_free($1)], [ovs_cv_atomic_always_lock_free_$1], [AC_COMPUTE_INT( [ovs_cv_atomic_always_lock_free_$1], [__atomic_always_lock_free($1, 0)], [], [ovs_cv_atomic_always_lock_free_$1=unsupported])]) if test ovs_cv_atomic_always_lock_free_$1 != unsupported; then AC_DEFINE_UNQUOTED( [ATOMIC_ALWAYS_LOCK_FREE_$1B], [$ovs_cv_atomic_always_lock_free_$1], [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.]) fi]) dnl OVS_CHECK_POSIX_AIO AC_DEFUN([OVS_CHECK_POSIX_AIO], [AC_SEARCH_LIBS([aio_write], [rt]) AM_CONDITIONAL([HAVE_POSIX_AIO], [test "$ac_cv_search_aio_write" != no])]) dnl OVS_CHECK_INCLUDE_NEXT AC_DEFUN([OVS_CHECK_INCLUDE_NEXT], [AC_REQUIRE([gl_CHECK_NEXT_HEADERS]) gl_CHECK_NEXT_HEADERS([$1])]) dnl OVS_CHECK_PRAGMA_MESSAGE AC_DEFUN([OVS_CHECK_PRAGMA_MESSAGE], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM( [[_Pragma("message(\"Checking for pragma message\")") ]])], [AC_DEFINE(HAVE_PRAGMA_MESSAGE,1,[Define if compiler supports #pragma message directive])]) ]) dnl OVS_LIBTOOL_VERSIONS sets the major, minor, micro version information for dnl OVS_LTINFO variable. This variable locks libtool information for shared dnl objects, allowing multiple versions with different ABIs to coexist. AC_DEFUN([OVS_LIBTOOL_VERSIONS], [AC_MSG_CHECKING(linker output version information) OVS_MAJOR=`echo "$PACKAGE_VERSION" | sed -e 's/[[.]].*//'` OVS_MINOR=`echo "$PACKAGE_VERSION" | sed -e "s/^$OVS_MAJOR//" -e 's/^.//' -e 's/[[.]].*//'` OVS_MICRO=`echo "$PACKAGE_VERSION" | sed -e "s/^$OVS_MAJOR.$OVS_MINOR//" -e 's/^.//' -e 's/[[^0-9]].*//'` OVS_LT_RELINFO="-release $OVS_MAJOR.$OVS_MINOR" OVS_LT_VERINFO="-version-info $LT_CURRENT:$OVS_MICRO" OVS_LTINFO="$OVS_LT_RELINFO $OVS_LT_VERINFO" AC_MSG_RESULT([libX-$OVS_MAJOR.$OVS_MINOR.so.$LT_CURRENT.0.$OVS_MICRO)]) AC_SUBST(OVS_LTINFO) ]) dnl OVS does not use C++ itself, but it provides public header files dnl that a C++ compiler should accept, so when --enable-Werror is in dnl effect and a C++ compiler is available, we enable building a C++ dnl source file that #includes all the public headers, as a way to dnl ensure that they are acceptable as C++. AC_DEFUN([OVS_CHECK_CXX], [AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([OVS_ENABLE_WERROR]) AX_CXX_COMPILE_STDCXX([11], [], [optional]) if test $enable_Werror = yes && test $HAVE_CXX11 = 1; then enable_cxx=: AC_LANG_PUSH([C++]) AC_CHECK_HEADERS([atomic]) AC_LANG_POP([C++]) else enable_cxx=false fi AM_CONDITIONAL([HAVE_CXX], [$enable_cxx])]) dnl Checks for unbound library. AC_DEFUN([OVS_CHECK_UNBOUND], [AC_CHECK_LIB(unbound, ub_ctx_create, [HAVE_UNBOUND=yes], [HAVE_UNBOUND=no]) if test "$HAVE_UNBOUND" = yes; then AC_DEFINE([HAVE_UNBOUND], [1], [Define to 1 if unbound is detected.]) LIBS="$LIBS -lunbound" fi AM_CONDITIONAL([HAVE_UNBOUND], [test "$HAVE_UNBOUND" = yes]) AC_SUBST([HAVE_UNBOUND])]) dnl Checks for libunwind. AC_DEFUN([OVS_CHECK_UNWIND], [AC_CHECK_LIB([unwind], [unw_backtrace], [AC_CHECK_HEADERS([libunwind.h], [HAVE_UNWIND=yes], [HAVE_UNWIND=no])], [HAVE_UNWIND=no]) if test "$HAVE_UNWIND" = yes; then AC_DEFINE([HAVE_UNWIND], [1], [Define to 1 if unwind is detected.]) LIBS="$LIBS -lunwind" fi AM_CONDITIONAL([HAVE_UNWIND], [test "$HAVE_UNWIND" = yes]) AC_SUBST([HAVE_UNWIND])]) ovn-vif-25.09.0~git20250813.23884f5/m4/ovn.m4000066400000000000000000000214731476622600000173220ustar00rootroot00000000000000# -*- autoconf -*- # Copyright (c) 2008-2016, 2019 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. # m4_include([m4/compat.m4]) dnl Checks for --enable-ndebug and defines NDEBUG if it is specified. AC_DEFUN([OVS_CHECK_NDEBUG], [AC_ARG_ENABLE( [ndebug], [AC_HELP_STRING([--enable-ndebug], [Disable debugging features for max performance])], [case "${enableval}" in (yes) ndebug=true ;; (no) ndebug=false ;; (*) AC_MSG_ERROR([bad value ${enableval} for --enable-ndebug]) ;; esac], [ndebug=false]) AM_CONDITIONAL([NDEBUG], [test x$ndebug = xtrue])]) dnl Checks for valgrind/valgrind.h. AC_DEFUN([OVN_CHECK_VALGRIND], [AC_CHECK_HEADERS([valgrind/valgrind.h])]) dnl Checks for thread-local storage support. dnl dnl Checks whether the compiler and linker support the C11 dnl thread_local macro from , and if so defines dnl HAVE_THREAD_LOCAL. If not, checks whether the compiler and linker dnl support the GCC __thread extension, and if so defines dnl HAVE___THREAD. AC_DEFUN([OVS_CHECK_TLS], [AC_CACHE_CHECK( [whether $CC has that supports thread_local], [ovs_cv_thread_local], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([#include static thread_local int var;], [return var;])], [ovs_cv_thread_local=yes], [ovs_cv_thread_local=no])]) if test $ovs_cv_thread_local = yes; then AC_DEFINE([HAVE_THREAD_LOCAL], [1], [Define to 1 if the C compiler and linker supports the C11 thread_local matcro defined in .]) else AC_CACHE_CHECK( [whether $CC supports __thread], [ovs_cv___thread], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([static __thread int var;], [return var;])], [ovs_cv___thread=yes], [ovs_cv___thread=no])]) if test $ovs_cv___thread = yes; then AC_DEFINE([HAVE___THREAD], [1], [Define to 1 if the C compiler and linker supports the GCC __thread extenions.]) fi fi]) dnl OVS_CHECK_ATOMIC_LIBS dnl dnl Check to see if -latomic is need for GCC atomic built-ins. AC_DEFUN([OVS_CHECK_ATOMIC_LIBS], [AC_SEARCH_LIBS([__atomic_load_8], [atomic])]) dnl OVS_CHECK_GCC4_ATOMICS dnl dnl Checks whether the compiler and linker support GCC 4.0+ atomic built-ins. dnl A compile-time only check is not enough because the compiler defers dnl unimplemented built-ins to libgcc, which sometimes also lacks dnl implementations. AC_DEFUN([OVS_CHECK_GCC4_ATOMICS], [AC_CACHE_CHECK( [whether $CC supports GCC 4.0+ atomic built-ins], [ovs_cv_gcc4_atomics], [AC_LINK_IFELSE( [AC_LANG_PROGRAM([[#include #define ovs_assert(expr) if (!(expr)) abort(); #define TEST_ATOMIC_TYPE(TYPE) \ { \ TYPE x = 1; \ TYPE orig; \ \ __sync_synchronize(); \ ovs_assert(x == 1); \ \ __sync_synchronize(); \ x = 3; \ __sync_synchronize(); \ ovs_assert(x == 3); \ \ orig = __sync_fetch_and_add(&x, 1); \ ovs_assert(orig == 3); \ __sync_synchronize(); \ ovs_assert(x == 4); \ \ orig = __sync_fetch_and_sub(&x, 2); \ ovs_assert(orig == 4); \ __sync_synchronize(); \ ovs_assert(x == 2); \ \ orig = __sync_fetch_and_or(&x, 6); \ ovs_assert(orig == 2); \ __sync_synchronize(); \ ovs_assert(x == 6); \ \ orig = __sync_fetch_and_and(&x, 10); \ ovs_assert(orig == 6); \ __sync_synchronize(); \ ovs_assert(x == 2); \ \ orig = __sync_fetch_and_xor(&x, 10); \ ovs_assert(orig == 2); \ __sync_synchronize(); \ ovs_assert(x == 8); \ }]], [dnl TEST_ATOMIC_TYPE(char); TEST_ATOMIC_TYPE(unsigned char); TEST_ATOMIC_TYPE(signed char); TEST_ATOMIC_TYPE(short); TEST_ATOMIC_TYPE(unsigned short); TEST_ATOMIC_TYPE(int); TEST_ATOMIC_TYPE(unsigned int); TEST_ATOMIC_TYPE(long int); TEST_ATOMIC_TYPE(unsigned long int); TEST_ATOMIC_TYPE(long long int); TEST_ATOMIC_TYPE(unsigned long long int); ])], [ovs_cv_gcc4_atomics=yes], [ovs_cv_gcc4_atomics=no])]) if test $ovs_cv_gcc4_atomics = yes; then AC_DEFINE([HAVE_GCC4_ATOMICS], [1], [Define to 1 if the C compiler and linker supports the GCC 4.0+ atomic built-ins.]) fi]) dnl OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE(SIZE) dnl dnl Checks __atomic_always_lock_free(SIZE, 0) AC_DEFUN([OVS_CHECK_ATOMIC_ALWAYS_LOCK_FREE], [AC_CACHE_CHECK( [value of __atomic_always_lock_free($1)], [ovs_cv_atomic_always_lock_free_$1], [AC_COMPUTE_INT( [ovs_cv_atomic_always_lock_free_$1], [__atomic_always_lock_free($1, 0)], [], [ovs_cv_atomic_always_lock_free_$1=unsupported])]) if test ovs_cv_atomic_always_lock_free_$1 != unsupported; then AC_DEFINE_UNQUOTED( [ATOMIC_ALWAYS_LOCK_FREE_$1B], [$ovs_cv_atomic_always_lock_free_$1], [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.]) fi]) dnl OVS_CHECK_POSIX_AIO AC_DEFUN([OVS_CHECK_POSIX_AIO], [AC_SEARCH_LIBS([aio_write], [rt]) AM_CONDITIONAL([HAVE_POSIX_AIO], [test "$ac_cv_search_aio_write" != no])]) dnl OVS_CHECK_INCLUDE_NEXT AC_DEFUN([OVS_CHECK_INCLUDE_NEXT], [AC_REQUIRE([gl_CHECK_NEXT_HEADERS]) gl_CHECK_NEXT_HEADERS([$1])]) dnl OVS_CHECK_PRAGMA_MESSAGE AC_DEFUN([OVS_CHECK_PRAGMA_MESSAGE], [AC_COMPILE_IFELSE([AC_LANG_PROGRAM( [[_Pragma("message(\"Checking for pragma message\")") ]])], [AC_DEFINE(HAVE_PRAGMA_MESSAGE,1,[Define if compiler supports #pragma message directive])]) ]) dnl OVS_LIBTOOL_VERSIONS sets the major, minor, micro version information for dnl OVS_LTINFO variable. This variable locks libtool information for shared dnl objects, allowing multiple versions with different ABIs to coexist. AC_DEFUN([OVS_LIBTOOL_VERSIONS], [AC_MSG_CHECKING(linker output version information) OVS_MAJOR=`echo "$PACKAGE_VERSION" | sed -e 's/[[.]].*//'` OVS_MINOR=`echo "$PACKAGE_VERSION" | sed -e "s/^$OVS_MAJOR//" -e 's/^.//' -e 's/[[.]].*//'` OVS_MICRO=`echo "$PACKAGE_VERSION" | sed -e "s/^$OVS_MAJOR.$OVS_MINOR//" -e 's/^.//' -e 's/[[^0-9]].*//'` OVS_LT_RELINFO="-release $OVS_MAJOR.$OVS_MINOR" OVS_LT_VERINFO="-version-info $LT_CURRENT:$OVS_MICRO" OVS_LTINFO="$OVS_LT_RELINFO $OVS_LT_VERINFO" AC_MSG_RESULT([libX-$OVS_MAJOR.$OVS_MINOR.so.$LT_CURRENT.0.$OVS_MICRO)]) AC_SUBST(OVS_LTINFO) ]) dnl OVS does not use C++ itself, but it provides public header files dnl that a C++ compiler should accept, so when --enable-Werror is in dnl effect and a C++ compiler is available, we enable building a C++ dnl source file that #includes all the public headers, as a way to dnl ensure that they are acceptable as C++. AC_DEFUN([OVS_CHECK_CXX], [AC_REQUIRE([AC_PROG_CXX]) AC_REQUIRE([OVS_ENABLE_WERROR]) AX_CXX_COMPILE_STDCXX([11], [], [optional]) if test $enable_Werror = yes && test $HAVE_CXX11 = 1; then enable_cxx=: AC_LANG_PUSH([C++]) AC_CHECK_HEADERS([atomic]) AC_LANG_POP([C++]) else enable_cxx=false fi AM_CONDITIONAL([HAVE_CXX], [$enable_cxx])]) dnl Checks for sphinx. AC_DEFUN([OVN_CHECK_SPHINX], [AC_CACHE_CHECK( [for sphinx], [ovs_cv_sphinx], [if type sphinx-build >/dev/null 2>&1; then ovs_cv_sphinx=yes else ovs_cv_sphinx=no fi]) AM_CONDITIONAL([HAVE_SPHINX], [test "$ovs_cv_sphinx" = yes])]) ovn-vif-25.09.0~git20250813.23884f5/m4/pkg.m4000066400000000000000000000240111476622600000172700ustar00rootroot00000000000000dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- dnl serial 11 (pkg-config-0.29.1) dnl dnl Copyright © 2004 Scott James Remnant . dnl Copyright © 2012-2015 Dan Nicholson dnl dnl This program is free software; you can redistribute it and/or modify dnl it under the terms of the GNU General Public License as published by dnl the Free Software Foundation; either version 2 of the License, or dnl (at your option) any later version. dnl dnl This program is distributed in the hope that it will be useful, but dnl WITHOUT ANY WARRANTY; without even the implied warranty of dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dnl General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program; if not, write to the Free Software dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA dnl 02111-1307, USA. dnl dnl As a special exception to the GNU General Public License, if you dnl distribute this file as part of a program that contains a dnl configuration script generated by Autoconf, you may include it under dnl the same distribution terms that you use for the rest of that dnl program. dnl PKG_PREREQ(MIN-VERSION) dnl ----------------------- dnl Since: 0.29 dnl dnl Verify that the version of the pkg-config macros are at least dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's dnl installed version of pkg-config, this checks the developer's version dnl of pkg.m4 when generating configure. dnl dnl To ensure that this macro is defined, also add: dnl m4_ifndef([PKG_PREREQ], dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) dnl dnl See the "Since" comment for each macro you use to see what version dnl of the macros you require. m4_defun([PKG_PREREQ], [m4_define([PKG_MACROS_VERSION], [0.29.1]) m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) ])dnl PKG_PREREQ dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) dnl ---------------------------------- dnl Since: 0.16 dnl dnl Search for the pkg-config tool and set the PKG_CONFIG variable to dnl first found in the path. Checks that the version of pkg-config found dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is dnl used since that's the first version where most current features of dnl pkg-config existed. AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])dnl PKG_PROG_PKG_CONFIG dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------------------------------- dnl Since: 0.18 dnl dnl Check to see whether a particular set of modules exists. Similar to dnl PKG_CHECK_MODULES(), but does not set variables or print errors. dnl dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) dnl only at the first occurence in configure.ac, so if the first place dnl it's called might be skipped (such as if it is within an "if", you dnl have to call PKG_CHECK_EXISTS manually AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_default([$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) dnl --------------------------------------------- dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting dnl pkg_failed based on the result. m4_define([_PKG_CONFIG], [if test -n "$$1"; then pkg_cv_[]$1="$$1" elif test -n "$PKG_CONFIG"; then PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` test "x$?" != "x0" && pkg_failed=yes ], [pkg_failed=yes]) else pkg_failed=untried fi[]dnl ])dnl _PKG_CONFIG dnl _PKG_SHORT_ERRORS_SUPPORTED dnl --------------------------- dnl Internal check to see if pkg-config supports short errors. AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])dnl _PKG_SHORT_ERRORS_SUPPORTED dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl -------------------------------------------------------------- dnl Since: 0.4.0 dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES might not happen, you should be sure to include an dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then AC_MSG_RESULT([no]) _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` else $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD m4_default([$4], [AC_MSG_ERROR( [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT])[]dnl ]) elif test $pkg_failed = untried; then AC_MSG_RESULT([no]) m4_default([$4], [AC_MSG_FAILURE( [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])[]dnl ]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) $3 fi[]dnl ])dnl PKG_CHECK_MODULES dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], dnl [ACTION-IF-NOT-FOUND]) dnl --------------------------------------------------------------------- dnl Since: 0.29 dnl dnl Checks for existence of MODULES and gathers its build flags with dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags dnl and VARIABLE-PREFIX_LIBS from --libs. dnl dnl Note that if there is a possibility the first call to dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to dnl include an explicit call to PKG_PROG_PKG_CONFIG in your dnl configure.ac. AC_DEFUN([PKG_CHECK_MODULES_STATIC], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl _save_PKG_CONFIG=$PKG_CONFIG PKG_CONFIG="$PKG_CONFIG --static" PKG_CHECK_MODULES($@) PKG_CONFIG=$_save_PKG_CONFIG[]dnl ])dnl PKG_CHECK_MODULES_STATIC dnl PKG_INSTALLDIR([DIRECTORY]) dnl ------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable pkgconfigdir as the location where a module dnl should install pkg-config .pc files. By default the directory is dnl $libdir/pkgconfig, but the default can be changed by passing dnl DIRECTORY. The user can override through the --with-pkgconfigdir dnl parameter. AC_DEFUN([PKG_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([pkgconfigdir], [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, [with_pkgconfigdir=]pkg_default) AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_INSTALLDIR dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) dnl -------------------------------- dnl Since: 0.27 dnl dnl Substitutes the variable noarch_pkgconfigdir as the location where a dnl module should install arch-independent pkg-config .pc files. By dnl default the directory is $datadir/pkgconfig, but the default can be dnl changed by passing DIRECTORY. The user can override through the dnl --with-noarch-pkgconfigdir parameter. AC_DEFUN([PKG_NOARCH_INSTALLDIR], [m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) m4_pushdef([pkg_description], [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) AC_ARG_WITH([noarch-pkgconfigdir], [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, [with_noarch_pkgconfigdir=]pkg_default) AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) m4_popdef([pkg_default]) m4_popdef([pkg_description]) ])dnl PKG_NOARCH_INSTALLDIR dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) dnl ------------------------------------------- dnl Since: 0.28 dnl dnl Retrieves the value of the pkg-config variable for the given module. AC_DEFUN([PKG_CHECK_VAR], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl _PKG_CONFIG([$1], [variable="][$3]["], [$2]) AS_VAR_COPY([$1], [pkg_cv_][$1]) AS_VAR_IF([$1], [""], [$5], [$4])dnl ])dnl PKG_CHECK_VAR ovn-vif-25.09.0~git20250813.23884f5/tests/000077500000000000000000000000001476622600000170715ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/tests/.gitignore000066400000000000000000000001311476622600000210540ustar00rootroot00000000000000/atconfig /atlocal /ovstest /testsuite /testsuite.dir /testsuite.log /testsuite.tmp.orig ovn-vif-25.09.0~git20250813.23884f5/tests/atlocal.in000066400000000000000000000005751476622600000210470ustar00rootroot00000000000000# Prevent logging to syslog during tests. OVS_SYSLOG_METHOD=null export OVS_SYSLOG_METHOD # Set default timeout for control utils OVS_CTL_TIMEOUT=30 export OVS_CTL_TIMEOUT # Add some default flags to make the tests run better under Address # Sanitizer, if it was used for the build. ASAN_OPTIONS=detect_leaks=1:abort_on_error=true:log_path=asan:$ASAN_OPTIONS export ASAN_OPTIONS ovn-vif-25.09.0~git20250813.23884f5/tests/automake.mk000066400000000000000000000056701476622600000212400ustar00rootroot00000000000000EXTRA_DIST += \ $(TESTSUITE_AT) \ $(SYSTEM_KMOD_TESTSUITE_AT) \ $(TESTSUITE) \ $(SYSTEM_KMOD_TESTSUITE) \ tests/atlocal.in \ $(srcdir)/package.m4 \ $(srcdir)/tests/testsuite TESTSUITE_AT = \ tests/testsuite.at \ tests/vif-plug-providers.at SYSTEM_KMOD_TESTSUITE_AT = \ tests/ovs-macros.at \ tests/ovn-macros.at \ tests/ofproto-macros.at \ tests/system-common-macros.at \ tests/system-kmod-testsuite.at \ tests/system-kmod-macros.at \ tests/system-ovn-vif-macros.at \ tests/system-plug-representor.at TESTSUITE = $(srcdir)/tests/testsuite TESTSUITE_DIR = $(abs_top_builddir)/tests/testsuite.dir SYSTEM_KMOD_TESTSUITE = $(srcdir)/tests/system-kmod-testsuite DISTCLEANFILES += tests/atconfig tests/atlocal tests/testsuite.log AUTOTEST_PATH = $(ovs_builddir)/utilities:$(ovs_builddir)/vswitchd:$(ovs_builddir)/ovsdb:$(ovs_builddir)/vtep:tests:$(PTHREAD_WIN32_DIR_DLL):$(SSL_DIR):$(ovn_builddir)/controller-vtep:$(ovn_builddir)/northd:$(ovn_builddir)/utilities:$(ovn_builddir)/controller:$(ovn_builddir)/ic export ovs_srcdir export ovn_srcdir # Run kmod tests. Assume kernel modules has been installed or linked into the # kernel check-kernel: all set $(SHELL) '$(SYSTEM_KMOD_TESTSUITE)' -C tests \ AUTOTEST_PATH='$(AUTOTEST_PATH)'; \ $(SUDO) "$$@" $(TESTSUITEFLAGS) -j1 || \ (test X'$(RECHECK)' = Xyes && $(SUDO) "$$@" --recheck) check-local: set $(SHELL) '$(TESTSUITE)' -C tests AUTOTEST_PATH=$(AUTOTEST_PATH); \ "$$@" $(TESTSUITEFLAGS) || \ (test -z "$$(find $(TESTSUITE_DIR) -name 'asan.*')" && \ test X'$(RECHECK)' = Xyes && "$$@" --recheck) AUTOTEST = $(AUTOM4TE) --language=autotest $(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 $@ $(TESTSUITE): package.m4 $(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' noinst_PROGRAMS += tests/ovstest tests_ovstest_SOURCES = \ tests/ovstest.h \ tests/ovstest.c \ lib/vif-plug-providers/representor/vif-plug-representor.c tests_ovstest_LDADD = \ $(OVS_LIBDIR)/libopenvswitch.la \ lib/netlink-devlink.$(OBJEXT) if HAVE_UDEV tests_ovstest_LDADD += \ -ludev endif tests_ovstest_CPPFLAGS = $(AM_CPPFLAGS) tests_ovstest_CPPFLAGS += \ -DOVSTEST \ -I$(OVS_LIBDIR) \ -Ilib/vif-plug-providers/representor ovn-vif-25.09.0~git20250813.23884f5/tests/ofproto-macros.at000066400000000000000000000301521476622600000223720ustar00rootroot00000000000000m4_divert_push([PREPARE_TESTS]) [ # Strips 'n_packets=...' from ovs-ofctl output. strip_n_packets () { sed 's/ n_packets=[0-9]*,//' } # Strips 'n_bytes=...' from ovs-ofctl output. strip_n_bytes () { sed 's/ n_bytes=[0-9]*,//' } # Strips 'cookie=...' from ovs-ofctl output. strip_cookie () { sed ' s/ cookie=0x[0-9a-fA-F]*,// s/cookie=0x[0-9a-fA-F]*,// ' } # Strips out uninteresting parts of ovs-ofctl output, as well as parts # that vary from one run to another. ofctl_strip () { sed ' s/ (xid=0x[0-9a-fA-F]*)// s/ duration=[0-9.]*s,// s/ cookie=0,// s/ table=0,// s/ n_packets=0,// s/ n_bytes=0,// s/ idle_age=[0-9]*,// s/ hard_age=[0-9]*,// s/dp_hash=0x[0-9a-f]*\//dp_hash=0x0\// s/recirc_id=0x[0-9a-f]*,/recirc_id=0x0,/ s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]T[0-9][0-9]:[0-9][0-9]:[0-9][0-9]Z|// s/dir\/[0-9]*\/br0.mgmt/dir\/XXXX\/br0.mgmt/ ' } # Strips out uninteresting parts of ovs-ofctl output, including n_packets=.. # n_bytes=.. ofctl_strip_all () { ofctl_strip | strip_n_packets | strip_n_bytes | strip_cookie | sort } # Filter (multiline) vconn debug messages from ovs-vswitchd.log. # Use with vconn_sub() and ofctl_strip() print_vconn_debug () { awk -F\| < ovs-vswitchd.log ' BEGIN { prt=0 } /\|vconn\|DBG\|/ { sub(/[ \t]*$/, ""); print $3 "|" $4 "|" $5; prt=1; next } $4 != "" { prt=0; next } prt==1 { sub(/[ \t]*$/, ""); print $0 } ' } vconn_sub() { sed ' s/tcp:127.0.0.1:[0-9][0-9]*:/unix:/ s/unix#[0-9]*:/unix:/ ' } ] # PARSE_LISTENING_PORT LOGFILE VARIABLE # # Parses the TCP or SSL port on which a server is listening from # LOGFILE, given that the server was told to listen on a kernel-chosen # port, and assigns the port number to shell VARIABLE. You should # specify the listening remote as ptcp:0:127.0.0.1 or # pssl:0:127.0.0.1, or the equivalent with [::1] instead of 127.0.0.1. # # Here's an example of how to use this with ovsdb-server: # # ovsdb-server --log-file --remote=ptcp:0:127.0.0.1 ... # PARSE_LISTENING_PORT([ovsdb-server.log], [TCP_PORT]) # # Now $TCP_PORT holds the listening port. m4_define([PARSE_LISTENING_PORT], [OVS_WAIT_UNTIL([$2=`sed -n 's/.*0:.*: listening on port \([[0-9]]*\)$/\1/p' "$1"` && test X != X"[$]$2"])]) start_daemon () { set "$@" -vconsole:off --detach --no-chdir --pidfile --log-file echo "$@" "$@" pidfile="$OVS_RUNDIR"/$1.pid on_exit "test -e \"$pidfile\" && kill \`cat \"$pidfile\"\`" } # sim_add SANDBOX # # Starts a new simulated Open vSwitch instance named SANDBOX. Files related to # the instance, such as logs, databases, sockets, and pidfiles, are created in # a subdirectory of the main test directory also named SANDBOX. Afterward, the # "as" command (see below) can be used to run Open vSwitch utilities in the # context of the new sandbox. # # The new sandbox starts out without any bridges. Use ovs-vsctl in the context # of the new sandbox to create a bridge, e.g.: # # sim_add hv0 # Create sandbox hv0. # as hv0 # Set hv0 as default sandbox. # ovs-vsctl add-br br0 # Add bridge br0 inside hv0. # # or: # # sim_add hv0 # as hv0 ovs-vsctl add-br br0 PKIDIR="$(cd $abs_top_builddir/tests && pwd)" sims= sim_add () { echo "adding simulator '$1'" sims="$sims $1" # Create sandbox. local d="$ovs_base"/$1 mkdir "$d" || return 1 ovs_setenv $1 # Create database and start ovsdb-server. : > "$d"/.conf.db.~lock~ as $1 ovsdb-tool create "$d"/conf.db "$ovs_srcdir"/vswitchd/vswitch.ovsschema || return 1 as $1 start_daemon ovsdb-server --remote=punix:"$d"/db.sock || return 1 # Initialize database. as $1 ovs-vsctl --no-wait -- init || return 1 # Start ovs-vswitchd as $1 start_daemon ovs-vswitchd --enable-dummy=system -vvconn -vofproto_dpif -vunixctl as $1 ovs-appctl vlog/disable-rate-limit vconn if test X$HAVE_OPENSSL = Xyes; then if test -f $PKIDIR/testpki-$1-privkey.pem; then as $1 ovs-vsctl set-ssl \ $PKIDIR/testpki-$1-privkey.pem \ $PKIDIR/testpki-$1-cert.pem \ $PKIDIR/testpki-cacert.pem \ || return 1 else echo "WARNING: No certificate created for sim '$1', check TESTPKI_CNS variable in tests/automake.mk" fi fi } # "as $1" sets the OVS_*DIR environment variables to point to $ovs_base/$1. # # "as $1 COMMAND..." sets those variables in a subshell and invokes COMMAND # there. as() { if test "X$2" != X; then (ovs_setenv $1; shift; "$@") else ovs_setenv $1 fi } # Strips 'xid=0x1234' from ovs-ofctl output. strip_xids () { sed 's/ (xid=0x[[0-9a-fA-F]]*)//' } # Changes all 'used:...' to say 'used:0.0', to make output easier to compare. strip_used () { sed 's/used:[[0-9]]\.[[0-9]]*/used:0.0/' } # Removes all 'duration=...' to make output easier to compare. strip_duration () { sed 's/duration=[[0-9]]*\.[[0-9]]*s,//' } # Strips 'ufid:...' from output, to make it easier to compare. # (ufids are random.) strip_ufid () { sed 's/ufid:[[-0-9a-f]]* //' } m4_divert_pop([PREPARE_TESTS]) m4_define([TESTABLE_LOG], [-vPATTERN:ANY:'%c|%p|%m']) # _OVS_VSWITCHD_START([vswitchd-aux-args]) # # Creates an empty database and starts ovsdb-server. # Starts ovs-vswitchd, with additional arguments 'vswitchd-aux-args'. # m4_define([_OVS_VSWITCHD_START], [dnl Create database. touch .conf.db.~lock~ AT_CHECK([ovsdb-tool create conf.db $ovs_srcdir/vswitchd/vswitch.ovsschema]) dnl Start ovsdb-server. AT_CHECK([ovsdb-server --detach --no-chdir --pidfile --log-file --remote=punix:$OVS_RUNDIR/db.sock], [0], [], [stderr]) on_exit "kill `cat ovsdb-server.pid`" AT_CHECK([[sed < stderr ' /vlog|INFO|opened log file/d /ovsdb_server|INFO|ovsdb-server (Open vSwitch)/d']]) AT_CAPTURE_FILE([ovsdb-server.log]) dnl Initialize database. AT_CHECK([ovs-vsctl --no-wait init $2]) dnl Start ovs-vswitchd. AT_CHECK([ovs-vswitchd $1 --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif -vunixctl], [0], [], [stderr]) AT_CAPTURE_FILE([ovs-vswitchd.log]) on_exit "kill_ovs_vswitchd `cat ovs-vswitchd.pid`" AT_CHECK([[sed < stderr ' /ovs_numa|INFO|Discovered /d /vlog|INFO|opened log file/d /vswitchd|INFO|ovs-vswitchd (Open vSwitch)/d /reconnect|INFO|/d /dpif_netlink|INFO|Generic Netlink family .ovs_datapath. does not exist/d /ofproto|INFO|using datapath ID/d /netdev_linux|INFO|.*device has unknown hardware address family/d /ofproto|INFO|datapath ID changed to fedcba9876543210/d /dpdk|INFO|DPDK Disabled - Use other_config:dpdk-init to enable/d /netlink_socket|INFO|netlink: could not enable listening to all nsid/d /netdev: Flow API/d /probe tc:/d /tc: Using policy/d']]) ]) # OVS_VSWITCHD_START([vsctl-args], [vsctl-output], [=override], # [vswitchd-aux-args]) # # Creates a database and starts ovsdb-server, starts ovs-vswitchd # connected to that database, calls ovs-vsctl to create a bridge named # br0 with predictable settings, passing 'vsctl-args' as additional # commands to ovs-vsctl. If 'vsctl-args' causes ovs-vsctl to provide # output (e.g. because it includes "create" commands) then 'vsctl-output' # specifies the expected output after filtering through uuidfilt. # # If a test needs to use "system" devices (as dummies), then specify # =override (literally) as the third argument. Otherwise, system devices # won't work at all (which makes sense because tests should not access a # system's real Ethernet devices). # # 'vswitchd-aux-args' provides a way to pass extra command line arguments # to ovs-vswitchd m4_define([OVS_VSWITCHD_START], [_OVS_VSWITCHD_START([--enable-dummy$3 --disable-system --disable-system-route $4]) AT_CHECK([add_of_br 0 $1 m4_if([$2], [], [], [| uuidfilt])], [0], [$2]) ]) # check_logs scans through all *.log files (except '*.log' and testsuite.log) # and reports all WARN, ERR, EMER log entries. User can add custom sed filters # in $1. m4_divert_push([PREPARE_TESTS]) check_logs () { local logs for log in *.log; do case ${log} in # ( '*.log'|testsuite.log) ;; # ( *) logs="${logs} ${log}" ;; esac done # We most notably ignore 'Broken pipe' warnings. These often and # intermittently appear in ovsdb-server.log, because *ctl commands # (e.g. ovs-vsctl, ovn-nbctl) exit right after committing a change to the # database. However, in reaction, some daemon may immediately update the # database, and this later update may cause database sending update back to # *ctl command if *ctl has not exited yet. If *ctl command exits before # the database calls send, the send fails with 'Broken pipe' or # 'not connected' depending on system. Also removes all 'connection reset' # warning logs for similar reasons (EPIPE, ENOTCONN or ECONNRESET can be # returned on a send depending on whether the peer had unconsumed data # when it closed the socket). # # We also ignore "Dropped # log messages..." messages. Otherwise, even if # we ignore the messages that were rate-limited, we can end up failing just # because of the announcement that rate-limiting happened (and in a racy, # timing-dependent way, too). sed -n "$1 /reset by peer/d /Broken pipe/d /is not connected/d /timeval.*Unreasonably long [[0-9]]*ms poll interval/d /timeval.*faults: [[0-9]]* minor, [[0-9]]* major/d /timeval.*disk: [[0-9]]* reads, [[0-9]]* writes/d /timeval.*context switches: [[0-9]]* voluntary, [[0-9]]* involuntary/d /ovs_rcu.*blocked [[0-9]]* ms waiting for .* to quiesce/d /Dropped [[0-9]]* log messages/d /|WARN|/p /|ERR|/p /|EMER|/p" ${logs} } # add_of_br BRNUM [ARG...] add_of_br () { local brnum=$1; shift local br=br$brnum local dpid=fedcba987654321$brnum local mac=aa:55:aa:55:00:0$brnum ovs-vsctl --timeout=20 \ -- add-br $br \ -- set bridge $br datapath-type=dummy \ fail-mode=secure \ other-config:datapath-id=$dpid \ other-config:hwaddr=$mac \ protocols="[[OpenFlow10,OpenFlow11,OpenFlow12,\ OpenFlow13,OpenFlow14,OpenFlow15]]" \ -- "$@" } # add_of_ports__ PORT_TYPE [--pcap] BRIDGE PNUM... # # Creates PORT_TYPE interfaces in BRIDGE named pPNUM, OpenFlow port number # PNUM, and datapath port number PNUM (the latter is a consequence of # the dummy implementation, which tries to assign datapath port # numbers based on port names). # # If --pcap is supplied then packets received from the interface will # be written to $port-rx.pcap and those sent to it to $port-tx.pcap. add_of_ports__ () { local args local pcap=false local ptype=$1 shift if test "$1" = --pcap; then pcap=: shift fi local br=$1; shift for pnum; do AS_VAR_APPEND([args], [" -- add-port $br p$pnum -- set Interface p$pnum type=$ptype ofport_request=$pnum"]) if $pcap; then AS_VAR_APPEND([args], [" -- set Interface p$pnum options:rxq_pcap=p$pnum-rx.pcap options:tx_pcap=p$pnum-tx.pcap"]) fi done echo ovs-vsctl $args ovs-vsctl $args } # add_of_ports [--pcap] BRIDGE PNUM... # add_of_ports () { add_of_ports__ dummy $@ } # add_pmd_of_ports [--pcap] BRIDGE PNUM... # add_pmd_of_ports () { add_of_ports__ dummy-pmd $@ } m4_divert_pop([PREPARE_TESTS]) # OVS_VSWITCHD_STOP([WHITELIST]) # # Gracefully stops ovs-vswitchd and ovsdb-server, checking their log files # for messages with severity WARN or higher and signaling an error if any # is present. The optional WHITELIST may contain shell-quoted "sed" # commands to delete any warnings that are actually expected, e.g.: # # OVS_VSWITCHD_STOP(["/expected error/d"]) m4_define([OVS_VSWITCHD_STOP], [AT_CHECK([check_logs $1]) OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) OVS_APP_EXIT_AND_WAIT([ovsdb-server])]) m4_define([OVS_VSWITCHD_DISABLE_TUNNEL_PUSH_POP], [AT_CHECK([ovs-appctl dpif/set-dp-features br0 tnl_push_pop false], [0]) ]) # WAIT_FOR_DUMMY_PORTS(NETDEV_DUMMY_PORT[, NETDEV_DUMMY_PORT...]) # # Wait until the netdev dummy ports are connected to each other m4_define([WAIT_FOR_DUMMY_PORTS], \ [m4_foreach([dummy_port], [$@], [ \ OVS_WAIT_WHILE([ovs-appctl netdev-dummy/conn-state dummy_port \ | grep 'unknown\|disconnected'])])]) ovn-vif-25.09.0~git20250813.23884f5/tests/ovn-macros.at000066400000000000000000000451071476622600000215120ustar00rootroot00000000000000# OVN_CLEANUP_VSWITCH(sim) # # Gracefully terminate vswitch daemons in the # specified sandbox. m4_define([OVN_CLEANUP_VSWITCH],[ echo echo "$1: clean up vswitch" as $1 OVS_APP_EXIT_AND_WAIT([ovs-vswitchd]) OVS_APP_EXIT_AND_WAIT([ovsdb-server]) ]) # OVN_CLEANUP_SBOX(sbox) # # Gracefully terminate OVN daemons in the specified # sandbox instance. The sandbox name "vtep" is treated # as a special case, and is assumed to have ovn-controller-vtep # and ovs-vtep daemons running instead of ovn-controller. m4_define([OVN_CLEANUP_SBOX],[ echo echo "$1: clean up sandbox" as $1 if test "$1" = "vtep"; then OVS_APP_EXIT_AND_WAIT([ovn-controller-vtep]) OVS_APP_EXIT_AND_WAIT([ovs-vtep]) else OVS_APP_EXIT_AND_WAIT([ovn-controller]) fi OVN_CLEANUP_VSWITCH([$1]) ]) # OVN_CLEANUP(sim [, sim ...]) # # Gracefully terminate all OVN daemons, including those in the # specified sandbox instances. m4_define([OVN_CLEANUP],[ m4_foreach([sbox], [$@], [ OVN_CLEANUP_SBOX([sbox]) ]) echo echo "clean up OVN" as ovn-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as ovn-nb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as northd OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) if test -d northd-backup; then as northd-backup OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) fi OVN_CLEANUP_VSWITCH([main]) ]) # OVN_CLEANUP_AZ(az) # # Gracefully terminate all OVN daemons, including those in the # specified sandbox instances. m4_define([OVN_CLEANUP_AZ],[ echo echo "$1: clean up availability zone" as $1/ovn-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as $1/ovn-nb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as $1/northd OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) if test -d $1/northd-backup; then as $1/northd-backup OVS_APP_EXIT_AND_WAIT([[$NORTHD_TYPE]]) fi as $1/ic OVS_APP_EXIT_AND_WAIT([ovn-ic]) ]) # OVN_CLEANUP_IC([az ...]) # # Gracefully terminate all interconnection DBs, and daemons in the # specified AZs, if any. m4_define([OVN_CLEANUP_IC],[ m4_foreach([az], [$@], [ OVN_CLEANUP_AZ([az]) ]) echo echo "clean up interconnection" as ovn-ic-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as ovn-ic-nb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) if test -d "$ovs_base"/main; then OVN_CLEANUP_VSWITCH([main]) fi ]) m4_divert_push([PREPARE_TESTS]) # ovn_init_db DATABASE [AZ] # # Creates and initializes the given DATABASE (one of "ovn-sb" or "ovn-nb"), # starts its ovsdb-server instance, and sets the appropriate environment # variable (OVN_SB_DB or OVN_NB_DB) so that ovn-sbctl or ovn-nbctl uses the # database by default. # # Usually invoked from ovn_start. ovn_init_db () { echo "${AZ:+$AZ: }creating $1 database" local as_d=$1 if test -n "$2"; then as_d=$2/$as_d fi local d=$ovs_base/$as_d mkdir "$d" || return 1 : > "$d"/.$1.db.~lock~ as $as_d ovsdb-tool create "$d"/$1.db "$ovn_srcdir"/$1.ovsschema local remote_in_db= if test X$HAVE_OPENSSL = Xyes -a X"$1" = X"ovn-sb"; then remote_in_db="--remote=db:OVN_Southbound,SB_Global,connections --private-key=$PKIDIR/testpki-test-privkey.pem --certificate=$PKIDIR/testpki-test-cert.pem --ca-cert=$PKIDIR/testpki-cacert.pem" fi as $as_d start_daemon ovsdb-server \ -vjsonrpc \ --remote=punix:"$d"/$1.sock \ $remote_in_db \ "$d"/$1.db local var=`echo $1_db | tr a-z- A-Z_` AS_VAR_SET([$var], [unix:"$d"/$1.sock]); export $var } # ovn_init_ic_db # # Creates and initializes ovn-ic-nb and ovn-ic-sb databases and starts their # ovsdb-server instances, for OVN interconnection. ovn_init_ic_db () { ovn_init_db ovn-ic-nb ovn_init_db ovn-ic-sb } # ovn_start_northd [--paused] (primary|backup) [AZ] ovn_start_northd() { local northd_args= case $1 in --paused) northd_args=--dry-run; shift ;; esac local priority=$1 local AZ=$2 local msg_prefix=${AZ:+$AZ: } local d_prefix=${AZ:+$AZ/} local suffix= case $priority in backup) suffix=-backup ;; esac case ${NORTHD_TYPE:=ovn-northd} in ovn-northd) ;; ovn-northd-ddlog) northd_args="$northd_args --ddlog-record=${AZ:+$AZ/}northd$suffix/replay.dat -v" ;; esac if test X$NORTHD_DUMMY_NUMA = Xyes; then northd_args="$northd_args --dummy-numa=\"0,0,1,1\"" fi local name=${d_prefix}northd${suffix} echo "${prefix}starting $name" test -d "$ovs_base/$name" || mkdir "$ovs_base/$name" as $name start_daemon $NORTHD_TYPE $northd_args -vjsonrpc \ --ovnnb-db=$OVN_NB_DB --ovnsb-db=$OVN_SB_DB } # ovn_start [--backup-northd=none|paused] [AZ] # # Creates and initializes ovn-sb and ovn-nb databases and starts their # ovsdb-server instance, sets appropriate environment variables so that # ovn-sbctl and ovn-nbctl use them by default, and starts ovn-northd running # against them. # # Normally this starts an active northd and a backup northd. The following # options are accepted to adjust that: # --backup-northd=none Don't start a backup northd. # --backup-northd=paused Start the backup northd in the paused state. ovn_start () { local backup_northd=: local backup_northd_options= case $1 in --backup-northd=none) backup_northd=false; shift ;; --backup-northd=paused) backup_northd_options=--paused; shift ;; esac local AZ=$1 local msg_prefix=${AZ:+$AZ: } local d_prefix=${AZ:+$AZ/} if test -n "$AZ"; then mkdir "$ovs_base"/$AZ fi ovn_init_db ovn-sb $1; ovn-sbctl init ovn_init_db ovn-nb $1; ovn-nbctl init if test -n "$1"; then ovn-nbctl set NB_Global . name=$1 fi ovn_start_northd primary $AZ if $backup_northd; then ovn_start_northd $backup_northd_options backup $AZ fi if test X$HAVE_OPENSSL = Xyes; then # Create the SB DB pssl+RBAC connection. Ideally we could pre-create # SB_Global and Connection with ovsdb-tool transact at DB creation # time, but unfortunately that does not work, northd-ddlog will replace # the SB_Global record on startup. ovn-sbctl \ -- --id=@c create connection \ target=\"pssl:0:127.0.0.1\" role=ovn-controller \ -- add SB_Global . connections @c local d=$ovs_base if test -n "$AZ"; then d=$d/$AZ fi PARSE_LISTENING_PORT([$d/ovn-sb/ovsdb-server.log], [TCP_PORT]) var="SSL_OVN_SB_DB" AS_VAR_SET([$var], [ssl:127.0.0.1:$TCP_PORT]); export $var fi if test -n "$AZ"; then ovn-nbctl --wait=sb sync || exit $? echo "${msg_prefix}starting ovn-ic" mkdir "$ovs_base"/$d_prefix/ic as $d_prefix/ic start_daemon ovn-ic -v \ --ovnnb-db=$OVN_NB_DB --ovnsb-db=$OVN_SB_DB \ --ic-nb-db=unix:"$ovs_base"/ovn-ic-nb/ovn-ic-nb.sock \ --ic-sb-db=unix:"$ovs_base"/ovn-ic-sb/ovn-ic-sb.sock fi if test X$NORTHD_USE_DP_GROUPS = Xyes; then ovn-nbctl set NB_Global . options:use_logical_dp_groups=true else ovn-nbctl set NB_Global . options:use_logical_dp_groups=false fi if test X$NORTHD_USE_PARALLELIZATION = Xyes; then ovn-nbctl set NB_Global . options:use_parallel_build=true fi } # Interconnection networks. # # When multiple sandboxed Open vSwitch instances exist, one will inevitably # want to connect them together. These commands allow for that. Conceptually, # an interconnection network is a switch for which these functions make it easy # to plug into other switches in other sandboxed Open vSwitch instances. # Interconnection networks are implemented as bridges in a switch named "main", # so to use interconnection networks please avoid working with that switch # directly. # net_add NETWORK # # Creates a new interconnection network named NETWORK. net_add () { test -d "$ovs_base"/main || sim_add main || return 1 as main ovs-vsctl add-br "$1" } # net_attach NETWORK BRIDGE # # Adds a new port to BRIDGE in the default sandbox (as set with as()) and plugs # it into the NETWORK interconnection network. NETWORK must already have been # created by a previous invocation of net_add. The default sandbox must not be # "main". net_attach () { local net=$1 bridge=$2 local port=${sandbox}_$bridge as main ovs-vsctl \ -- add-port $net $port \ -- set Interface $port options:pstream="punix:$ovs_base/main/$port.sock" options:rxq_pcap="$ovs_base/main/$port-rx.pcap" options:tx_pcap="$ovs_base/main/$port-tx.pcap" \ || return 1 ovs-vsctl \ -- set Interface $bridge options:tx_pcap="$ovs_base/$sandbox/$bridge-tx.pcap" options:rxq_pcap="$ovs_base/$sandbox/$bridge-rx.pcap" \ -- add-port $bridge ${bridge}_$net \ -- set Interface ${bridge}_$net options:stream="unix:$ovs_base/main/$port.sock" options:rxq_pcap="$ovs_base/$sandbox/${bridge}_$net-rx.pcap" options:tx_pcap="$ovs_base/$sandbox/${bridge}_$net-tx.pcap" \ || return 1 } # ovn_az_attach AZ NETWORK BRIDGE IP [MASKLEN] ovn_az_attach() { local az=$1 net=$2 bridge=$3 ip=$4 masklen=${5-24} encap=${6-geneve,vxlan} net_attach $net $bridge || return 1 mac=`ovs-vsctl get Interface $bridge mac_in_use | sed s/\"//g` arp_table="$arp_table $sandbox,$bridge,$ip,$mac" ovs-appctl netdev-dummy/ip4addr $bridge $ip/$masklen >/dev/null || return 1 ovs-appctl ovs/route/add $ip/$masklen $bridge >/dev/null || return 1 local ovn_remote if test X"$az" = XNONE; then if test X$HAVE_OPENSSL = Xyes; then ovn_remote=$SSL_OVN_SB_DB else ovn_remote=unix:$ovs_base/ovn-sb/ovn-sb.sock fi else ovn_remote=unix:$ovs_base/$az/ovn-sb/ovn-sb.sock fi ovs-vsctl \ -- set Open_vSwitch . external-ids:hostname=$sandbox \ -- set Open_vSwitch . external-ids:system-id=$sandbox \ -- set Open_vSwitch . external-ids:ovn-remote=$ovn_remote \ -- set Open_vSwitch . external-ids:ovn-encap-type=$encap \ -- set Open_vSwitch . external-ids:ovn-encap-ip=$ip \ -- --may-exist add-br br-int \ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true \ || return 1 start_daemon ovn-controller --enable-dummy-vif-plug || return 1 } # ovn_attach NETWORK BRIDGE IP [MASKLEN] # # First, this command attaches BRIDGE to interconnection network NETWORK, just # like "net_attach NETWORK BRIDGE". Second, it configures (simulated) IP # address IP (with network mask length MASKLEN, which defaults to 24) on # BRIDGE. Finally, it configures the Open vSwitch database to work with OVN # and starts ovn-controller. ovn_attach() { ovn_az_attach NONE $@ } # ovn_setenv AZ ovn_setenv () { local d=$ovs_base/$1 AS_VAR_SET([OVN_NB_DB], [unix:"$d"/ovn-nb/ovn-nb.sock]); export $var AS_VAR_SET([OVN_SB_DB], [unix:"$d"/ovn-sb/ovn-sb.sock]); export $var } # ovs_as AZ ovn_as() { if test "X$2" != X; then (ovn_setenv $1; shift; "$@") else ovn_setenv $1 fi } # OVN_POPULATE_ARP # # This pre-populates the ARP tables of all of the OVN instances that have been # started with ovn_attach(). That means that packets sent from one hypervisor # to another never get dropped or delayed by ARP resolution, which makes # testing easier. ovn_populate_arp__() { for e1 in $arp_table; do set `echo $e1 | sed 's/,/ /g'`; sb1=$1 br1=$2 ip=$3 mac=$4 for e2 in $arp_table; do set `echo $e2 | sed 's/,/ /g'`; sb2=$1 br2=$2 if test $sb1,$br1 != $sb2,$br2; then as $sb2 ovs-appctl tnl/neigh/set $br2 $ip $mac || return 1 fi done done } m4_divert_pop([PREPARE_TESTS]) OVS_START_SHELL_HELPERS # check COMMAND... # # Runs COMMAND and checks that it succeeds without any output. check() { echo "$@" AT_CHECK(["$@"]) } parse_db() { case $1 in (*:*) echo ${1%%:*} ;; (*) echo sb ;; esac } parse_table() { case $1 in (*:*) echo ${1##*:} ;; (*) echo $1 ;; esac } # count_rows TABLE [CONDITION...] # # Prints the number of rows in TABLE (that satisfy CONDITION). # Uses the southbound db by default; set DB=nb for the northbound database. count_rows() { local db=$(parse_db $1) table=$(parse_table $1); shift ovn-${db}ctl --format=table --no-headings find $table "$@" | wc -l } # check_row_count [DATABASE:]TABLE COUNT [CONDITION...] # # Checks that TABLE contains COUNT rows (that satisfy CONDITION). # The default DATABASE is "sb". check_row_count() { local db=$(parse_db $1) table=$(parse_table $1); shift local count=$1; shift local found=$(count_rows $db:$table "$@") echo echo "Checking for $count rows in $db $table${1+ with $*}... found $found" if test "$count" != "$found"; then ovn-${db}ctl list $table AT_FAIL_IF([:]) fi } # wait_row_count [DATABASE:]TABLE COUNT [CONDITION...] # # Waits until TABLE contains COUNT rows (that satisfy CONDITION). # The default DATABASE is "sb". wait_row_count() { local db=$(parse_db $1) table=$(parse_table $1); shift local count=$1; shift local a=$1 b=$2 c=$3 d=$4 e=$5 echo "Waiting until $count rows in $db $table${1+ with $*}..." OVS_WAIT_UNTIL([test $count = $(count_rows $db:$table $a $b $c $d $e)],[ echo "$db table $table has the following rows. $(count_rows $db:$table $a $b $c $d $e) rows match instead of expected $count:" ovn-${db}ctl list $table]) } # fetch_column [DATABASE:]TABLE COLUMN [CONDITION...] # # Fetches and prints all the values of COLUMN in the rows of TABLE # (that satisfy CONDITION), sorting the results lexicographically. # The default DATABASE is "sb". fetch_column() { local db=$(parse_db $1) table=$(parse_table $1) column=${2-_uuid}; shift; shift # Using "echo" removes spaces and newlines. echo $(ovn-${db}ctl --bare --columns $column find $table "$@" | sort) } # check_column EXPECTED [DATABASE:]TABLE COLUMN [CONDITION...] # # Fetches all of the values of COLUMN in the rows of TABLE (that # satisfy CONDITION), and compares them against EXPECTED (ignoring # order). # # The default DATABASE is "sb". check_column() { local expected=$1 db=$(parse_db $2) table=$(parse_table $2) column=${3-_uuid}; shift; shift; shift local found=$(ovn-${db}ctl --bare --columns $column find $table "$@") # Sort the expected and found values. local found=$(for d in $found; do echo $d; done | sort) local expected=$(for d in $expected; do echo $d; done | sort) echo echo "Checking values in $db $table${1+ with $*} against $expected... found $found" if test "$found" != "$expected"; then ovn-${db}ctl list $table AT_FAIL_IF([:]) fi } # wait_column EXPECTED [DATABASE:]TABLE [COLUMN [CONDITION...]] # # Wait until all of the values of COLUMN in the rows of TABLE (that # satisfy CONDITION) equal EXPECTED (ignoring order). # # The default DATABASE is "sb". # # COLUMN defaults to _uuid if unspecified. wait_column() { local expected=$(for d in $1; do echo $d; done | sort) local db=$(parse_db $2) table=$(parse_table $2) column=${3-_uuid}; shift; shift; shift local a=$1 b=$2 c=$3 d=$4 e=$5 echo echo "Waiting until $column in $db $table${1+ with $*} is $expected..." OVS_WAIT_UNTIL([ found=$(ovn-${db}ctl --bare --columns $column find $table $a $b $c $d $e) found=$(for d in $found; do echo $d; done | sort) test "$expected" = "$found" ], [ echo "$column in $db table $table has value $found, from the following rows:" ovn-${db}ctl list $table]) } # wait_for_ports_up [PORT...] # # With arguments, waits for specified Logical_Switch_Ports to come up. # Without arguments, waits for all "plain" and router # Logical_Switch_Ports to come up. wait_for_ports_up() { if test $# = 0; then wait_row_count nb:Logical_Switch_Port 0 up!=true type='""' wait_row_count nb:Logical_Switch_Port 0 up!=true type=router else for port; do wait_row_count nb:Logical_Switch_Port 1 up=true name=$port done fi } # reset_pcap_file iface pcap_file # Resets the pcap file associates with OVS interface. should be used # with dummy datapath. reset_iface_pcap_file() { local iface=$1 local pcap_file=$2 check rm -f dummy-*.pcap check ovs-vsctl -- set Interface $iface options:tx_pcap=dummy-tx.pcap \ options:rxq_pcap=dummy-rx.pcap OVS_WAIT_WHILE([test 24 = $(wc -c dummy-tx.pcap | cut -d " " -f1)]) check rm -f ${pcap_file}*.pcap check ovs-vsctl -- set Interface $iface options:tx_pcap=${pcap_file}-tx.pcap \ options:rxq_pcap=${pcap_file}-rx.pcap OVS_WAIT_WHILE([test 24 = $(wc -c ${pcap_file}-tx.pcap | cut -d " " -f1)]) } # Receive a packet on a dummy netdev interface. If we expect packets to be # recorded, then wait until the pcap file reflects the change. netdev_dummy_receive() { local interface="$1" local packet="$2" local hv="$3" local pcap_file="$4" if test -n "pcap_file" ; then ts_old=$(stat -c %y "$pcap_file") fi if test -n "$hv" ; then as "$hv" ovs-appctl netdev-dummy/receive "$interface" "$packet" else ovs-appctl netdev-dummy/receive "$interface" "$packet" fi if test -n "$pcap_file" ; then OVS_WAIT_WHILE( [ts_new=$(stat -c %y "$pcap_file") test "$ts_new" = "$ts_old"]) fi } OVS_END_SHELL_HELPERS m4_define([OVN_POPULATE_ARP], [AT_CHECK(ovn_populate_arp__, [0], [ignore])]) # Defines a versions of a test with all combinations of northd and # datapath groups. m4_define([OVN_FOR_EACH_NORTHD], [m4_foreach([NORTHD_TYPE], [ovn-northd, ovn-northd-ddlog], [m4_foreach([NORTHD_USE_DP_GROUPS], [yes, no], [$1 ])])]) # Some tests aren't prepared for dp groups to be enabled. m4_define([OVN_FOR_EACH_NORTHD_WITHOUT_DP_GROUPS], [m4_foreach([NORTHD_TYPE], [ovn-northd, ovn-northd-ddlog], [m4_foreach([NORTHD_USE_DP_GROUPS], [no], [$1 ])])]) # Test parallelization with dp groups enabled and disabled m4_define([OVN_NORTHD_PARALLELIZATION_DUMMY], [ m4_pushdef([NORTHD_TYPE], [ovn_northd]) m4_pushdef(NORTHD_DUMMY_NUMA, [yes]) [m4_foreach([NORTHD_USE_DP_GROUPS], [yes, no], [[NORTHD_USE_PARALLELIZATION], [yes] ])]]) m4_define([OVN_NORTHD_PARALLELIZATION_NO_DUMMY], [ m4_pushdef([NORTHD_TYPE], [ovn_northd]) m4_pushdef(NORTHD_DUMMY_NUMA, [no]) [m4_foreach([NORTHD_USE_DP_GROUPS], [yes, no], [[NORTHD_USE_PARALLELIZATION], [yes] ])]]) # Use --dummy-numa if system has low cores m4_define([HOST_HAS_LOW_CORES], [ if test $(nproc) -lt 4; then : $1 else : $2 fi ]) m4_define([NORTHD_PARALLELIZATION], [ HOST_HAS_LOW_CORES([OVN_NORTHD_PARALLELIZATION_DUMMY], [OVN_NORTHD_PARALLELIZATION_NO_DUMMY]) ]) ovn-vif-25.09.0~git20250813.23884f5/tests/ovs-macros.at000066400000000000000000000305721476622600000215170ustar00rootroot00000000000000AT_TESTED([ovs-vswitchd]) AT_TESTED([ovs-vsctl]) m4_include([m4/compat.m4]) dnl Make AT_SETUP automatically do some things for us: dnl - Run the ovs_init() shell function as the first step in every test. dnl - If NORTHD_TYPE is defined, then append it to the test name and dnl set it as a shell variable as well. dnl - Skip the test if it's for ovn-northd-ddlog but it didn't get built. m4_rename([AT_SETUP], [OVS_AT_SETUP]) m4_define([AT_SETUP], [OVS_AT_SETUP($@[]m4_ifdef([NORTHD_TYPE], [ -- NORTHD_TYPE])[]m4_ifdef([NORTHD_USE_DP_GROUPS], [ -- dp-groups=NORTHD_USE_DP_GROUPS])) m4_ifdef([NORTHD_TYPE], [[NORTHD_TYPE]=NORTHD_TYPE ])dnl m4_ifdef([NORTHD_USE_DP_GROUPS], [[NORTHD_USE_DP_GROUPS]=NORTHD_USE_DP_GROUPS ])dnl m4_if(NORTHD_TYPE, [ovn-northd-ddlog], [dnl AT_SKIP_IF([test $TEST_DDLOG = no]) ])dnl ovs_init ]) dnl Make AT_CLEANUP check for Address Sanitizer errors as the last step dnl in every test. m4_rename([AT_CLEANUP], [OVS_AT_CLEANUP]) m4_define([AT_CLEANUP], [ovs_cleanup OVS_AT_CLEANUP($@) ]) dnl OVS_START_SHELL_HELPERS...OVS_END_SHELL_HELPERS may bracket shell dnl function definitions that invoke AT_CHECK and other Autotest macros dnl that can ordinarily be run only within AT_SETUP...AT_CLEANUP. m4_define([OVS_START_SHELL_HELPERS], [m4_ifdef([AT_ingroup], [m4_fatal([$0: AT_SETUP and OVS_DEFINE_SHELL_HELPERS may not nest])]) m4_define([AT_ingroup]) m4_define([AT_capture_files]) m4_divert_push([PREPARE_TESTS])]) m4_define([OVS_END_SHELL_HELPERS], [ m4_divert_pop([PREPARE_TESTS]) m4_undefine([AT_capture_files]) m4_undefine([AT_ingroup])]) m4_divert_push([PREPARE_TESTS]) [ # Set ovs_base to the base directory in which the test is running and # initialize the OVS_*DIR environment variables to point to this # directory. ovs_init() { ovs_base=`pwd` trap ovs_on_exit 0 : > cleanup ovs_setenv } # Catch testsuite error condition and cleanup test environment by tearing down # all interfaces and processes spawned. # User has an option to leave the test environment in error state so that system # can be poked around to get more information. User can enable this option by setting # environment variable OVS_PAUSE_TEST=1. User needs to press CTRL-D to resume the # cleanup operation. ovs_pause() { echo "=====================================================" echo "Set following environment variable to use various ovs utilities" echo "export OVS_RUNDIR=$ovs_base" echo "Press ENTER to continue: " read } ovs_on_exit () { if [ ! -z "${OVS_PAUSE_TEST}" ] && [ -z $at_verbose ]; then trap '' INT ovs_pause fi . "$ovs_base/cleanup" } # With no parameter or an empty parameter, sets the OVS_*DIR # environment variables to point to $ovs_base, the base directory in # which the test is running. # # With a parameter, sets them to $ovs_base/$1. ovs_setenv() { sandbox=$1 ovs_dir=$ovs_base${1:+/$1} OVS_RUNDIR=$ovs_dir; export OVS_RUNDIR OVN_RUNDIR=$ovs_dir; export OVN_RUNDIR OVS_LOGDIR=$ovs_dir; export OVS_LOGDIR OVS_DBDIR=$ovs_dir; export OVS_DBDIR OVS_SYSCONFDIR=$ovs_dir; export OVS_SYSCONFDIR OVS_PKGDATADIR=$ovs_dir; export OVS_PKGDATADIR } # Prints the integers from $1 to $2, increasing by $3 (default 1) on stdout. seq () { if test $# = 1; then set 1 $1 fi while test $1 -le $2; do echo $1 set `expr $1 + ${3-1}` $2 $3 done } if test "$IS_WIN32" = "yes"; then pwd () { command pwd -W "$@" } diff () { command diff --strip-trailing-cr "$@" } # tskill is more effective than taskkill but it isn't always installed. if (tskill //?) >/dev/null 2>&1; then :; else tskill () { taskkill //F //PID $1 >/dev/null; } fi kill () { signal= retval=0 for arg; do case $arg in -*) signal=$arg ;; [1-9][0-9]*) # tasklist always returns 0. # If pid does exist, there will be a line with the pid. if tasklist //fi "PID eq $arg" | grep $arg >/dev/null; then if test "X$signal" != "X-0"; then tskill $arg fi else retval=1 fi ;; esac done return $retval } fi # parent_pid PID # # Prints the PID of the parent of process PID. parent_pid () { # Using "ps" is portable to any POSIX system, but busybox "ps" (used in # e.g. Alpine Linux) is noncompliant, so we use a Linux-specific approach # when it's available. We check the format of the status file to avoid # the NetBSD file with the same name but different contents. if egrep '^PPid:[[:space:]]*[0-9]*$' /proc/$1/status > /dev/null 2>&1; then sed -n 's/^PPid: \([0-9]*\)/\1/p' /proc/$1/status else ps -o ppid= -p $1 fi } # kill_ovs_vswitchd [PID] # # Signal the ovs-vswitchd daemon to exit gracefully and wait for it to # terminate or kill it if that takes too long. # # It is used to cleanup all sorts of tests and results. It can't assume # any state, including the availability of PID file which can be provided. kill_ovs_vswitchd () { # Use provided PID or save the current PID if available. TMPPID=$1 if test -z "$TMPPID"; then TMPPID=$(cat $OVS_RUNDIR/ovs-vswitchd.pid 2>/dev/null) fi # Tell the daemon to terminate gracefully ovs-appctl --timeout=10 -t ovs-vswitchd exit --cleanup 2>/dev/null # Nothing else to be done if there is no PID test -z "$TMPPID" && return for i in 1 2 3 4 5 6 7 8 9; do # Check if the daemon is alive. kill -0 $TMPPID 2>/dev/null || return # Fallback to whole number since POSIX doesn't require # fractional times to work. sleep 0.1 || sleep 1 done # Make sure it is terminated. kill $TMPPID } # Normalize the output of 'wc' to match POSIX. # POSIX says 'wc' should print "%d %d %d", but GNU prints "%7d %7d %7d". # POSIX says 'wc -l' should print "%d %s", but BSD prints "%8d". # # This fixes all of those (it will screw up filenames that contain # multiple sequential spaces, but that doesn't really matter). wc () { command wc "$@" | tr -s ' ' ' ' | sed 's/^ *//' } uuidfilt () { $PYTHON "$top_srcdir"/tests/uuidfilt.py "$@" } # run_as PROGRAM_NAME COMMAND [ARG...] # # Runs a command with argv[0] set to PROGRAM_NAME, if possible, in a # subshell. Most utilities print argc[0] as part of their messages, # so this makes it easier to figure out which particular utility # prints a message if a bunch of identical processes are running. # # Not all shells support "exec -a NAME", so test for it. if (exec -a myname true 2>/dev/null); then run_as () { (exec -a "$@") } else run_as () { shift (exec "$@") } fi ] m4_divert_pop([PREPARE_TESTS]) OVS_START_SHELL_HELPERS ovs_cleanup() { if test "$(echo asan.*)" != 'asan.*'; then echo "Address Sanitizer reported errors in:" asan.* cat asan.* AT_FAIL_IF([:]) fi } ovs_wait () { echo "$1: waiting $2..." >&AS_MESSAGE_LOG_FD # First try the condition without waiting. if ovs_wait_cond; then echo "$1: wait succeeded immediately" >&AS_MESSAGE_LOG_FD; return 0; fi # Try a quick sleep, so that the test completes very quickly # in the normal case. POSIX doesn't require fractional times to # work, so this might not work. sleep 0.1 if ovs_wait_cond; then echo "$1: wait succeeded quickly" >&AS_MESSAGE_LOG_FD; return 0; fi # Then wait up to OVS_CTL_TIMEOUT seconds. local timer for timer in `seq 1 "$OVS_CTL_TIMEOUT"`; do sleep 1 if ovs_wait_cond; then echo "$1: wait succeeded after $timer seconds" >&AS_MESSAGE_LOG_FD; return 0; fi done echo "$1: wait failed after $timer seconds" >&AS_MESSAGE_LOG_FD ovs_wait_failed AT_FAIL_IF([:]) } OVS_END_SHELL_HELPERS m4_define([OVS_WAIT], [dnl ovs_wait_cond () { $1 } ovs_wait_failed () { : $2 } ovs_wait "AS_ESCAPE([$3])" "AS_ESCAPE([$4])" ]) dnl OVS_WAIT_UNTIL(COMMAND[, IF-FAILED]) dnl dnl Executes shell COMMAND in a loop until it returns dnl zero return code. If COMMAND did not return dnl zero code within reasonable time limit, then dnl the test fails. In that case, runs IF-FAILED dnl before aborting. m4_define([OVS_WAIT_UNTIL], [OVS_WAIT([$1], [$2], [AT_LINE], [until $1])]) dnl OVS_WAIT_FOR_OUTPUT(COMMAND, EXIT-STATUS, STDOUT, STDERR) dnl OVS_WAIT_FOR_OUTPUT_UNQUOTED(COMMAND, EXIT-STATUS, STDOUT, STDERR) dnl dnl Executes shell COMMAND in a loop until it exits with status EXIT-STATUS, dnl prints STDOUT on stdout, and prints STDERR on stderr. If this doesn't dnl happen within a reasonable time limit, then the test fails. dnl dnl The UNQUOTED version expands shell $variables, $(command)s, and so on. dnl The plain version does not m4_define([OVS_WAIT_FOR_OUTPUT__], [dnl wait_expected_status=m4_if([$2], [], [0], [$2]) ovs_wait_command() { $1 } ovs_wait_cond() { ovs_wait_command >wait-stdout 2>wait-stderr wait_status=$? (test $wait_status = $wait_expected_status && $at_diff wait-expected-stdout wait-stdout && $at_diff wait-expected-stderr wait-stderr) >/dev/null 2>&1 } ovs_wait_failed () { if test $wait_status != $wait_expected_status; then echo "exit status $wait_status != expected $wait_expected_status" fi $at_diff wait-expected-stdout wait-stdout $at_diff wait-expected-stderr wait-stderr } ovs_wait "AS_ESCAPE([AT_LINE])" "for output from AS_ESCAPE([$1])" ]) m4_define([OVS_WAIT_FOR_OUTPUT], [dnl AT_DATA([wait-expected-stdout], [$3]) AT_DATA([wait-expected-stderr], [$4]) OVS_WAIT_FOR_OUTPUT__([$1], [$2]) ]) m4_define([OVS_WAIT_FOR_OUTPUT_UNQUOTED], [dnl cat > wait-expected-stdout < wait-expected-stderr </dev/null])]) dnl OVS_APP_EXIT_AND_WAIT_BY_TARGET(TARGET, PIDFILE) dnl dnl Ask the daemon identified by TARGET to exit, via ovs-appctl (using the target dnl argument), and then wait for it to exit. m4_define([OVS_APP_EXIT_AND_WAIT_BY_TARGET], [AT_CHECK([test -e $2]) TMPPID=$(cat $2) AT_CHECK([ovs-appctl --timeout=10 --target=[$1] exit]) OVS_WAIT_WHILE([kill -0 $TMPPID 2>/dev/null])]) dnl on_exit "COMMAND" dnl dnl Add the shell COMMAND to a collection executed when the current test dnl completes, as a cleanup action. (The most common use is to kill a dnl daemon started by the test. This is important to prevent tests that dnl start daemons from hanging at exit.) dnl dnl Cleanup commands are executed in the reverse order of calls to this dnl function. m4_divert_text([PREPARE_TESTS], [dnl on_exit () { (echo "$1"; cat cleanup) > cleanup.tmp mv cleanup.tmp cleanup } ]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AS_VAR_APPEND], [m4_divert_text([PREPARE_TESTS], [as_var_append () { eval $1=\$$1\$2 } ]) m4_define([AS_VAR_APPEND], [as_var_append $1 $2])]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AT_CHECK_UNQUOTED], [m4_define([AT_CHECK_UNQUOTED], [_AT_CHECK([$1], [$2], AS_ESCAPE(m4_dquote(m4_expand([$3])), [""]), AS_ESCAPE(m4_dquote(m4_expand([$4])),[""]), [$5], [$6])])]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AT_SKIP_IF], [m4_define([AT_SKIP_IF], [AT_CHECK([($1) \ && exit 77 || exit 0], [0], [ignore], [ignore])])]) dnl Autoconf 2.63 compatibility verison of macro introduced in Autoconf 2.64: m4_ifndef([AT_FAIL_IF], [m4_define([AT_FAIL_IF], [AT_CHECK([($1) \ && exit 99 || exit 0], [0], [ignore], [ignore])])]) ovn-vif-25.09.0~git20250813.23884f5/tests/ovsdb-macros.at000066400000000000000000000066761476622600000220350ustar00rootroot00000000000000dnl OVSDB_INIT([$1]) dnl dnl Creates an empty database named $1. m4_define([OVSDB_INIT], [AT_CHECK( [ovsdb-tool create $1 $abs_top_srcdir/vswitchd/vswitch.ovsschema], [0], [stdout], [ignore]) AT_CHECK( [[ovsdb-tool transact $1 \ '["Open_vSwitch", {"op": "insert", "table": "Open_vSwitch", "row": {}}]']], [0], [ignore], [ignore])]) # OVSDB_CHECK_POSITIVE(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ]) # # Runs "test-ovsdb TEST-OVSDB-ARGS" and checks that it exits with # status 0 and prints OUTPUT on stdout. # # TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS. m4_define([OVSDB_CHECK_POSITIVE], [AT_SETUP([$1]) AT_KEYWORDS([ovsdb positive $4]) AT_CHECK([test-ovsdb $2], [0], [$3 ], []) AT_CLEANUP]) # OVSDB_CHECK_POSITIVE_PY(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ], # [PY-CHECK]) # # Runs "test-ovsdb.py TEST-OVSDB-ARGS" and checks that it exits with # status 0 and prints OUTPUT on stdout. # # PY-CHECK is expanded before the check. It can check for features of the # Python implementation that are required for the test to pass. # # TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS. m4_define([OVSDB_CHECK_POSITIVE_PY], [AT_SETUP([$1]) $6 AT_KEYWORDS([ovsdb positive Python $4]) AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py $2], [0], [$3 ], []) AT_CLEANUP]) # OVSDB_CHECK_POSITIVE_CPY(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], # [PREREQ], [PY3-CHECK]) # # Runs identical C and Python tests, as specified. m4_define([OVSDB_CHECK_POSITIVE_CPY], [OVSDB_CHECK_POSITIVE([$1 - C], [$2], [$3], [$4], [$5]) OVSDB_CHECK_POSITIVE_PY([$1 - Python3], [$2], [$3], [$4], [$5], [$7])]) # OVSDB_CHECK_NEGATIVE(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ]) # # Runs "test-ovsdb TEST-OVSDB-ARGS" and checks that it exits with # status 1 and that its output on stdout contains substring OUTPUT. # TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS. m4_define([OVSDB_CHECK_NEGATIVE], [AT_SETUP([$1]) AT_KEYWORDS([ovsdb negative $4]) AT_CHECK([test-ovsdb $2], [1], [], [stderr]) m4_assert(m4_len([$3])) AT_CHECK( [if grep -F -e "AS_ESCAPE([$3])" stderr then : else exit 99 fi], [0], [ignore], [ignore]) AT_CLEANUP]) # OVSDB_CHECK_NEGATIVE_PY(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], [PREREQ]) # # Runs "test-ovsdb TEST-OVSDB-ARGS" and checks that it exits with # status 1 and that its output on stdout contains substring OUTPUT. # TITLE is provided to AT_SETUP and KEYWORDS to AT_KEYWORDS. m4_define([OVSDB_CHECK_NEGATIVE_PY], [AT_SETUP([$1]) AT_KEYWORDS([ovsdb negative $4]) AT_CHECK([$PYTHON3 $srcdir/test-ovsdb.py $2], [1], [], [stderr]) m4_assert(m4_len([$3])) AT_CHECK( [if grep -F -e "AS_ESCAPE([$3])" stderr then : else exit 99 fi], [0], [ignore], [ignore]) AT_CLEANUP]) # OVSDB_CHECK_NEGATIVE_CPY(TITLE, TEST-OVSDB-ARGS, OUTPUT, [KEYWORDS], # [PREREQ]) # # Runs identical C and Python tests, as specified. m4_define([OVSDB_CHECK_NEGATIVE_CPY], [OVSDB_CHECK_NEGATIVE([$1 - C], [$2], [$3], [$4], [$5]) OVSDB_CHECK_NEGATIVE_PY([$1 - Python3], [$2], [$3], [$4], [$5])]) OVS_START_SHELL_HELPERS ovsdb_client_wait() { ovsdb-client -vconsole:warn -vreconnect:err -vjsonrpc:err -vtimeval:off -vfile -vsyslog:off -vvlog:off wait "$@" } OVS_END_SHELL_HELPERS ovn-vif-25.09.0~git20250813.23884f5/tests/ovstest.c000066400000000000000000000101301476622600000207370ustar00rootroot00000000000000/* * 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. */ /* The mother of all test programs that links with libopevswitch.la */ #include #undef NDEBUG #include #include #include #include "command-line.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" #include "ovstest.h" #include "util.h" static struct ovs_cmdl_command *commands = NULL; static size_t n_commands = 0; static size_t allocated_commands = 0; static void add_command(struct ovs_cmdl_command *cmd) { const struct ovs_cmdl_command nil = {NULL, NULL, 0, 0, NULL, OVS_RO}; while (n_commands + 1 >= allocated_commands) { commands = x2nrealloc(commands, &allocated_commands, sizeof *cmd); } commands[n_commands] = *cmd; commands[n_commands + 1] = nil; n_commands++; } #define OVSTEST_USAGE \ "TEST [TESTARGS] where 'TEST' is a string, 'TESTARGS' are optional \n"\ "arguments of the TEST" static void flush_help_string(struct ds *ds) { if (ds->length > 2) { ds->length -= 2; printf ("%s\n", ds_cstr(ds)); ds_clear(ds); } } static void help(struct ovs_cmdl_context *ctx OVS_UNUSED) { const struct ovs_cmdl_command *p; struct ds test_names = DS_EMPTY_INITIALIZER; const int linesize = 70; printf("%s: the big test executable\n" "usage: %s TEST [TESTARGS]\n" "where TEST is one of the following. \n\n", program_name, program_name); for (p = commands; p->name != NULL; p++) { if (*p->name != '-') { /* Skip internal commands */ ds_put_format(&test_names, "%s, ", p->name); if ((test_names.length) >= linesize) { flush_help_string(&test_names); } } } flush_help_string(&test_names); ds_destroy(&test_names); } static void add_top_level_commands(void) { struct ovs_cmdl_command help_cmd = {"--help", NULL, 0, 0, help, OVS_RO }; add_command(&help_cmd); } void ovstest_register(const char *test_name, ovs_cmdl_handler f) { struct ovs_cmdl_command test_cmd; test_cmd.name = test_name; test_cmd.usage = NULL; test_cmd.min_args = 0; test_cmd.max_args = INT_MAX; test_cmd.handler = f; test_cmd.mode = OVS_RO; add_command(&test_cmd); } static void cleanup(void) { if (allocated_commands) { free(commands); } } int main(int argc, char *argv[]) { set_program_name(argv[0]); if (argc < 2) { ovs_fatal(0, "expect test program to be specified; " "use --help for usage"); } /* Disable logging to the console when running tests. * * By default, OVN and OVS errors and warnings are written to * stderr. GNU Autotest automatically fails a test if unexpected * data is written to stderr. This causes two problems: * 1) Unit tests that attempt off-nominal code paths may * fail because of a warning message in OVN or OVS. To get * around this, it is common for tests to pass "[ignore]" * to AT_CHECK's stderr parameter so that OVN/OVS log messages * do not cause failures. But... * 2) Passing "[ignore]" makes it so that unit tests cannot * then print their own messages to stderr to help debug * test failures. */ vlog_set_levels(NULL, VLF_CONSOLE, VLL_OFF); add_top_level_commands(); if (argc > 1) { struct ovs_cmdl_context ctx = { .argc = argc - 1, .argv = argv + 1, }; ovs_cmdl_run_command(&ctx, commands); } cleanup(); return 0; } ovn-vif-25.09.0~git20250813.23884f5/tests/ovstest.h000066400000000000000000000047261476622600000207620ustar00rootroot00000000000000/* * 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 OVSTEST_H #define OVSTEST_H #include "compiler.h" #include "command-line.h" /* Overview * ======== * * OVS tests directory contains many small test programs. One down side * of building them as individual programs is that they all have to be * linked whenever a library function is modified. * * ovstest is an attempt to improve the overall build time by linking * all test programs into a single program, ovs-test. Regardless of * the number of test programs, linking will be done only once to produce * ovstest. * * With ovstest, each test programs now becomes a sub program of ovstest. * For example, 'mytest' program, can now be invoked as 'ovstest mytest'. * * 'ovstest --help' will list all test programs can be invoked. * * The 'Usage' section below documents how to add a new sub program * to ovstest using OVSTEST_REIGSTER macros. */ typedef void (*ovstest_func)(int argc, char *argv[]); void ovstest_register(const char *test_name, ovs_cmdl_handler f); /* Usage * ===== * * For each sub test program, its 'main' program should be named as * '_main()'. * * The 'main' programs should be registered with ovstest as a sub program. * OVSTEST_REGISTER(name, function) * * 'name' will be name of the test program. It is expected as argv[1] when * invoking with ovstest. * * 'function' is the 'main' program mentioned above. * * Example: * ---------- * * Suppose the test program is called my-test.c * ... * * static void * my_test_main(int argc, char *argv[]) * { * .... * } * * OVSTEST_REGISTER("my-test", my_test_main); */ #define OVSTEST_REGISTER(name, function) \ static void \ ovstest_wrapper_##function##__(struct ovs_cmdl_context *ctx) \ { \ function(ctx->argc, ctx->argv); \ } \ OVS_CONSTRUCTOR(register_##function) { \ ovstest_register(name, ovstest_wrapper_##function##__); \ } #endif ovn-vif-25.09.0~git20250813.23884f5/tests/system-common-macros.at000066400000000000000000000267121476622600000235230ustar00rootroot00000000000000# DEL_NAMESPACES(ns [, ns ... ]) # # Delete namespaces from the running OS m4_define([DEL_NAMESPACES], [m4_foreach([ns], [$@], [ip netns del ns ]) ] ) # ADD_NAMESPACES(ns [, ns ... ]) # # Add new namespaces, if ns exists, the old one # will be remove before new ones are installed. m4_define([ADD_NAMESPACES], [m4_foreach([ns], [$@], [DEL_NAMESPACES(ns) AT_CHECK([ip netns add ns || return 77]) on_exit "DEL_NAMESPACES(ns)" ip netns exec ns sysctl -w net.netfilter.nf_conntrack_helper=0 ]) ] ) # NS_EXEC([namespace], [command]) # # Execute 'command' in 'namespace' m4_define([NS_EXEC], [ip netns exec $1 sh << NS_EXEC_HEREDOC $2 NS_EXEC_HEREDOC]) # NS_CHECK_EXEC([namespace], [command], other_params...) # # Wrapper for AT_CHECK that executes 'command' inside 'namespace'. # 'other_params' as passed as they are to AT_CHECK. m4_define([NS_CHECK_EXEC], [ AT_CHECK([NS_EXEC([$1], [$2])], m4_shift(m4_shift($@))) ] ) # ADD_BR([name], [vsctl-args]) # # Expands into the proper ovs-vsctl commands to create a bridge with the # appropriate type, and allows additional arguments to be passed. m4_define([ADD_BR], [ovs-vsctl _ADD_BR([$1]) -- $2]) # ADD_INT([port], [namespace], [ovs-br], [ip_addr]) # # Add an internal port to 'ovs-br', then shift it into 'namespace' and # configure it with 'ip_addr' (specified in CIDR notation). m4_define([ADD_INT], [ AT_CHECK([ovs-vsctl add-port $3 $1 -- set int $1 type=internal]) AT_CHECK([ip link set $1 netns $2]) NS_CHECK_EXEC([$2], [ip addr add $4 dev $1]) NS_CHECK_EXEC([$2], [ip link set dev $1 up]) ] ) # ADD_VETH([port], [namespace], [ovs-br], [ip_addr] [mac_addr], [gateway], # [ip_addr_flags]) # # Add a pair of veth ports. 'port' will be added to name space 'namespace', # and "ovs-'port'" will be added to ovs bridge 'ovs-br'. # # The 'port' in 'namespace' will be brought up with static IP address # with 'ip_addr' in CIDR notation. # # Optionally, one can specify the 'mac_addr' for 'port' and the default # 'gateway'. # # The existing 'port' or 'ovs-port' will be removed before new ones are added. # m4_define([ADD_VETH], [ AT_CHECK([ip link add $1 type veth peer name ovs-$1 || return 77]) CONFIGURE_VETH_OFFLOADS([$1]) AT_CHECK([ip link set $1 netns $2]) AT_CHECK([ip link set dev ovs-$1 up]) AT_CHECK([ovs-vsctl add-port $3 ovs-$1 -- \ set interface ovs-$1 external-ids:iface-id="$1"]) NS_CHECK_EXEC([$2], [ip addr add $4 dev $1 $7]) NS_CHECK_EXEC([$2], [ip link set dev $1 up]) if test -n "$5"; then NS_CHECK_EXEC([$2], [ip link set dev $1 address $5]) fi if test -n "$6"; then NS_CHECK_EXEC([$2], [ip route add default via $6]) fi on_exit "ip link del ovs-$1" ] ) # ADD_VETH_BOND([ports], [namespace], [ovs-br], [bond], [mode], [ip_addr]) # # Add a set of veth port pairs. Ports named in the list 'ports' will be added # to 'namespace', and the corresponding port names, prefixed by 'ovs-' will # be included in an OVS bond 'bond' which is added to bridge 'ovs-br'. # # The 'bond' in 'namespace' will be brought up with static IP address # with 'ip_addr' in CIDR notation. # m4_define([ADD_VETH_BOND], [ BONDPORTS="" for port in $1; do AT_CHECK([ip link add $port type veth peer name ovs-$port]) CONFIGURE_VETH_OFFLOADS([$port]) AT_CHECK([ip link set $port netns $2]) AT_CHECK([ip link set dev ovs-$port up]) BONDPORTS="$BONDPORTS ovs-$port" on_exit 'ip link del ovs-$port' done NS_CHECK_EXEC([$2], [ip link add name $4 type bond]) case "$(echo $5 | sed 's/.*lacp=//' | sed 's/ .*//')" in active|passive) NS_CHECK_EXEC([$2], [sh -c "echo 802.3ad > /sys/class/net/$4/bonding/mode"]) NS_CHECK_EXEC([$2], [sh -c "echo 100 > /sys/class/net/$4/bonding/miimon"]) ;; esac for port in $1; do NS_CHECK_EXEC([$2], [ip link set dev $port master $4]) done NS_CHECK_EXEC([$2], [ip addr add $6 dev $4]) NS_CHECK_EXEC([$2], [ip link set dev $4 up]) AT_CHECK([ovs-vsctl add-bond $3 ovs-$4 $BONDPORTS $5]) on_exit 'ip link del ovs-$4' ] ) # ADD_VLAN([port], [namespace], [vlan-id], [ip-addr]) # # Add a VLAN device named 'port' within 'namespace'. It will be configured # with the ID 'vlan-id' and the address 'ip-addr'. m4_define([ADD_VLAN], [ NS_CHECK_EXEC([$2], [ip link add link $1 name $1.$3 type vlan proto 802.1q id $3]) NS_CHECK_EXEC([$2], [ip link set dev $1.$3 up]) NS_CHECK_EXEC([$2], [ip addr add dev $1.$3 $4]) ] ) # ADD_SVLAN([port], [namespace], [vlan-id], [ip-addr]) # # Add a SVLAN device named 'port' within 'namespace'. It will be configured # with the ID 'vlan-id' and the address 'ip-addr'. m4_define([ADD_SVLAN], [ NS_CHECK_EXEC([$2], [ip link add link $1 name $1.$3 type vlan proto 802.1ad id $3]) NS_CHECK_EXEC([$2], [ip link set dev $1.$3 up]) NS_CHECK_EXEC([$2], [ip addr add dev $1.$3 $4]) NS_CHECK_EXEC([$2], [ip link set $1.$3 mtu 1496]) ] ) # ADD_CVLAN([port], [namespace], [vlan-id], [ip-addr]) # # Similar to ADD_VLAN(), but sets MTU. Lower MTU here instead of increase MTU # on bridge/SVLAN because older kernels didn't work. # m4_define([ADD_CVLAN], [ ADD_VLAN([$1], [$2], [$3], [$4]) NS_CHECK_EXEC([$2], [ip link set $1.$3 mtu 1492]) ] ) # ADD_OVS_TUNNEL([type], [bridge], [port], [remote-addr], [overlay-addr], # [tunnel-args]) # # Add an ovs-based tunnel device in the root namespace, with name 'port' and # type 'type'. The tunnel device will be configured as point-to-point with the # 'remote-addr' as the underlay address of the remote tunnel endpoint. # # 'port will be configured with the address 'overlay-addr'. # m4_define([ADD_OVS_TUNNEL], [AT_CHECK([ovs-vsctl add-port $2 $3 -- \ set int $3 type=$1 options:remote_ip=$4 $6]) AT_CHECK([ip addr add dev $2 $5]) AT_CHECK([ip link set dev $2 up]) AT_CHECK([ip link set dev $2 mtu 1450]) on_exit 'ip addr del dev $2 $5' ] ) # ADD_OVS_TUNNEL6([type], [bridge], [port], [remote-addr], [overlay-addr], # [tunnel-args]) # # Same as ADD_OVS_TUNNEL, but drops MTU enough for the IPv6 underlay. # m4_define([ADD_OVS_TUNNEL6], [ADD_OVS_TUNNEL([$1], [$2], [$3], [$4], [$5], [$6]) AT_CHECK([ip link set dev $2 mtu 1430]) ] ) # ADD_NATIVE_TUNNEL([type], [port], [namespace], [remote-addr], [overlay-addr], # [type-args], [link-args]) # # Add a native tunnel device within 'namespace', with name 'port' and type # 'type'. The tunnel device will be configured as point-to-point with the # 'remote-addr' as the underlay address of the remote tunnel endpoint (as # viewed from the perspective of that namespace). # # 'port' will be configured with the address 'overlay-addr'. 'type-args' is # made available so that additional arguments can be passed to "ip link add" # for configuring specific link type's arguments, for instance to configure # the vxlan destination port. 'link-args' is made for arguments passed to # "ip link set", for instance to configure MAC address. # m4_define([ADD_NATIVE_TUNNEL], [NS_CHECK_EXEC([$3], [ip link add dev $2 type $1 remote $4 $6]) NS_CHECK_EXEC([$3], [ip addr add dev $2 $5]) NS_CHECK_EXEC([$3], [ip link set dev $2 mtu 1450 $7 up]) ] ) # ADD_NATIVE_TUNNEL6([type], [port], [namespace], [remote-addr], [overlay-addr], # [type-args], [link-args]) # # Same as ADD_NATIVE_TUNNEL, but drops MTU enough for the IPv6 underlay. # m4_define([ADD_NATIVE_TUNNEL6], [ADD_NATIVE_TUNNEL([$1], [$2], [$3], [$4], [$5], [$6], [$7]) NS_CHECK_EXEC([$3], [ip link set dev $2 mtu 1430]) ] ) # FORMAT_PING([]) # # Strip variant pieces from ping output so the output can be reliably compared. # m4_define([FORMAT_PING], [grep "transmitted" | sed 's/time.*ms$/time 0ms/']) # STRIP_MONITOR_CSUM([]) # # Strip the csum value from ovs-ofctl monitor. # m4_define([STRIP_MONITOR_CSUM], [grep "csum:" | sed 's/csum:.*/csum: /']) # FORMAT_CT([ip-addr]) # # Strip content from the piped input which would differ from test to test # and limit the output to the rows containing 'ip-addr'. # m4_define([FORMAT_CT], [[grep "dst=$1" | sed -e 's/port=[0-9]*/port=/g' -e 's/id=[0-9]*/id=/g' -e 's/state=[0-9_A-Z]*/state=/g' | sort | uniq]]) # NETNS_DAEMONIZE([namespace], [command], [pidfile]) # # Run 'command' as a background process within 'namespace' and record its pid # to 'pidfile' to allow cleanup on exit. # m4_define([NETNS_DAEMONIZE], [ip netns exec $1 $2 & echo $! > $3 echo "kill \`cat $3\`" >> cleanup ] ) # OVS_CHECK_FIREWALL() # # Check if firewalld is active, skip the test if it is on. # The following command currently only supports RHEL and CentOS. m4_define([OVS_CHECK_FIREWALL], [AT_SKIP_IF([systemctl status firewalld 2>&1 | grep running > /dev/null])]) # OVS_START_L7([namespace], [protocol]) # # Start a server serving 'protocol' within 'namespace'. The server will exit # when the test finishes. # m4_define([OVS_START_L7], [PIDFILE=$(mktemp $2XXX.pid) echo $PIDFILE > l7_pid_file NETNS_DAEMONIZE([$1], [[$PYTHON $srcdir/test-l7.py $2]], [$PIDFILE]) dnl netstat doesn't print http over IPv6 as "http6"; drop the number. PROTO=$(echo $2 | sed -e 's/\([[a-zA-Z]]*\).*/\1/') OVS_WAIT_UNTIL([NS_EXEC([$1], [netstat -l | grep $PROTO])]) ] ) # OVS_CHECK_VXLAN() # # Do basic check for vxlan functionality, skip the test if it's not there. m4_define([OVS_CHECK_VXLAN], [AT_SKIP_IF([! ip link add foo type vxlan help 2>&1 | grep dstport >/dev/null]) OVS_CHECK_FIREWALL()]) # OVS_CHECK_VXLAN_UDP6ZEROCSUM() m4_define([OVS_CHECK_VXLAN_UDP6ZEROCSUM], [AT_SKIP_IF([! ip link add foo type vxlan help 2>&1 | grep udp6zerocsum >/dev/null]) OVS_CHECK_FIREWALL()]) # OVS_CHECK_VXLAN_GPE() m4_define([OVS_CHECK_VXLAN_GPE], [OVS_CHECK_VXLAN() AT_SKIP_IF([! ip link add foo type vxlan help 2>&1 | grep gpe >/dev/null])]) # OVS_CHECK_GRE() m4_define([OVS_CHECK_GRE], [AT_SKIP_IF([! ip link add foo type gretap help 2>&1 | grep gretap >/dev/null]) OVS_CHECK_FIREWALL()]) # OVS_CHECK_ERSPAN() m4_define([OVS_CHECK_ERSPAN], [AT_SKIP_IF([! ip link add foo type erspan help 2>&1 | grep erspan >/dev/null]) OVS_CHECK_FIREWALL()]) # OVS_CHECK_GRE_L3() m4_define([OVS_CHECK_GRE_L3], [AT_SKIP_IF([! ip link add foo type gre help 2>&1 | grep "gre " >/dev/null]) OVS_CHECK_FIREWALL()]) # OVS_CHECK_GENEVE() m4_define([OVS_CHECK_GENEVE], [AT_SKIP_IF([! ip link add foo type geneve help 2>&1 | grep geneve >/dev/null]) OVS_CHECK_FIREWALL()]) # OVS_CHECK_GENEVE_UDP6ZEROCSUM() m4_define([OVS_CHECK_GENEVE_UDP6ZEROCSUM], [AT_SKIP_IF([! ip link add foo type geneve help 2>&1 | grep udp6zerocsum >/dev/null]) OVS_CHECK_FIREWALL()]) # OVS_CHECK_8021AD() m4_define([OVS_CHECK_8021AD], [AT_SKIP_IF([! grep -q "VLAN header stack length probed as" ovs-vswitchd.log]) AT_SKIP_IF([[test `sed -n 's/.*VLAN header stack length probed as \([0-9]\+\).*/\1/p' ovs-vswitchd.log` -lt 2]])]) # OVS_CHECK_IPROUTE_ENCAP() m4_define([OVS_CHECK_IPROUTE_ENCAP], [AT_SKIP_IF([! ip route help 2>&1 |grep encap >/dev/null])]) # OVS_CHECK_CT_CLEAR() m4_define([OVS_CHECK_CT_CLEAR], [AT_SKIP_IF([! grep -q "Datapath supports ct_clear action" ovs-vswitchd.log])]) # OVS_CHECK_CT_ZERO_SNAT() m4_define([OVS_CHECK_CT_ZERO_SNAT], [AT_SKIP_IF([! grep -q "Datapath supports ct_zero_snat" ovs-vswitchd.log])])) ovn-vif-25.09.0~git20250813.23884f5/tests/system-kmod-macros.at000066400000000000000000000134301476622600000231560ustar00rootroot00000000000000# _ADD_BR([name]) # # Expands into the proper ovs-vsctl commands to create a bridge with the # appropriate type and properties m4_define([_ADD_BR], [[add-br $1 -- set Bridge $1 protocols=OpenFlow10,OpenFlow11,OpenFlow12,OpenFlow13,OpenFlow14,OpenFlow15 fail-mode=secure ]]) # OVS_TRAFFIC_VSWITCHD_START([vsctl-args], [vsctl-output], [=override]) # # Creates a database and starts ovsdb-server, starts ovs-vswitchd # connected to that database, calls ovs-vsctl to create a bridge named # br0 with predictable settings, passing 'vsctl-args' as additional # commands to ovs-vsctl. If 'vsctl-args' causes ovs-vsctl to provide # output (e.g. because it includes "create" commands) then 'vsctl-output' # specifies the expected output after filtering through uuidfilt. # # Best-effort loading of all available vport modules is performed. # m4_define([OVS_TRAFFIC_VSWITCHD_START], [AT_CHECK([modprobe openvswitch]) on_exit 'modprobe -r openvswitch' m4_foreach([mod], [[vport_geneve], [vport_gre], [vport_lisp], [vport_stt], [vport_vxlan]], [modprobe -q mod || echo "Module mod not loaded." on_exit 'modprobe -q -r mod' ]) on_exit 'ovs-dpctl del-dp ovs-system' on_exit 'ovs-appctl dpctl/flush-conntrack' _OVS_VSWITCHD_START([]) dnl Add bridges, ports, etc. AT_CHECK([ovs-vsctl -- _ADD_BR([br0]) -- $1 m4_if([$2], [], [], [| uuidfilt])], [0], [$2]) ]) # OVS_TRAFFIC_VSWITCHD_STOP([WHITELIST], [extra_cmds]) # # Gracefully stops ovs-vswitchd and ovsdb-server, checking their log files # for messages with severity WARN or higher and signaling an error if any # is present. The optional WHITELIST may contain shell-quoted "sed" # commands to delete any warnings that are actually expected, e.g.: # # OVS_TRAFFIC_VSWITCHD_STOP(["/expected error/d"]) # # 'extra_cmds' are shell commands to be executed afte OVS_VSWITCHD_STOP() is # invoked. They can be used to perform additional cleanups such as name space # removal. m4_define([OVS_TRAFFIC_VSWITCHD_STOP], [OVS_VSWITCHD_STOP([$1]) AT_CHECK([:; $2]) ]) # CONFIGURE_VETH_OFFLOADS([VETH]) # # The kernel datapath has no problem with offloads and veths. Nothing # to do here. m4_define([CONFIGURE_VETH_OFFLOADS], ) # CHECK_CONNTRACK() # # Perform requirements checks for running conntrack tests, and flush the # kernel conntrack tables when the test is finished. # m4_define([CHECK_CONNTRACK], m4_foreach([mod], [[nf_conntrack_ipv4], [nf_conntrack_ipv6], [nf_nat_ftp], [nf_nat_tftp]], [modprobe mod || echo "Module mod not loaded." on_exit 'modprobe -r mod' ]) sysctl -w net.netfilter.nf_conntrack_helper=0 on_exit 'ovstest test-netlink-conntrack flush' ] ) # CHECK_CONNTRACK_ALG() # # Perform requirements checks for running conntrack ALG tests. The kernel # supports ALG, so no check is needed. # m4_define([CHECK_CONNTRACK_ALG]) # CHECK_CONNTRACK_LOCAL_STACK() # # Perform requirements checks for running conntrack tests with local stack. # The kernel always supports reading the connection state of an skb coming # from an internal port, without an explicit ct() action, so no check is # needed. m4_define([CHECK_CONNTRACK_LOCAL_STACK]) # CHECK_CONNTRACK_FRAG_OVERLAP() # # The kernel does not support overlapping fragments checking. m4_define([CHECK_CONNTRACK_FRAG_OVERLAP], [ AT_SKIP_IF([:]) ]) # CHECK_CONNTRACK_NAT() # # Perform requirements checks for running conntrack NAT tests. The kernel # always supports NAT, so no check is needed. # m4_define([CHECK_CONNTRACK_NAT]) # CHECK_CT_DPIF_PER_ZONE_LIMIT() # # Perform requirements checks for running ovs-dpctl ct-[set|get|del]-limits per # zone. The kernel datapath does support this feature. Will remove this check # after both kernel and userspace datapath support it. m4_define([CHECK_CT_DPIF_PER_ZONE_LIMIT]) # CHECK_CT_DPIF_SET_GET_MAXCONNS() # # Perform requirements checks for running ovs-dpctl ct-set-maxconns or # ovs-dpctl ct-get-maxconns. The kernel datapath does not support this # feature. m4_define([CHECK_CT_DPIF_SET_GET_MAXCONNS], [ AT_SKIP_IF([:]) ]) # CHECK_CT_DPIF_GET_NCONNS() # # Perform requirements checks for running ovs-dpctl ct-get-nconns. The # kernel datapath does not support this feature. m4_define([CHECK_CT_DPIF_GET_NCONNS], [ AT_SKIP_IF([:]) ]) # DPCTL_SET_MIN_FRAG_SIZE() # # The kernel does not support this command. m4_define([DPCTL_SET_MIN_FRAG_SIZE], [ ]) # DPCTL_MODIFY_FRAGMENTATION() # # The kernel does not support this command. m4_define([DPCTL_MODIFY_FRAGMENTATION], [ ]) # DPCTL_CHECK_FRAGMENTATION_PASS() # # The kernel does not support this command. m4_define([DPCTL_CHECK_FRAGMENTATION_PASS], [ ]) # DPCTL_CHECK_V6_FRAGMENTATION_PASS() # # The kernel does not support this command. m4_define([DPCTL_CHECK_V6_FRAGMENTATION_PASS], [ ]) # DPCTL_CHECK_FRAGMENTATION_FAIL() # # The kernel does not support this command. m4_define([DPCTL_CHECK_FRAGMENTATION_FAIL], [ ]) # OVS_CHECK_MIN_KERNEL([minversion], [minsublevel]) # # Skip test if kernel version falls below minversion.minsublevel m4_define([OVS_CHECK_MIN_KERNEL], [ version=$(uname -r | sed -e 's/\./ /g' | awk '{print $ 1}') sublevel=$(uname -r | sed -e 's/\./ /g' | awk '{print $ 2}') AT_SKIP_IF([test $version -lt $1 || ( test $version -eq $1 && test $sublevel -lt $2 )]) ]) # OVS_CHECK_KERNEL_EXCL([minversion], [minsublevel], [maxversion], [maxsublevel]) # # Skip test if kernel version falls between minversion.minsublevel and maxversion.maxsublevel m4_define([OVS_CHECK_KERNEL_EXCL], [ version=$(uname -r | sed -e 's/\./ /g' | awk '{print $ 1}') sublevel=$(uname -r | sed -e 's/\./ /g' | awk '{print $ 2}') AT_SKIP_IF([ ! ( test $version -lt $1 || ( test $version -eq $1 && test $sublevel -lt $2 ) || test $version -gt $3 || ( test $version -eq $3 && test $sublevel -gt $4 ) ) ]) ]) ovn-vif-25.09.0~git20250813.23884f5/tests/system-kmod-testsuite.at000066400000000000000000000016671476622600000237340ustar00rootroot00000000000000AT_INIT AT_COPYRIGHT([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.]) m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS]) m4_include([tests/ovs-macros.at]) m4_include([tests/ovsdb-macros.at]) m4_include([tests/ofproto-macros.at]) m4_include([tests/system-common-macros.at]) m4_include([tests/system-kmod-macros.at]) m4_include([tests/ovn-macros.at]) m4_include([tests/system-ovn-vif-macros.at]) m4_include([tests/system-plug-representor.at]) ovn-vif-25.09.0~git20250813.23884f5/tests/system-ovn-vif-macros.at000066400000000000000000000005141476622600000236070ustar00rootroot00000000000000# NETDEVSIM_START([dev-num], [nports]) # # Loads the netdevsim kernel module and creates a new netdevsim device numbered # 'dev-num' with 'nports' physical ports. m4_define([NETDEVSIM_START], [AT_CHECK([modprobe netdevsim]) on_exit 'modprobe -r netdevsim' AT_CHECK([echo "$1 $2" > /sys/bus/netdevsim/new_device] [0], []) ]) ovn-vif-25.09.0~git20250813.23884f5/tests/system-plug-representor.at000066400000000000000000000135751476622600000242710ustar00rootroot00000000000000# CREATE_FAKE_SMART_NIC_NETDEV_TMPDIR([netdev_name], [dst_dir], [pf_mac]) # # Populates 'dst_dir' with the files required to fake a Smart NIC DPU sysfs # netdev directory as consumed by OVN VIF representor implementation. # # NOTE 'dst_dir' will be removed on exit! m4_define([CREATE_FAKE_SMART_NIC_NETDEV_TMPDIR], on_exit 'rm -rf $2' mkdir -p $2/smart_nic/pf cp /sys/class/net/$1/ifindex $2/ cat < $2/smart_nic/pf/config MAC : 00:53:00:00:00:42 MaxTxRate : 0 MinTxRate : 0 State : Follow EOF ) # BIND_MOUNT_NETDEV([netdev_name], [src_dir]) # # Replaces the sysfs representation of netdev as identified by 'netdev_name' # with the contents of 'src_dir'. m4_define([BIND_MOUNT_NETDEV], mount_point="$(realpath /sys/class/net/$1/device)/net/$1" on_exit 'umount $mount_point' mount --bind $2 $mount_point ) AT_BANNER([system-ovn-vif-plug-representor]) AT_SETUP([Runtime update of lookup tables - pcipf hw_addr]) OVS_CHECK_MIN_KERNEL(5, 13) ovn_start OVS_TRAFFIC_VSWITCHD_START() ADD_BR([br-int]) # Set external-ids in br-int needed for ovn-controller ovs-vsctl \ -- set Open_vSwitch . external-ids:system-id=hv1 \ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true # Start ovn-controller start_daemon ovn-controller # To confirm the OVN VIF representor lookup tables are successfully updated # at runtime we load the netdevsim module and create the PF and VF representor # ports after starting the ovn-controller. NETDEVSIM_START([10], [1]) $DEVLINK port add netdevsim/netdevsim10/10 flavour pcipf pfnum 0 $DEVLINK port function set netdevsim/netdevsim10/10 hw_addr 00:53:00:00:00:42 echo 4 > /sys/class/net/eni10np1/device/sriov_numvfs $DEVLINK dev eswitch set netdevsim/netdevsim10 mode switchdev $DEVLINK port show ovn-nbctl ls-add foo ovn-nbctl lsp-add foo foo1 \ -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2" \ -- lsp-set-options foo1 requested-chassis=hv1 \ vif-plug-type=representor \ "vif-plug:representor:pf-mac=00:53:00:00:00:42" \ "vif-plug:representor:vf-num=0" # The first couple of ovn-controller main loop iterations will fail to lookup # the representor due to interface renaming etc. Since there is nothing else # going on in the system we extend the timeout here to ensure the representor # port is eventually plugged. In a real world system both system startup # sequence and other changes to the database will ensure faster operation. _current_ovs_ctl_timeout=$OVS_CTL_TIMEOUT export OVS_CTL_TIMEOUT=120 wait_for_ports_up foo1 export OVS_CTL_TIMEOUT=$_current_ovs_ctl_timeout OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as ovn-nb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as northd OVS_APP_EXIT_AND_WAIT([ovn-northd]) # We need some extra ignore sentences here as the netdevsim does not behave # just like any normal PCI netdev would. as OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d /connection dropped.*/d /cannot get.*STP.*/d /ethtool command.*/d /could not open network device.*/d /Unable to find PHYSICAL representor.*/d"]) AT_CLEANUP # We currently skip this test due to the netdevsim driver not currently # properly simulating the association between PF and VF representors. AT_SETUP([Runtime update of lookup tables - compat mode]) AT_SKIP_IF([true]) OVS_CHECK_MIN_KERNEL(5, 13) ovn_start OVS_TRAFFIC_VSWITCHD_START() ADD_BR([br-int]) # Set external-ids in br-int needed for ovn-controller ovs-vsctl \ -- set Open_vSwitch . external-ids:system-id=hv1 \ -- set Open_vSwitch . external-ids:ovn-remote=unix:$ovs_base/ovn-sb/ovn-sb.sock \ -- set Open_vSwitch . external-ids:ovn-encap-type=geneve \ -- set Open_vSwitch . external-ids:ovn-encap-ip=169.0.0.1 \ -- set bridge br-int fail-mode=secure other-config:disable-in-band=true # In compat mode we need to create the PF and VF representors prior to starting # the ovn-controller to be able to fake the sysfs layout. NETDEVSIM_START([10], [1]) $DEVLINK port add netdevsim/netdevsim10/10 flavour pcipf pfnum 1 echo 4 > /sys/class/net/eni10np1/device/sriov_numvfs $DEVLINK dev eswitch set netdevsim/netdevsim10 mode switchdev fake_smart_nic_netdev=$(mktemp -d) CREATE_FAKE_SMART_NIC_NETDEV_TMPDIR(eni10np1, $fake_smart_nic_netdev, 00:53:00:00:00:42) BIND_MOUNT_NETDEV(eni10np1, $fake_smart_nic_netdev) $DEVLINK port show # Start ovn-controller start_daemon ovn-controller ovn-nbctl ls-add foo ovn-nbctl lsp-add foo foo1 \ -- lsp-set-addresses foo1 "f0:00:00:01:02:03 192.168.1.2" \ -- lsp-set-options foo1 requested-chassis=hv1 \ vif-plug-type=representor \ "vif-plug:representor:pf-mac=00:53:00:00:00:42" \ "vif-plug:representor:vf-num=0" # The first couple of ovn-controller main loop iterations will fail to lookup # the representor due to interface renaming etc. Since there is nothing else # going on in the system we extend the timeout here to ensure the representor # port is eventually plugged. In a real world system other changes to the # database will ensure faster operation. _current_ovs_ctl_timeout=$OVS_CTL_TIMEOUT export OVS_CTL_TIMEOUT=120 wait_for_ports_up foo1 export OVS_CTL_TIMEOUT=$_current_ovs_ctl_timeout OVS_APP_EXIT_AND_WAIT([ovn-controller]) as ovn-sb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as ovn-nb OVS_APP_EXIT_AND_WAIT([ovsdb-server]) as northd OVS_APP_EXIT_AND_WAIT([ovn-northd]) # We need some extra ignore sentences here as the netdevsim does not behave # just like any normal PCI netdev would. as OVS_TRAFFIC_VSWITCHD_STOP(["/failed to query port patch-.*/d /connection dropped.*/d /cannot get.*STP.*/d /ethtool command.*/d /could not open network device.*/d"]) AT_CLEANUP ovn-vif-25.09.0~git20250813.23884f5/tests/testsuite.at000066400000000000000000000013041476622600000214460ustar00rootroot00000000000000AT_INIT AT_COPYRIGHT([Copyright (c) 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.]) m4_ifdef([AT_COLOR_TESTS], [AT_COLOR_TESTS]) m4_include([tests/vif-plug-providers.at]) ovn-vif-25.09.0~git20250813.23884f5/tests/vif-plug-providers.at000066400000000000000000000011701476622600000231620ustar00rootroot00000000000000AT_BANNER([vif-plug-providers unit tests]) AT_SETUP([representor data store]) AT_CHECK([ovstest test-vif-plug-representor store-phy], [0], []) AT_CHECK([ovstest test-vif-plug-representor store-port], [0], []) AT_CHECK([ovstest test-vif-plug-representor store-rename-expected], [0], []) AT_CLEANUP AT_SETUP([representor data store devlink interface]) AT_CHECK([ ovstest test-vif-plug-representor store-devlink-port-update], [0], []) AT_CHECK([ ovstest test-vif-plug-representor store-devlink-port-delete], [0], []) AT_CHECK([ ovstest test-vif-plug-representor store-devlink-port-update-compat], [0], []) AT_CLEANUP ovn-vif-25.09.0~git20250813.23884f5/utilities/000077500000000000000000000000001476622600000177425ustar00rootroot00000000000000ovn-vif-25.09.0~git20250813.23884f5/utilities/.gitignore000066400000000000000000000000111476622600000217220ustar00rootroot00000000000000/devlink ovn-vif-25.09.0~git20250813.23884f5/utilities/automake.mk000066400000000000000000000002641476622600000221030ustar00rootroot00000000000000if LINUX noinst_PROGRAMS += utilities/devlink utilities_devlink_SOURCES = utilities/devlink.c utilities_devlink_LDADD = \ lib/libovn-vif.la \ -L$(OVS_LIBDIR) -lopenvswitch endif ovn-vif-25.09.0~git20250813.23884f5/utilities/devlink.c000066400000000000000000000175701476622600000215540ustar00rootroot00000000000000/* * Copyright (c) 2021 Canonical * * 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 #include #include "netlink.h" #include "netlink-socket.h" #include "netlink-devlink.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" #include "packets.h" VLOG_DEFINE_THIS_MODULE(devlink); enum { CMD_DUMP, CMD_MONITOR, }; static const char *CMD_NAME[] = { "dump", "monitor", }; static void usage(void) { printf("usage: %s MODE\n" "where MODE is one of 'dump' or 'monitor'.\n", program_name); } static void print_port(struct dl_port *port_entry) { VLOG_INFO("bus_name: '%s'", port_entry->bus_name); VLOG_INFO("dev_name: '%s'", port_entry->dev_name); VLOG_INFO("index: %"PRIu32, port_entry->index); VLOG_INFO("type: %s", port_entry->type == DEVLINK_PORT_TYPE_AUTO ? "AUTO" : port_entry->type == DEVLINK_PORT_TYPE_ETH ? "ETH" : port_entry->type == DEVLINK_PORT_TYPE_IB ? "IB" : "unknown"); VLOG_INFO("desired_type: %"PRIu16, port_entry->desired_type); VLOG_INFO("netdev_ifindex: %"PRIu32, port_entry->netdev_ifindex); VLOG_INFO("netdev_name: '%s'", port_entry->netdev_name); VLOG_INFO("split_count: %"PRIu32, port_entry->split_count); VLOG_INFO("split_group: %"PRIu32, port_entry->split_group); VLOG_INFO("flavour: %s", port_entry->flavour == DEVLINK_PORT_FLAVOUR_PHYSICAL ? "PHYSICAL" : port_entry->flavour == DEVLINK_PORT_FLAVOUR_CPU ? "CPU" : port_entry->flavour == DEVLINK_PORT_FLAVOUR_DSA ? "DSA" : port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_PF ? "PCI_PF": port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_VF ? "PCI_VF": port_entry->flavour == DEVLINK_PORT_FLAVOUR_VIRTUAL ? "VIRTUAL": port_entry->flavour == DEVLINK_PORT_FLAVOUR_UNUSED ? "UNUSED": port_entry->flavour == DEVLINK_PORT_FLAVOUR_PCI_SF ? "PCI_SF": "UNKNOWN"); VLOG_INFO("number: %"PRIu32, port_entry->number); VLOG_INFO("split_subport_number: %"PRIu32, port_entry->split_subport_number); VLOG_INFO("pci_pf_number: %"PRIu16, port_entry->pci_pf_number); VLOG_INFO("pci_vf_number: %"PRIu16, port_entry->pci_vf_number); VLOG_INFO("function eth_addr: "ETH_ADDR_FMT, ETH_ADDR_ARGS(port_entry->function.eth_addr)); VLOG_INFO("function state: %"PRIu8, port_entry->function.state); VLOG_INFO("function opstate: %"PRIu8, port_entry->function.opstate); VLOG_INFO("lanes: %"PRIu32, port_entry->lanes); VLOG_INFO("splittable: %s", port_entry->splittable == 0 ? "false" : port_entry->splittable == 1 ? "true" : "unknown"); VLOG_INFO("external: %s", port_entry->external == 0 ? "false" : port_entry->external == 1 ? "true" : "unknown"); VLOG_INFO("controller_number: %"PRIu32, port_entry->controller_number); VLOG_INFO("pci_sf_number: %"PRIu32, port_entry->pci_sf_number); } static void print_version(const char *prefix, struct dl_info_version *version) { if (!version->name || version->name == dl_str_not_present) { return; } VLOG_INFO("%s %s: %s", prefix, version->name, version->value); } static void print_info(struct dl_info *info_entry) { VLOG_INFO("driver_name: '%s'", info_entry->driver_name); VLOG_INFO("serial_number: '%s'", info_entry->serial_number); VLOG_INFO("board_serial_number: '%s'", info_entry->board_serial_number); print_version("fixed", &info_entry->version_fixed); print_version("running", &info_entry->version_running); print_version("stored", &info_entry->version_stored); } static void dump(void) { struct nl_dl_dump_state *port_dump; struct nl_dl_dump_state *info_dump; struct dl_port port_entry; struct dl_info info_entry; int error; printf("port dump\n"); port_dump = nl_dl_dump_init(); if ((error = nl_dl_dump_init_error(port_dump))) { ovs_fatal(error, "error"); } nl_dl_dump_start(DEVLINK_CMD_PORT_GET, port_dump); while (nl_dl_port_dump_next(port_dump, &port_entry)) { print_port(&port_entry); } nl_dl_dump_finish(port_dump); nl_dl_dump_destroy(port_dump); printf("info dump\n"); info_dump = nl_dl_dump_init(); if ((error = nl_dl_dump_init_error(info_dump))) { ovs_fatal(error, "error"); } nl_dl_dump_start(DEVLINK_CMD_INFO_GET, info_dump); while (nl_dl_info_dump_next(info_dump, &info_entry)) { print_info(&info_entry); } nl_dl_dump_finish(info_dump); nl_dl_dump_destroy(info_dump); } static void monitor(void) { uint64_t buf_stub[4096 / 64]; struct nl_sock *sock; struct ofpbuf buf; unsigned int devlink_mcgroup; int error; error = nl_lookup_genl_mcgroup(DEVLINK_GENL_NAME, DEVLINK_GENL_MCGRP_CONFIG_NAME, &devlink_mcgroup); if (error) { ovs_fatal(error, "unable to lookup devlink genl multicast group"); } error = nl_sock_create(NETLINK_GENERIC, &sock); if (error) { ovs_fatal(error, "could not create genlnetlink socket"); } error = nl_sock_join_mcgroup(sock, devlink_mcgroup); if (error) { ovs_fatal(error, "could not join devlink config multicast group"); } ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); for (;;) { error = nl_sock_recv(sock, &buf, NULL, false); if (error == EAGAIN) { /* Nothing to do. */ } else if (error == ENOBUFS) { ovs_error(0, "network monitor socket overflowed"); } else if (error) { ovs_fatal(error, "error on network monitor socket"); } else { struct genlmsghdr *genl; struct dl_port port_entry; genl = nl_msg_genlmsghdr(&buf); printf("cmd=%"PRIu8",version=%"PRIu8")\n", genl->cmd, genl->version); switch (genl->cmd) { case DEVLINK_CMD_PORT_GET: case DEVLINK_CMD_PORT_SET: case DEVLINK_CMD_PORT_NEW: case DEVLINK_CMD_PORT_DEL: if (!nl_dl_parse_port_policy(&buf, &port_entry)) { VLOG_WARN("could not parse port entry"); continue; } VLOG_INFO("%s", genl->cmd == DEVLINK_CMD_PORT_GET ? "DEVLINK_CMD_PORT_GET": genl->cmd == DEVLINK_CMD_PORT_SET ? "DEVLINK_CMD_PORT_SET": genl->cmd == DEVLINK_CMD_PORT_NEW ? "DEVLINK_CMD_PORT_NEW": genl->cmd == DEVLINK_CMD_PORT_DEL ? "DEVLINK_CMD_PORT_DEL": "UNKNOWN"); print_port(&port_entry); break; }; } nl_sock_wait(sock, POLLIN); poll_block(); } } int main(int argc, char *argv[]) { int cmd = -1; set_program_name(argv[0]); vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG); if (argc > 1 && !strcmp(argv[1], CMD_NAME[CMD_DUMP])) { cmd = CMD_DUMP; } else if (argc > 1 && !strcmp(argv[1], CMD_NAME[CMD_MONITOR])) { cmd = CMD_MONITOR; } switch (cmd) { case CMD_DUMP: dump(); break; case CMD_MONITOR: monitor(); break; default: usage(); return EX_USAGE; }; return 0; }