From 8e62dcacc834a2318cb69533f4f83d32bc950fd4 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 28 Feb 2022 15:32:27 +0100 Subject: [PATCH 2/2] build: Seperated common used headers --- Makefile.am | 2 +- build-aux/extract-odp-netlink-h | 9 + build-aux/extract-odp-netlink-macros-h | 6 + datapath/conntrack.c | 2 +- datapath/conntrack.h | 2 +- datapath/datapath.c | 2 +- datapath/datapath.h | 2 +- datapath/flow.c | 2 +- datapath/flow_netlink.c | 2 +- datapath/flow_netlink.h | 2 +- datapath/flow_table.c | 2 +- datapath/flow_table.h | 2 +- datapath/meter.h | 2 +- include/automake.mk | 1 + include/internal/automake.mk | 77 +++ {lib => include/internal}/bitmap.h | 2 +- {lib => include/internal}/bundle.h | 0 {lib => include/internal}/byte-order.h | 0 {lib => include/internal}/classifier.h | 8 +- {lib => include/internal}/cmap.h | 4 +- {lib => include/internal}/colors.h | 0 {lib => include/internal}/command-line.h | 0 {lib => include/internal}/coverage.h | 2 +- {lib => include/internal}/crc32c.h | 0 {lib => include/internal}/csum.h | 0 {lib => include/internal}/daemon.h | 0 {lib => include/internal}/db-ctl-base.h | 0 {lib => include/internal}/dhcp.h | 4 +- {lib => include/internal}/dhparams.h | 0 {lib => include/internal}/dirs.h | 0 {lib => include/internal}/dp-packet.h | 10 +- {lib => include/internal}/fatal-signal.h | 0 {lib => include/internal}/flow.h | 10 +- {lib => include/internal}/hash-aarch64.h | 0 {lib => include/internal}/hash.h | 4 +- {lib => include/internal}/hindex.h | 2 +- {lib => include/internal}/hmapx.h | 0 {lib => include/internal}/id-pool.h | 0 {lib => include/internal}/jsonrpc.h | 0 {lib => include/internal}/latch.h | 2 +- {lib => include/internal}/mcast-snooping.h | 10 +- {lib => include/internal}/memory.h | 0 {lib => include/internal}/netdev-afxdp.h | 0 {lib => include/internal}/netdev-dpdk.h | 0 {lib => include/internal}/netdev.h | 4 +- {lib => include/internal}/netlink-protocol.h | 2 +- {lib => include/internal}/netlink.h | 2 +- {lib => include/internal}/nx-match.h | 2 +- {lib => include/internal}/ovs-atomic-c++.h | 0 {lib => include/internal}/ovs-atomic-c11.h | 0 {lib => include/internal}/ovs-atomic-clang.h | 2 +- .../internal}/ovs-atomic-flag-gcc4.7+.h | 0 {lib => include/internal}/ovs-atomic-gcc4+.h | 2 +- .../internal}/ovs-atomic-gcc4.7+.h | 2 +- {lib => include/internal}/ovs-atomic-i586.h | 0 {lib => include/internal}/ovs-atomic-locked.c | 6 +- {lib => include/internal}/ovs-atomic-locked.h | 0 {lib => include/internal}/ovs-atomic-msvc.h | 0 .../internal}/ovs-atomic-pthreads.h | 2 +- {lib => include/internal}/ovs-atomic-x86_64.h | 0 {lib => include/internal}/packets.h | 12 +- {lib => include/internal}/process.h | 0 {lib => include/internal}/pvector.h | 4 +- {lib => include/internal}/random.h | 0 {lib => include/internal}/rculist.h | 4 +- {lib => include/internal}/seq.h | 2 +- {lib => include/internal}/simap.h | 0 {lib => include/internal}/skiplist.h | 0 {lib => include/internal}/smap.h | 2 +- {lib => include/internal}/socket-util.h | 0 {lib => include/internal}/sort.h | 0 {lib => include/internal}/sset.h | 2 +- {lib => include/internal}/stopwatch.h | 0 {lib => include/internal}/stream-ssl.h | 0 {lib => include/internal}/stream.h | 4 +- {lib => include/internal}/svec.h | 0 {lib => include/internal}/table.h | 0 {lib => include/internal}/timer.h | 4 +- {lib => include/internal}/timeval.h | 2 +- .../internal/tun-metadata-private.h | 2 +- {lib => include/internal}/unaligned.h | 4 +- {lib => include/internal}/unixctl.h | 0 include/internal/util.h | 603 ++++++++++++++++++ {lib => include/internal}/uuid.h | 0 {lib => include/internal}/versions.h | 2 +- include/openvswitch/automake.mk | 16 + {lib => include/openvswitch}/ovs-atomic.h | 30 +- {lib => include/openvswitch}/ovs-numa.h | 8 + {lib => include/openvswitch}/ovs-rcu.h | 10 +- {lib => include/openvswitch}/ovs-thread.h | 14 +- .../openvswitch}/ovsdb-condition.h | 8 + {lib => include/openvswitch}/ovsdb-cs.h | 10 +- {lib => include/openvswitch}/ovsdb-data.h | 4 +- {lib => include/openvswitch}/ovsdb-error.h | 8 + .../openvswitch}/ovsdb-idl-provider.h | 12 +- {lib => include/openvswitch}/ovsdb-idl.h | 8 +- {lib => include/openvswitch}/ovsdb-map-op.h | 2 +- {lib => include/openvswitch}/ovsdb-parser.h | 12 +- {lib => include/openvswitch}/ovsdb-set-op.h | 2 +- {lib => include/openvswitch}/ovsdb-types.h | 2 +- include/sparse/automake.mk | 10 +- include/windows/netinet/icmp6.h | 2 +- include/windows/netinet/ip6.h | 2 +- lib/aes128.c | 2 +- lib/async-append-aio.c | 4 +- lib/async-append-null.c | 2 +- lib/automake.mk | 16 - lib/backtrace.c | 2 +- lib/bfd.c | 30 +- lib/bfd.h | 2 +- lib/bundle.c | 8 +- lib/byteq.c | 2 +- lib/ccmap.c | 12 +- lib/ccmap.h | 4 +- lib/cfm.c | 26 +- lib/cfm.h | 2 +- lib/classifier-private.h | 8 +- lib/classifier.c | 8 +- lib/cmap.c | 14 +- lib/colors.c | 4 +- lib/command-line.c | 8 +- lib/connectivity.c | 4 +- lib/conntrack-icmp.c | 2 +- lib/conntrack-other.c | 2 +- lib/conntrack-private.h | 8 +- lib/conntrack-tcp.c | 6 +- lib/conntrack.c | 20 +- lib/conntrack.h | 12 +- lib/coverage.c | 12 +- lib/crc32c.c | 4 +- lib/csum.c | 4 +- lib/ct-dpif.h | 2 +- lib/daemon-unix.c | 18 +- lib/daemon-windows.c | 8 +- lib/daemon.c | 6 +- lib/db-ctl-base.c | 23 +- lib/dhparams.c | 2 +- lib/dirs.c.in | 6 +- lib/dns-resolve.c | 4 +- lib/dp-packet.c | 8 +- lib/dpctl.c | 23 +- lib/dpdk-stub.c | 4 +- lib/dpdk.c | 18 +- lib/dpif-netdev-avx512.c | 4 +- lib/dpif-netdev-extract-avx512.c | 2 +- lib/dpif-netdev-extract-study.c | 2 +- lib/dpif-netdev-lookup-avx512-gather.c | 6 +- lib/dpif-netdev-lookup-generic.c | 14 +- lib/dpif-netdev-perf.c | 6 +- lib/dpif-netdev-perf.h | 8 +- lib/dpif-netdev-private-dpcls.h | 2 +- lib/dpif-netdev-private-dpif.c | 2 +- lib/dpif-netdev-private-extract.c | 8 +- lib/dpif-netdev-private-flow.h | 2 +- lib/dpif-netdev-private-thread.h | 2 +- lib/dpif-netdev.c | 44 +- lib/dpif-netdev.h | 4 +- lib/dpif-netlink-rtnl.h | 2 +- lib/dpif-netlink.c | 20 +- lib/dpif-netlink.h | 2 +- lib/dpif-provider.h | 2 +- lib/dpif.c | 22 +- lib/dpif.h | 10 +- lib/dummy.c | 2 +- lib/dynamic-string.c | 4 +- lib/entropy.c | 4 +- lib/fat-rwlock.c | 4 +- lib/fat-rwlock.h | 2 +- lib/fatal-signal.c | 10 +- lib/flow.c | 28 +- lib/getopt_long.c | 2 +- lib/getrusage-windows.c | 2 +- lib/guarded-list.h | 2 +- lib/hash.c | 4 +- lib/heap.c | 2 +- lib/hindex.c | 4 +- lib/hmap.c | 6 +- lib/hmapx.c | 4 +- lib/id-fpool.c | 2 +- lib/id-pool.c | 4 +- lib/if-notifier-bsd.c | 2 +- lib/if-notifier.c | 2 +- lib/ipf.c | 12 +- lib/ipf.h | 2 +- lib/jhash.c | 2 +- lib/jhash.h | 2 +- lib/json.c | 6 +- lib/jsonrpc.c | 12 +- lib/lacp.c | 18 +- lib/lacp.h | 2 +- lib/latch-unix.c | 4 +- lib/latch-windows.c | 4 +- lib/learn.c | 8 +- lib/learning-switch.c | 12 +- lib/lldp/lldp.c | 4 +- lib/lldp/lldpd-structs.c | 2 +- lib/lldp/lldpd-structs.h | 2 +- lib/lldp/lldpd.c | 4 +- lib/lldp/lldpd.h | 4 +- lib/lockfile.c | 10 +- lib/mac-learning.c | 12 +- lib/mac-learning.h | 8 +- lib/match.c | 10 +- lib/mcast-snooping.c | 16 +- lib/memory.c | 8 +- lib/meta-flow.c | 22 +- lib/mpsc-queue.c | 2 +- lib/mpsc-queue.h | 2 +- lib/multipath.c | 8 +- lib/namemap.c | 2 +- lib/netdev-afxdp-pool.c | 2 +- lib/netdev-afxdp-pool.h | 2 +- lib/netdev-afxdp.c | 16 +- lib/netdev-bsd.c | 16 +- lib/netdev-dpdk.c | 34 +- lib/netdev-dummy.c | 18 +- lib/netdev-linux-private.h | 8 +- lib/netdev-linux.c | 28 +- lib/netdev-native-tnl.c | 16 +- lib/netdev-native-tnl.h | 6 +- lib/netdev-offload-dpdk.c | 8 +- lib/netdev-offload-provider.h | 4 +- lib/netdev-offload-tc.c | 8 +- lib/netdev-offload.c | 26 +- lib/netdev-offload.h | 8 +- lib/netdev-provider.h | 12 +- lib/netdev-vport-private.h | 4 +- lib/netdev-vport.c | 20 +- lib/netdev-windows.c | 10 +- lib/netdev.c | 28 +- lib/netflow.h | 2 +- lib/netlink-conntrack.c | 10 +- lib/netlink-conntrack.h | 8 +- lib/netlink-notifier.c | 4 +- lib/netlink-socket.c | 16 +- lib/netlink-socket.h | 4 +- lib/netlink.c | 14 +- lib/nx-match.c | 14 +- lib/object-collection.c | 2 +- lib/odp-execute.c | 16 +- lib/odp-util.c | 24 +- lib/odp-util.h | 6 +- lib/ofp-actions.c | 12 +- lib/ofp-bundle.c | 2 +- lib/ofp-connection.c | 4 +- lib/ofp-ed-props.c | 4 +- lib/ofp-errors.c | 4 +- lib/ofp-flow.c | 10 +- lib/ofp-group.c | 8 +- lib/ofp-ipfix.c | 4 +- lib/ofp-match.c | 6 +- lib/ofp-meter.c | 4 +- lib/ofp-monitor.c | 6 +- lib/ofp-msgs.c | 8 +- lib/ofp-packet.c | 8 +- lib/ofp-parse.c | 8 +- lib/ofp-port.c | 4 +- lib/ofp-print.c | 22 +- lib/ofp-prop.c | 6 +- lib/ofp-protocol.c | 2 +- lib/ofp-queue.c | 6 +- lib/ofp-switch.c | 4 +- lib/ofp-table.c | 6 +- lib/ofp-util.c | 26 +- lib/ofp-version-opt.c | 2 +- lib/ofp-version-opt.h | 2 +- lib/ofpbuf.c | 2 +- lib/ovs-lldp.c | 12 +- lib/ovs-lldp.h | 8 +- lib/ovs-numa.c | 8 +- lib/ovs-rcu.c | 14 +- lib/ovs-replay.c | 6 +- lib/ovs-router.c | 20 +- lib/ovs-router.h | 2 +- lib/ovs-thread.c | 14 +- lib/ovsdb-condition.c | 4 +- lib/ovsdb-cs.c | 22 +- lib/ovsdb-data.c | 16 +- lib/ovsdb-error.c | 4 +- lib/ovsdb-idl.c | 34 +- lib/ovsdb-map-op.c | 6 +- lib/ovsdb-parser.c | 4 +- lib/ovsdb-session.c | 6 +- lib/ovsdb-set-op.c | 4 +- lib/ovsdb-types.c | 12 +- lib/ox-stat.c | 4 +- lib/packets.c | 16 +- lib/pcap-file.c | 14 +- lib/perf-counter.c | 2 +- lib/poll-loop.c | 14 +- lib/process.c | 14 +- lib/pvector.c | 2 +- lib/random.c | 10 +- lib/rconn.c | 10 +- lib/reconnect.c | 2 +- lib/route-table-bsd.c | 4 +- lib/route-table.c | 8 +- lib/rstp-common.h | 4 +- lib/rstp-state-machines.c | 12 +- lib/rstp.c | 12 +- lib/rstp.h | 2 +- lib/rtbsd.c | 4 +- lib/rtnetlink.c | 4 +- lib/seq.c | 10 +- lib/sflow_agent.c | 2 +- lib/sha1.c | 2 +- lib/shash.c | 2 +- lib/signals.c | 4 +- lib/simap.c | 4 +- lib/skiplist.c | 6 +- lib/smap.c | 10 +- lib/socket-util-unix.c | 8 +- lib/socket-util.c | 10 +- lib/sort.c | 4 +- lib/sset.c | 4 +- lib/stopwatch.c | 12 +- lib/stp.c | 14 +- lib/stp.h | 2 +- lib/stream-fd.c | 8 +- lib/stream-nossl.c | 2 +- lib/stream-provider.h | 2 +- lib/stream-replay.c | 6 +- lib/stream-ssl.c | 16 +- lib/stream-tcp.c | 8 +- lib/stream-unix.c | 12 +- lib/stream-windows.c | 6 +- lib/stream.c | 18 +- lib/string.c | 2 +- lib/strsep.c | 2 +- lib/svec.c | 6 +- lib/syslog-direct.c | 4 +- lib/syslog-libc.c | 4 +- lib/syslog-null.c | 2 +- lib/table.c | 10 +- lib/tc.c | 10 +- lib/timer.c | 4 +- lib/timeval.c | 18 +- lib/tnl-neigh-cache.c | 28 +- lib/tnl-neigh-cache.h | 8 +- lib/tnl-ports.c | 12 +- lib/tnl-ports.h | 6 +- lib/token-bucket.c | 4 +- lib/tun-metadata.c | 12 +- lib/unicode.c | 2 +- lib/unixctl.c | 12 +- lib/userspace-tso.c | 4 +- lib/util.c | 16 +- lib/util.h | 1 - lib/uuid.c | 10 +- lib/vconn-provider.h | 2 +- lib/vconn-stream.c | 8 +- lib/vconn.c | 14 +- lib/vl-mff-map.h | 2 +- lib/vlan-bitmap.h | 2 +- lib/vlog.c | 16 +- lib/wmi.c | 2 +- ofproto/bond.c | 18 +- ofproto/bond.h | 2 +- ofproto/bundles.c | 8 +- ofproto/bundles.h | 2 +- ofproto/collectors.c | 6 +- ofproto/connmgr.c | 12 +- ofproto/connmgr.h | 2 +- ofproto/fail-open.c | 8 +- ofproto/in-band.c | 14 +- ofproto/in-band.h | 2 +- ofproto/netflow.c | 12 +- ofproto/netflow.h | 4 +- ofproto/ofproto-dpif-ipfix.c | 18 +- ofproto/ofproto-dpif-mirror.c | 4 +- ofproto/ofproto-dpif-mirror.h | 2 +- ofproto/ofproto-dpif-monitor.c | 14 +- ofproto/ofproto-dpif-monitor.h | 2 +- ofproto/ofproto-dpif-rid.h | 6 +- ofproto/ofproto-dpif-sflow.c | 14 +- ofproto/ofproto-dpif-sflow.h | 2 +- ofproto/ofproto-dpif-trace.c | 2 +- ofproto/ofproto-dpif-trace.h | 2 +- ofproto/ofproto-dpif-upcall.c | 16 +- ofproto/ofproto-dpif-xlate-cache.c | 14 +- ofproto/ofproto-dpif-xlate-cache.h | 2 +- ofproto/ofproto-dpif-xlate.c | 24 +- ofproto/ofproto-dpif-xlate.h | 6 +- ofproto/ofproto-dpif.c | 34 +- ofproto/ofproto-dpif.h | 8 +- ofproto/ofproto-provider.h | 18 +- ofproto/ofproto.c | 40 +- ofproto/ofproto.h | 8 +- ofproto/pinsched.c | 8 +- ofproto/pinsched.h | 2 +- ofproto/tunnel.c | 20 +- ofproto/tunnel.h | 2 +- ovsdb/column.c | 6 +- ovsdb/column.h | 2 +- ovsdb/condition.c | 4 +- ovsdb/condition.h | 6 +- ovsdb/execution.c | 8 +- ovsdb/file.c | 14 +- ovsdb/jsonrpc-server.c | 16 +- ovsdb/log.c | 14 +- ovsdb/monitor.c | 16 +- ovsdb/mutation.c | 4 +- ovsdb/mutation.h | 2 +- ovsdb/ovsdb-client.c | 30 +- ovsdb/ovsdb-idlc.in | 16 +- ovsdb/ovsdb-server.c | 36 +- ovsdb/ovsdb-tool.c | 21 +- ovsdb/ovsdb-util.c | 2 +- ovsdb/ovsdb.c | 10 +- ovsdb/raft-private.c | 10 +- ovsdb/raft-private.h | 2 +- ovsdb/raft-rpc.c | 8 +- ovsdb/raft-rpc.h | 2 +- ovsdb/raft.c | 24 +- ovsdb/raft.h | 2 +- ovsdb/rbac.c | 8 +- ovsdb/relay.c | 12 +- ovsdb/replication.c | 12 +- ovsdb/row.c | 6 +- ovsdb/row.h | 2 +- ovsdb/server.c | 4 +- ovsdb/storage.c | 10 +- ovsdb/table.c | 6 +- ovsdb/transaction-forward.c | 8 +- ovsdb/transaction.c | 8 +- ovsdb/trigger.c | 6 +- tests/oss-fuzz/flow_extract_target.c | 6 +- tests/oss-fuzz/json_parser_target.c | 4 +- tests/oss-fuzz/miniflow_target.c | 8 +- tests/oss-fuzz/odp_target.c | 4 +- tests/oss-fuzz/ofctl_parse_target.c | 2 +- tests/oss-fuzz/ofp_print_target.c | 2 +- tests/ovstest.c | 4 +- tests/ovstest.h | 2 +- tests/test-aes128.c | 2 +- tests/test-atomic.c | 10 +- tests/test-barrier.c | 8 +- tests/test-bitmap.c | 6 +- tests/test-bundle.c | 6 +- tests/test-byte-order.c | 2 +- tests/test-ccmap.c | 14 +- tests/test-classifier.c | 24 +- tests/test-cmap.c | 16 +- tests/test-conntrack.c | 12 +- tests/test-csum.c | 12 +- tests/test-flows.c | 10 +- tests/test-hash.c | 2 +- tests/test-heap.c | 6 +- tests/test-hindex.c | 8 +- tests/test-hmap.c | 6 +- tests/test-id-fpool.c | 16 +- tests/test-json.c | 6 +- tests/test-jsonrpc.c | 14 +- tests/test-lockfile.c | 6 +- tests/test-mpsc-queue.c | 10 +- tests/test-multipath.c | 4 +- tests/test-netflow.c | 12 +- tests/test-netlink-policy.c | 4 +- tests/test-odp.c | 4 +- tests/test-ofpbuf.c | 2 +- tests/test-ovsdb.c | 22 +- tests/test-packets.c | 2 +- tests/test-random.c | 2 +- tests/test-rcu.c | 8 +- tests/test-reconnect.c | 6 +- tests/test-rstp.c | 4 +- tests/test-sflow.c | 12 +- tests/test-sha1.c | 4 +- tests/test-skiplist.c | 6 +- tests/test-stopwatch.c | 4 +- tests/test-stp.c | 4 +- tests/test-stream.c | 6 +- tests/test-unix-socket.c | 4 +- tests/test-unixctl.c | 10 +- tests/test-util.c | 8 +- tests/test-uuid.c | 4 +- tests/test-vconn.c | 14 +- utilities/nlmon.c | 6 +- utilities/ovs-appctl.c | 16 +- utilities/ovs-dpctl.c | 12 +- utilities/ovs-ofctl.c | 34 +- utilities/ovs-testcontroller.c | 18 +- utilities/ovs-vsctl.c | 34 +- vswitchd/bridge.c | 42 +- vswitchd/ovs-vswitchd.c | 32 +- vswitchd/system-stats.c | 16 +- vswitchd/xenserver.c | 4 +- vtep/vtep-ctl.c | 30 +- 488 files changed, 2592 insertions(+), 1822 deletions(-) create mode 100644 include/internal/automake.mk rename {lib => include/internal}/bitmap.h (99%) rename {lib => include/internal}/bundle.h (100%) rename {lib => include/internal}/byte-order.h (100%) rename {lib => include/internal}/classifier.h (99%) rename {lib => include/internal}/cmap.h (99%) rename {lib => include/internal}/colors.h (100%) rename {lib => include/internal}/command-line.h (100%) rename {lib => include/internal}/coverage.h (99%) rename {lib => include/internal}/crc32c.h (100%) rename {lib => include/internal}/csum.h (100%) rename {lib => include/internal}/daemon.h (100%) rename {lib => include/internal}/db-ctl-base.h (100%) rename {lib => include/internal}/dhcp.h (97%) rename {lib => include/internal}/dhparams.h (100%) rename {lib => include/internal}/dirs.h (100%) rename {lib => include/internal}/dp-packet.h (99%) rename {lib => include/internal}/fatal-signal.h (100%) rename {lib => include/internal}/flow.h (99%) rename {lib => include/internal}/hash-aarch64.h (100%) rename {lib => include/internal}/hash.h (99%) rename {lib => include/internal}/hindex.h (99%) rename {lib => include/internal}/hmapx.h (100%) rename {lib => include/internal}/id-pool.h (100%) rename {lib => include/internal}/jsonrpc.h (100%) rename {lib => include/internal}/latch.h (97%) rename {lib => include/internal}/mcast-snooping.h (97%) rename {lib => include/internal}/memory.h (100%) rename {lib => include/internal}/netdev-afxdp.h (100%) rename {lib => include/internal}/netdev-dpdk.h (100%) rename {lib => include/internal}/netdev.h (99%) rename {lib => include/internal}/netlink-protocol.h (99%) rename {lib => include/internal}/netlink.h (99%) rename {lib => include/internal}/nx-match.h (99%) rename {lib => include/internal}/ovs-atomic-c++.h (100%) rename {lib => include/internal}/ovs-atomic-c11.h (100%) rename {lib => include/internal}/ovs-atomic-clang.h (98%) rename {lib => include/internal}/ovs-atomic-flag-gcc4.7+.h (100%) rename {lib => include/internal}/ovs-atomic-gcc4+.h (99%) rename {lib => include/internal}/ovs-atomic-gcc4.7+.h (98%) rename {lib => include/internal}/ovs-atomic-i586.h (100%) rename {lib => include/internal}/ovs-atomic-locked.c (94%) rename {lib => include/internal}/ovs-atomic-locked.h (100%) rename {lib => include/internal}/ovs-atomic-msvc.h (100%) rename {lib => include/internal}/ovs-atomic-pthreads.h (99%) rename {lib => include/internal}/ovs-atomic-x86_64.h (100%) rename {lib => include/internal}/packets.h (99%) rename {lib => include/internal}/process.h (100%) rename {lib => include/internal}/pvector.h (99%) rename {lib => include/internal}/random.h (100%) rename {lib => include/internal}/rculist.h (99%) rename {lib => include/internal}/seq.h (99%) rename {lib => include/internal}/simap.h (100%) rename {lib => include/internal}/skiplist.h (100%) rename {lib => include/internal}/smap.h (99%) rename {lib => include/internal}/socket-util.h (100%) rename {lib => include/internal}/sort.h (100%) rename {lib => include/internal}/sset.h (99%) rename {lib => include/internal}/stopwatch.h (100%) rename {lib => include/internal}/stream-ssl.h (100%) rename {lib => include/internal}/stream.h (98%) rename {lib => include/internal}/svec.h (100%) rename {lib => include/internal}/table.h (100%) rename {lib => include/internal}/timer.h (96%) rename {lib => include/internal}/timeval.h (98%) rename lib/tun-metadata.h => include/internal/tun-metadata-private.h (99%) rename {lib => include/internal}/unaligned.h (99%) rename {lib => include/internal}/unixctl.h (100%) create mode 100644 include/internal/util.h rename {lib => include/internal}/uuid.h (100%) rename {lib => include/internal}/versions.h (98%) rename {lib => include/openvswitch}/ovs-atomic.h (97%) rename {lib => include/openvswitch}/ovs-numa.h (96%) rename {lib => include/openvswitch}/ovs-rcu.h (99%) rename {lib => include/openvswitch}/ovs-thread.h (99%) rename {lib => include/openvswitch}/ovsdb-condition.h (95%) rename {lib => include/openvswitch}/ovsdb-cs.h (98%) rename {lib => include/openvswitch}/ovsdb-data.h (99%) rename {lib => include/openvswitch}/ovsdb-error.h (97%) rename {lib => include/openvswitch}/ovsdb-idl-provider.h (97%) rename {lib => include/openvswitch}/ovsdb-idl.h (99%) rename {lib => include/openvswitch}/ovsdb-map-op.h (97%) rename {lib => include/openvswitch}/ovsdb-parser.h (96%) rename {lib => include/openvswitch}/ovsdb-set-op.h (97%) rename {lib => include/openvswitch}/ovsdb-types.h (99%) Index: openvswitch-2.17.2/Makefile.am =================================================================== --- openvswitch-2.17.2.orig/Makefile.am +++ openvswitch-2.17.2/Makefile.am @@ -242,7 +242,7 @@ config-h-check: exit 1; \ fi; \ if grep '#include' include/openvswitch/*.h | \ - grep -vE '(<.*>)|("openvswitch)|("openflow)'; \ + grep -vE '(<.*>)|("openvswitch)|("openflow)|("internal)'; \ then \ echo "See above for list of violations of the rule that"; \ echo "public openvswitch header file should not include internal library."; \ Index: openvswitch-2.17.2/build-aux/extract-odp-netlink-h =================================================================== --- openvswitch-2.17.2.orig/build-aux/extract-odp-netlink-h +++ openvswitch-2.17.2/build-aux/extract-odp-netlink-h @@ -8,6 +8,9 @@ /* -*- mode: c; buffer-read-only: t -*- */\ /* Generated automatically from -- do not modify! */\ \ +#ifdef __cplusplus\ +extern "C" {\ +#endif\ \ @@ -65,3 +68,9 @@ s/__be16/ovs_be16/g # boundary. s/__u64/ovs_32aligned_u64/g s/__be64/ovs_32aligned_be64/g + +$a\ +#ifdef __cplusplus\ +} // extern "C"\ +#endif\ +\ Index: openvswitch-2.17.2/build-aux/extract-odp-netlink-macros-h =================================================================== --- openvswitch-2.17.2.orig/build-aux/extract-odp-netlink-macros-h +++ openvswitch-2.17.2/build-aux/extract-odp-netlink-macros-h @@ -42,6 +42,9 @@ echo "/* Generated automatically from -#include "flow.h" +#include "internal/flow.h" struct ovs_conntrack_info; struct ovs_ct_limit_info; Index: openvswitch-2.17.2/datapath/datapath.c =================================================================== --- openvswitch-2.17.2.orig/datapath/datapath.c +++ openvswitch-2.17.2/datapath/datapath.c @@ -55,7 +55,7 @@ #include "datapath.h" #include "conntrack.h" -#include "flow.h" +#include "internal/flow.h" #include "flow_table.h" #include "flow_netlink.h" #include "meter.h" Index: openvswitch-2.17.2/datapath/datapath.h =================================================================== --- openvswitch-2.17.2.orig/datapath/datapath.h +++ openvswitch-2.17.2/datapath/datapath.h @@ -29,7 +29,7 @@ #include #include "compat.h" -#include "flow.h" +#include "internal/flow.h" #include "flow_table.h" #include "meter.h" #include "vport-internal_dev.h" Index: openvswitch-2.17.2/datapath/flow.c =================================================================== --- openvswitch-2.17.2.orig/datapath/flow.c +++ openvswitch-2.17.2/datapath/flow.c @@ -50,7 +50,7 @@ #include "datapath.h" #include "conntrack.h" -#include "flow.h" +#include "internal/flow.h" #include "flow_netlink.h" #include "vport.h" Index: openvswitch-2.17.2/datapath/flow_netlink.c =================================================================== --- openvswitch-2.17.2.orig/datapath/flow_netlink.c +++ openvswitch-2.17.2/datapath/flow_netlink.c @@ -51,7 +51,7 @@ #include "datapath.h" #include "conntrack.h" -#include "flow.h" +#include "internal/flow.h" #include "flow_netlink.h" #include "gso.h" Index: openvswitch-2.17.2/datapath/flow_netlink.h =================================================================== --- openvswitch-2.17.2.orig/datapath/flow_netlink.h +++ openvswitch-2.17.2/datapath/flow_netlink.h @@ -34,7 +34,7 @@ #include #include -#include "flow.h" +#include "internal/flow.h" size_t ovs_tun_key_attr_size(void); size_t ovs_key_attr_size(void); Index: openvswitch-2.17.2/datapath/flow_table.c =================================================================== --- openvswitch-2.17.2.orig/datapath/flow_table.c +++ openvswitch-2.17.2/datapath/flow_table.c @@ -16,7 +16,7 @@ * 02110-1301, USA */ -#include "flow.h" +#include "internal/flow.h" #include "datapath.h" #include #include Index: openvswitch-2.17.2/datapath/flow_table.h =================================================================== --- openvswitch-2.17.2.orig/datapath/flow_table.h +++ openvswitch-2.17.2/datapath/flow_table.h @@ -33,7 +33,7 @@ #include #include -#include "flow.h" +#include "internal/flow.h" struct mask_cache_entry { u32 skb_hash; Index: openvswitch-2.17.2/datapath/meter.h =================================================================== --- openvswitch-2.17.2.orig/datapath/meter.h +++ openvswitch-2.17.2/datapath/meter.h @@ -17,7 +17,7 @@ #include #include -#include "flow.h" +#include "internal/flow.h" struct datapath; #define DP_MAX_BANDS 1 Index: openvswitch-2.17.2/include/automake.mk =================================================================== --- openvswitch-2.17.2.orig/include/automake.mk +++ openvswitch-2.17.2/include/automake.mk @@ -16,3 +16,4 @@ include include/openvswitch/automake.mk include include/sparse/automake.mk include include/windows/automake.mk include include/linux/automake.mk +include include/internal/automake.mk Index: openvswitch-2.17.2/include/internal/automake.mk =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/automake.mk @@ -0,0 +1,77 @@ +# Common headers needed by openvswitch and some depending projects like OVN + +ovslibincludedir = $(openvswitchincludedir)/internal +ovslibinclude_HEADERS = \ + include/internal/bitmap.h \ + include/internal/byte-order.h \ + include/internal/classifier.h \ + include/internal/cmap.h \ + include/internal/colors.h \ + include/internal/command-line.h \ + include/internal/coverage.h \ + include/internal/csum.h \ + include/internal/daemon.h \ + include/internal/db-ctl-base.h \ + include/internal/dirs.h \ + include/internal/dp-packet.h \ + include/internal/fatal-signal.h \ + include/internal/flow.h \ + include/internal/hash.h \ + include/internal/hash-aarch64.h \ + include/internal/hindex.h \ + include/internal/hmapx.h \ + include/internal/jsonrpc.h \ + include/internal/latch.h \ + include/internal/mcast-snooping.h \ + include/internal/memory.h \ + include/internal/netdev-afxdp.h \ + include/internal/netdev-dpdk.h \ + include/internal/netlink.h \ + include/internal/bundle.h \ + include/internal/crc32c.h \ + include/internal/dhcp.h \ + include/internal/dhparams.h \ + include/internal/id-pool.h \ + include/internal/netdev.h \ + include/internal/netlink-protocol.h \ + include/internal/nx-match.h \ + include/internal/ovs-atomic-c11.h \ + include/internal/ovs-atomic-c++.h \ + include/internal/ovs-atomic-clang.h \ + include/internal/ovs-atomic-flag-gcc4.7+.h \ + include/internal/ovs-atomic-gcc4.7+.h \ + include/internal/ovs-atomic-gcc4+.h \ + include/internal/ovs-atomic-i586.h \ + include/internal/ovs-atomic-locked.c \ + include/internal/ovs-atomic-locked.h \ + include/internal/ovs-atomic-msvc.h \ + include/internal/ovs-atomic-pthreads.h \ + include/internal/ovs-atomic-x86_64.h \ + include/internal/packets.h \ + include/internal/process.h \ + include/internal/pvector.h \ + include/internal/random.h \ + include/internal/rculist.h \ + include/internal/seq.h \ + include/internal/simap.h \ + include/internal/skiplist.h \ + include/internal/smap.h \ + include/internal/socket-util.h \ + include/internal/sort.h \ + include/internal/sset.h \ + include/internal/stopwatch.h \ + include/internal/stream.h \ + include/internal/stream-ssl.h \ + include/internal/svec.h \ + include/internal/table.h \ + include/internal/timer.h \ + include/internal/timeval.h \ + include/internal/tun-metadata-private.h \ + include/internal/unaligned.h \ + include/internal/unixctl.h \ + include/internal/util.h \ + include/internal/uuid.h \ + include/internal/versions.h \ + lib/vswitch-idl.h \ + vtep/vtep-idl.h + Index: openvswitch-2.17.2/lib/bitmap.h =================================================================== --- openvswitch-2.17.2.orig/lib/bitmap.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef BITMAP_H -#define BITMAP_H 1 - -#include -#include -#include "util.h" - -static inline unsigned long * -bitmap_unit__(const unsigned long *bitmap, size_t offset) -{ - return CONST_CAST(unsigned long *, &bitmap[offset / BITMAP_ULONG_BITS]); -} - -static inline unsigned long -bitmap_bit__(size_t offset) -{ - return 1UL << (offset % BITMAP_ULONG_BITS); -} - -static inline size_t -bitmap_n_longs(size_t n_bits) -{ - return BITMAP_N_LONGS(n_bits); -} - -static inline size_t -bitmap_n_bytes(size_t n_bits) -{ - return bitmap_n_longs(n_bits) * sizeof(unsigned long int); -} - -static inline unsigned long * -bitmap_allocate(size_t n_bits) -{ - return xzalloc(bitmap_n_bytes(n_bits)); -} - -/* Initializes bitmap to all-1-bits and returns the bitmap pointer. */ -static inline unsigned long * -bitmap_init1(unsigned long *bitmap, size_t n_bits) -{ - size_t n_longs = bitmap_n_longs(n_bits); - size_t n_bytes = bitmap_n_bytes(n_bits); - size_t r_bits = n_bits % BITMAP_ULONG_BITS; - - memset(bitmap, 0xff, n_bytes); - if (r_bits) { - bitmap[n_longs - 1] = (1UL << r_bits) - 1; - } - return bitmap; -} - -/* Allocates and returns a bitmap initialized to all-1-bits. */ -static inline unsigned long * -bitmap_allocate1(size_t n_bits) -{ - return bitmap_init1(xmalloc(bitmap_n_bytes(n_bits)), n_bits); -} - -static inline unsigned long * -bitmap_clone(const unsigned long *bitmap, size_t n_bits) -{ - return xmemdup(bitmap, bitmap_n_bytes(n_bits)); -} - -static inline void -bitmap_free(unsigned long *bitmap) -{ - free(bitmap); -} - -static inline bool -bitmap_is_set(const unsigned long *bitmap, size_t offset) -{ - return (*bitmap_unit__(bitmap, offset) & bitmap_bit__(offset)) != 0; -} - -static inline unsigned long * -bitmap_set1(unsigned long *bitmap, size_t offset) -{ - *bitmap_unit__(bitmap, offset) |= bitmap_bit__(offset); - return bitmap; -} - -static inline unsigned long * -bitmap_set0(unsigned long *bitmap, size_t offset) -{ - *bitmap_unit__(bitmap, offset) &= ~bitmap_bit__(offset); - return bitmap; -} - -static inline unsigned long * -bitmap_set(unsigned long *bitmap, size_t offset, bool value) -{ - return (value) ? bitmap_set1(bitmap, offset) : bitmap_set0(bitmap, offset); -} - -/* Sets 'n' bits of a single unit. */ -static inline void -bitmap_set_n__(unsigned long *bitmap, size_t start, size_t n, bool value) -{ - unsigned long mask = ((1UL << n) - 1) << start % BITMAP_ULONG_BITS; - - if (value) { - *bitmap_unit__(bitmap, start) |= mask; - } else { - *bitmap_unit__(bitmap, start) &= ~mask; - } -} - -/* Sets 'count' consecutive bits in 'bitmap', starting at bit offset 'start', - * to 'value'. */ -static inline unsigned long * -bitmap_set_multiple(unsigned long *bitmap, size_t start, size_t count, - bool value) -{ - if (count && start % BITMAP_ULONG_BITS) { - size_t n = MIN(count, BITMAP_ULONG_BITS - start % BITMAP_ULONG_BITS); - - bitmap_set_n__(bitmap, start, n, value); - count -= n; - start += n; - } - for (; count >= BITMAP_ULONG_BITS; count -= BITMAP_ULONG_BITS) { - *bitmap_unit__(bitmap, start) = (unsigned long)!value - 1; - start += BITMAP_ULONG_BITS; - } - if (count) { - bitmap_set_n__(bitmap, start, count, value); - } - return bitmap; -} - -/* Returns the number of 1-bits in the 'n'-bit bitmap at 'bitmap'. */ -static inline size_t -bitmap_count1(const unsigned long int *bitmap, size_t n) -{ - size_t i; - size_t count = 0; - - BUILD_ASSERT(ULONG_MAX <= UINT64_MAX); - for (i = 0; i < BITMAP_N_LONGS(n); i++) { - count += count_1bits(bitmap[i]); - } - return count; -} - -/* "dst &= arg;" for n-bit dst and arg. */ -static inline unsigned long * -bitmap_and(unsigned long *dst, const unsigned long *arg, size_t n) -{ - size_t i; - - for (i = 0; i < BITMAP_N_LONGS(n); i++) { - dst[i] &= arg[i]; - } - return dst; -} - -/* "dst |= arg;" for n-bit dst and arg. */ -static inline unsigned long * -bitmap_or(unsigned long *dst, const unsigned long *arg, size_t n) -{ - size_t i; - - for (i = 0; i < BITMAP_N_LONGS(n); i++) { - dst[i] |= arg[i]; - } - return dst; -} - -/* "dst = ~dst;" for n-bit dst. */ -static inline unsigned long * -bitmap_not(unsigned long *dst, size_t n) -{ - size_t i; - - for (i = 0; i < n / BITMAP_ULONG_BITS; i++) { - dst[i] = ~dst[i]; - } - if (n % BITMAP_ULONG_BITS) { - dst[i] ^= (1UL << (n % BITMAP_ULONG_BITS)) - 1; - } - return dst; -} - -/* Compares the 'n' bits in bitmaps 'a' and 'b'. Returns true if all bits are - * equal, false otherwise. */ -static inline bool -bitmap_equal(const unsigned long *a, const unsigned long *b, size_t n) -{ - if (memcmp(a, b, n / BITMAP_ULONG_BITS * sizeof(unsigned long))) { - return false; - } - if (n % BITMAP_ULONG_BITS) { - unsigned long mask = (1UL << n % BITMAP_ULONG_BITS) - 1; - unsigned long diff = *bitmap_unit__(a, n) ^ *bitmap_unit__(b, n); - - return !(diff & mask); - } - return true; -} - -/* Scans 'bitmap' from bit offset 'start' to 'end', excluding 'end' itself. - * Returns the bit offset of the lowest-numbered bit set to 'target', or 'end' - * if all of the bits are set to '!target'. 'target' is typically a - * compile-time constant, so it makes sense to inline this. Compiler may also - * optimize parts away depending on the 'start' and 'end' values passed in. */ -static inline size_t -bitmap_scan(const unsigned long *bitmap, bool target, size_t start, size_t end) -{ - if (OVS_LIKELY(start < end)) { - unsigned long *p, unit; - - p = bitmap_unit__(bitmap, start); - unit = (target ? *p : ~*p) >> (start % BITMAP_ULONG_BITS); - if (!unit) { - start -= start % BITMAP_ULONG_BITS; /* Round down. */ - start += BITMAP_ULONG_BITS; /* Start of the next unit. */ - - for (; start < end; start += BITMAP_ULONG_BITS) { - unit = target ? *++p : ~*++p; - if (unit) { - goto found; - } - } - return end; - } -found: - start += raw_ctz(unit); /* unit != 0 */ - if (OVS_LIKELY(start < end)) { - return start; - } - } - return end; -} - -/* Returns true if the 1-bits in 'super' are a superset of the 1-bits in 'sub', - * false otherwise. 'super' and 'sub' both have 'n_bits' bits. */ -static inline bool -bitmap_is_superset(const unsigned long int *super, - const unsigned long int *sub, size_t n_bits) -{ - size_t n_longs = bitmap_n_longs(n_bits); - for (size_t i = 0; i < n_longs; i++) { - if (!uint_is_superset(super[i], sub[i])) { - return false; - } - } - return true; -} - -/* Returns true if all of the 'n' bits in 'bitmap' are 0, - * false if at least one bit is a 1.*/ -static inline bool -bitmap_is_all_zeros(const unsigned long *bitmap, size_t n) -{ - return bitmap_scan(bitmap, true, 0, n) == n; -} - -#define BITMAP_FOR_EACH_1_RANGE(IDX, BEGIN, END, BITMAP) \ - for ((IDX) = bitmap_scan(BITMAP, true, BEGIN, END); (IDX) < (END); \ - (IDX) = bitmap_scan(BITMAP, true, (IDX) + 1, END)) -#define BITMAP_FOR_EACH_1(IDX, SIZE, BITMAP) \ - BITMAP_FOR_EACH_1_RANGE(IDX, 0, SIZE, BITMAP) - -/* More efficient access to a map of single ullong. */ -#define ULLONG_FOR_EACH_1(IDX, MAP) \ - for (uint64_t map__ = (MAP); \ - map__ && (((IDX) = raw_ctz(map__)), true); \ - map__ = zero_rightmost_1bit(map__)) - -#define ULLONG_SET0(MAP, OFFSET) ((MAP) &= ~(1ULL << (OFFSET))) -#define ULLONG_SET1(MAP, OFFSET) ((MAP) |= 1ULL << (OFFSET)) - -/* Returns the value of a bit in a map as a bool. */ -#define ULLONG_GET(MAP, OFFSET) !!((MAP) & (1ULL << (OFFSET))) - -#endif /* bitmap.h */ Index: openvswitch-2.17.2/include/internal/bitmap.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/bitmap.h @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef BITMAP_H +#define BITMAP_H 1 + +#include +#include +#include "internal/util.h" + +static inline unsigned long * +bitmap_unit__(const unsigned long *bitmap, size_t offset) +{ + return CONST_CAST(unsigned long *, &bitmap[offset / BITMAP_ULONG_BITS]); +} + +static inline unsigned long +bitmap_bit__(size_t offset) +{ + return 1UL << (offset % BITMAP_ULONG_BITS); +} + +static inline size_t +bitmap_n_longs(size_t n_bits) +{ + return BITMAP_N_LONGS(n_bits); +} + +static inline size_t +bitmap_n_bytes(size_t n_bits) +{ + return bitmap_n_longs(n_bits) * sizeof(unsigned long int); +} + +static inline unsigned long * +bitmap_allocate(size_t n_bits) +{ + return xzalloc(bitmap_n_bytes(n_bits)); +} + +/* Initializes bitmap to all-1-bits and returns the bitmap pointer. */ +static inline unsigned long * +bitmap_init1(unsigned long *bitmap, size_t n_bits) +{ + size_t n_longs = bitmap_n_longs(n_bits); + size_t n_bytes = bitmap_n_bytes(n_bits); + size_t r_bits = n_bits % BITMAP_ULONG_BITS; + + memset(bitmap, 0xff, n_bytes); + if (r_bits) { + bitmap[n_longs - 1] = (1UL << r_bits) - 1; + } + return bitmap; +} + +/* Allocates and returns a bitmap initialized to all-1-bits. */ +static inline unsigned long * +bitmap_allocate1(size_t n_bits) +{ + return bitmap_init1(xmalloc(bitmap_n_bytes(n_bits)), n_bits); +} + +static inline unsigned long * +bitmap_clone(const unsigned long *bitmap, size_t n_bits) +{ + return xmemdup(bitmap, bitmap_n_bytes(n_bits)); +} + +static inline void +bitmap_free(unsigned long *bitmap) +{ + free(bitmap); +} + +static inline bool +bitmap_is_set(const unsigned long *bitmap, size_t offset) +{ + return (*bitmap_unit__(bitmap, offset) & bitmap_bit__(offset)) != 0; +} + +static inline unsigned long * +bitmap_set1(unsigned long *bitmap, size_t offset) +{ + *bitmap_unit__(bitmap, offset) |= bitmap_bit__(offset); + return bitmap; +} + +static inline unsigned long * +bitmap_set0(unsigned long *bitmap, size_t offset) +{ + *bitmap_unit__(bitmap, offset) &= ~bitmap_bit__(offset); + return bitmap; +} + +static inline unsigned long * +bitmap_set(unsigned long *bitmap, size_t offset, bool value) +{ + return (value) ? bitmap_set1(bitmap, offset) : bitmap_set0(bitmap, offset); +} + +/* Sets 'n' bits of a single unit. */ +static inline void +bitmap_set_n__(unsigned long *bitmap, size_t start, size_t n, bool value) +{ + unsigned long mask = ((1UL << n) - 1) << start % BITMAP_ULONG_BITS; + + if (value) { + *bitmap_unit__(bitmap, start) |= mask; + } else { + *bitmap_unit__(bitmap, start) &= ~mask; + } +} + +/* Sets 'count' consecutive bits in 'bitmap', starting at bit offset 'start', + * to 'value'. */ +static inline unsigned long * +bitmap_set_multiple(unsigned long *bitmap, size_t start, size_t count, + bool value) +{ + if (count && start % BITMAP_ULONG_BITS) { + size_t n = MIN(count, BITMAP_ULONG_BITS - start % BITMAP_ULONG_BITS); + + bitmap_set_n__(bitmap, start, n, value); + count -= n; + start += n; + } + for (; count >= BITMAP_ULONG_BITS; count -= BITMAP_ULONG_BITS) { + *bitmap_unit__(bitmap, start) = (unsigned long)!value - 1; + start += BITMAP_ULONG_BITS; + } + if (count) { + bitmap_set_n__(bitmap, start, count, value); + } + return bitmap; +} + +/* Returns the number of 1-bits in the 'n'-bit bitmap at 'bitmap'. */ +static inline size_t +bitmap_count1(const unsigned long int *bitmap, size_t n) +{ + size_t i; + size_t count = 0; + + BUILD_ASSERT(ULONG_MAX <= UINT64_MAX); + for (i = 0; i < BITMAP_N_LONGS(n); i++) { + count += count_1bits(bitmap[i]); + } + return count; +} + +/* "dst &= arg;" for n-bit dst and arg. */ +static inline unsigned long * +bitmap_and(unsigned long *dst, const unsigned long *arg, size_t n) +{ + size_t i; + + for (i = 0; i < BITMAP_N_LONGS(n); i++) { + dst[i] &= arg[i]; + } + return dst; +} + +/* "dst |= arg;" for n-bit dst and arg. */ +static inline unsigned long * +bitmap_or(unsigned long *dst, const unsigned long *arg, size_t n) +{ + size_t i; + + for (i = 0; i < BITMAP_N_LONGS(n); i++) { + dst[i] |= arg[i]; + } + return dst; +} + +/* "dst = ~dst;" for n-bit dst. */ +static inline unsigned long * +bitmap_not(unsigned long *dst, size_t n) +{ + size_t i; + + for (i = 0; i < n / BITMAP_ULONG_BITS; i++) { + dst[i] = ~dst[i]; + } + if (n % BITMAP_ULONG_BITS) { + dst[i] ^= (1UL << (n % BITMAP_ULONG_BITS)) - 1; + } + return dst; +} + +/* Compares the 'n' bits in bitmaps 'a' and 'b'. Returns true if all bits are + * equal, false otherwise. */ +static inline bool +bitmap_equal(const unsigned long *a, const unsigned long *b, size_t n) +{ + if (memcmp(a, b, n / BITMAP_ULONG_BITS * sizeof(unsigned long))) { + return false; + } + if (n % BITMAP_ULONG_BITS) { + unsigned long mask = (1UL << n % BITMAP_ULONG_BITS) - 1; + unsigned long diff = *bitmap_unit__(a, n) ^ *bitmap_unit__(b, n); + + return !(diff & mask); + } + return true; +} + +/* Scans 'bitmap' from bit offset 'start' to 'end', excluding 'end' itself. + * Returns the bit offset of the lowest-numbered bit set to 'target', or 'end' + * if all of the bits are set to '!target'. 'target' is typically a + * compile-time constant, so it makes sense to inline this. Compiler may also + * optimize parts away depending on the 'start' and 'end' values passed in. */ +static inline size_t +bitmap_scan(const unsigned long *bitmap, bool target, size_t start, size_t end) +{ + if (OVS_LIKELY(start < end)) { + unsigned long *p, unit; + + p = bitmap_unit__(bitmap, start); + unit = (target ? *p : ~*p) >> (start % BITMAP_ULONG_BITS); + if (!unit) { + start -= start % BITMAP_ULONG_BITS; /* Round down. */ + start += BITMAP_ULONG_BITS; /* Start of the next unit. */ + + for (; start < end; start += BITMAP_ULONG_BITS) { + unit = target ? *++p : ~*++p; + if (unit) { + goto found; + } + } + return end; + } +found: + start += raw_ctz(unit); /* unit != 0 */ + if (OVS_LIKELY(start < end)) { + return start; + } + } + return end; +} + +/* Returns true if the 1-bits in 'super' are a superset of the 1-bits in 'sub', + * false otherwise. 'super' and 'sub' both have 'n_bits' bits. */ +static inline bool +bitmap_is_superset(const unsigned long int *super, + const unsigned long int *sub, size_t n_bits) +{ + size_t n_longs = bitmap_n_longs(n_bits); + for (size_t i = 0; i < n_longs; i++) { + if (!uint_is_superset(super[i], sub[i])) { + return false; + } + } + return true; +} + +/* Returns true if all of the 'n' bits in 'bitmap' are 0, + * false if at least one bit is a 1.*/ +static inline bool +bitmap_is_all_zeros(const unsigned long *bitmap, size_t n) +{ + return bitmap_scan(bitmap, true, 0, n) == n; +} + +#define BITMAP_FOR_EACH_1_RANGE(IDX, BEGIN, END, BITMAP) \ + for ((IDX) = bitmap_scan(BITMAP, true, BEGIN, END); (IDX) < (END); \ + (IDX) = bitmap_scan(BITMAP, true, (IDX) + 1, END)) +#define BITMAP_FOR_EACH_1(IDX, SIZE, BITMAP) \ + BITMAP_FOR_EACH_1_RANGE(IDX, 0, SIZE, BITMAP) + +/* More efficient access to a map of single ullong. */ +#define ULLONG_FOR_EACH_1(IDX, MAP) \ + for (uint64_t map__ = (MAP); \ + map__ && (((IDX) = raw_ctz(map__)), true); \ + map__ = zero_rightmost_1bit(map__)) + +#define ULLONG_SET0(MAP, OFFSET) ((MAP) &= ~(1ULL << (OFFSET))) +#define ULLONG_SET1(MAP, OFFSET) ((MAP) |= 1ULL << (OFFSET)) + +/* Returns the value of a bit in a map as a bool. */ +#define ULLONG_GET(MAP, OFFSET) !!((MAP) & (1ULL << (OFFSET))) + +#endif /* bitmap.h */ Index: openvswitch-2.17.2/lib/classifier.h =================================================================== --- openvswitch-2.17.2.orig/lib/classifier.h +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 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. - */ - -#ifndef CLASSIFIER_H -#define CLASSIFIER_H 1 - -/* Flow classifier. - * - * - * What? - * ===== - * - * A flow classifier holds any number of "rules", each of which specifies - * values to match for some fields or subfields and a priority. Each OpenFlow - * table is implemented as a flow classifier. - * - * The classifier has two primary design goals. The first is obvious: given a - * set of packet headers, as quickly as possible find the highest-priority rule - * that matches those headers. The following section describes the second - * goal. - * - * - * "Un-wildcarding" - * ================ - * - * A primary goal of the flow classifier is to produce, as a side effect of a - * packet lookup, a wildcard mask that indicates which bits of the packet - * headers were essential to the classification result. Ideally, a 1-bit in - * any position of this mask means that, if the corresponding bit in the packet - * header were flipped, then the classification result might change. A 0-bit - * means that changing the packet header bit would have no effect. Thus, the - * wildcarded bits are the ones that played no role in the classification - * decision. - * - * Such a wildcard mask is useful with datapaths that support installing flows - * that wildcard fields or subfields. If an OpenFlow lookup for a TCP flow - * does not actually look at the TCP source or destination ports, for example, - * then the switch may install into the datapath a flow that wildcards the port - * numbers, which in turn allows the datapath to handle packets that arrive for - * other TCP source or destination ports without additional help from - * ovs-vswitchd. This is useful for the Open vSwitch software and, - * potentially, for ASIC-based switches as well. - * - * Some properties of the wildcard mask: - * - * - "False 1-bits" are acceptable, that is, setting a bit in the wildcard - * mask to 1 will never cause a packet to be forwarded the wrong way. - * As a corollary, a wildcard mask composed of all 1-bits will always - * yield correct (but often needlessly inefficient) behavior. - * - * - "False 0-bits" can cause problems, so they must be avoided. In the - * extreme case, a mask of all 0-bits is only correct if the classifier - * contains only a single flow that matches all packets. - * - * - 0-bits are desirable because they allow the datapath to act more - * autonomously, relying less on ovs-vswitchd to process flow setups, - * thereby improving performance. - * - * - We don't know a good way to generate wildcard masks with the maximum - * (correct) number of 0-bits. We use various approximations, described - * in later sections. - * - * - Wildcard masks for lookups in a given classifier yield a - * non-overlapping set of rules. More specifically: - * - * Consider an classifier C1 filled with an arbitrary collection of rules - * and an empty classifier C2. Now take a set of packet headers H and - * look it up in C1, yielding a highest-priority matching rule R1 and - * wildcard mask M. Form a new classifier rule R2 out of packet headers - * H and mask M, and add R2 to C2 with a fixed priority. If one were to - * do this for every possible set of packet headers H, then this - * process would not attempt to add any overlapping rules to C2, that is, - * any packet lookup using the rules generated by this process matches at - * most one rule in C2. - * - * During the lookup process, the classifier starts out with a wildcard mask - * that is all 0-bits, that is, fully wildcarded. As lookup proceeds, each - * step tends to add constraints to the wildcard mask, that is, change - * wildcarded 0-bits into exact-match 1-bits. We call this "un-wildcarding". - * A lookup step that examines a particular field must un-wildcard that field. - * In general, un-wildcarding is necessary for correctness but undesirable for - * performance. - * - * - * Basic Classifier Design - * ======================= - * - * Suppose that all the rules in a classifier had the same form. For example, - * suppose that they all matched on the source and destination Ethernet address - * and wildcarded all the other fields. Then the obvious way to implement a - * classifier would be a hash table on the source and destination Ethernet - * addresses. If new classification rules came along with a different form, - * you could add a second hash table that hashed on the fields matched in those - * rules. With two hash tables, you look up a given flow in each hash table. - * If there are no matches, the classifier didn't contain a match; if you find - * a match in one of them, that's the result; if you find a match in both of - * them, then the result is the rule with the higher priority. - * - * This is how the classifier works. In a "struct classifier", each form of - * "struct cls_rule" present (based on its ->match.mask) goes into a separate - * "struct cls_subtable". A lookup does a hash lookup in every "struct - * cls_subtable" in the classifier and tracks the highest-priority match that - * it finds. The subtables are kept in a descending priority order according - * to the highest priority rule in each subtable, which allows lookup to skip - * over subtables that can't possibly have a higher-priority match than already - * found. Eliminating lookups through priority ordering aids both classifier - * primary design goals: skipping lookups saves time and avoids un-wildcarding - * fields that those lookups would have examined. - * - * One detail: a classifier can contain multiple rules that are identical other - * than their priority. When this happens, only the highest priority rule out - * of a group of otherwise identical rules is stored directly in the "struct - * cls_subtable", with the other almost-identical rules chained off a linked - * list inside that highest-priority rule. - * - * The following sub-sections describe various optimizations over this simple - * approach. - * - * - * Staged Lookup (Wildcard Optimization) - * ------------------------------------- - * - * Subtable lookup is performed in ranges defined for struct flow, starting - * from metadata (registers, in_port, etc.), then L2 header, L3, and finally - * L4 ports. Whenever it is found that there are no matches in the current - * subtable, the rest of the subtable can be skipped. - * - * Staged lookup does not reduce lookup time, and it may increase it, because - * it changes a single hash table lookup into multiple hash table lookups. - * It reduces un-wildcarding significantly in important use cases. - * - * - * Prefix Tracking (Wildcard Optimization) - * --------------------------------------- - * - * Classifier uses prefix trees ("tries") for tracking the used - * address space, enabling skipping classifier tables containing - * longer masks than necessary for the given address. This reduces - * un-wildcarding for datapath flows in parts of the address space - * without host routes, but consulting extra data structures (the - * tries) may slightly increase lookup time. - * - * Trie lookup is interwoven with staged lookup, so that a trie is - * searched only when the configured trie field becomes relevant for - * the lookup. The trie lookup results are retained so that each trie - * is checked at most once for each classifier lookup. - * - * This implementation tracks the number of rules at each address - * prefix for the whole classifier. More aggressive table skipping - * would be possible by maintaining lists of tables that have prefixes - * at the lengths encountered on tree traversal, or by maintaining - * separate tries for subsets of rules separated by metadata fields. - * - * Prefix tracking is configured via OVSDB "Flow_Table" table, - * "fieldspec" column. "fieldspec" is a string map where a "prefix" - * key tells which fields should be used for prefix tracking. The - * value of the "prefix" key is a comma separated list of field names. - * - * There is a maximum number of fields that can be enabled for any one - * flow table. Currently this limit is 3. - * - * - * Partitioning (Lookup Time and Wildcard Optimization) - * ---------------------------------------------------- - * - * Suppose that a given classifier is being used to handle multiple stages in a - * pipeline using "resubmit", with metadata (that is, the OpenFlow 1.1+ field - * named "metadata") distinguishing between the different stages. For example, - * metadata value 1 might identify ingress rules, metadata value 2 might - * identify ACLs, and metadata value 3 might identify egress rules. Such a - * classifier is essentially partitioned into multiple sub-classifiers on the - * basis of the metadata value. - * - * The classifier has a special optimization to speed up matching in this - * scenario: - * - * - Each cls_subtable that matches on metadata gets a tag derived from the - * subtable's mask, so that it is likely that each subtable has a unique - * tag. (Duplicate tags have a performance cost but do not affect - * correctness.) - * - * - For each metadata value matched by any cls_rule, the classifier - * constructs a "struct cls_partition" indexed by the metadata value. - * The cls_partition has a 'tags' member whose value is the bitwise-OR of - * the tags of each cls_subtable that contains any rule that matches on - * the cls_partition's metadata value. In other words, struct - * cls_partition associates metadata values with subtables that need to - * be checked with flows with that specific metadata value. - * - * Thus, a flow lookup can start by looking up the partition associated with - * the flow's metadata, and then skip over any cls_subtable whose 'tag' does - * not intersect the partition's 'tags'. (The flow must also be looked up in - * any cls_subtable that doesn't match on metadata. We handle that by giving - * any such cls_subtable TAG_ALL as its 'tags' so that it matches any tag.) - * - * Partitioning saves lookup time by reducing the number of subtable lookups. - * Each eliminated subtable lookup also reduces the amount of un-wildcarding. - * - * - * Classifier Versioning - * ===================== - * - * Classifier lookups are always done in a specific classifier version, where - * a version is defined to be a natural number. - * - * When a new rule is added to a classifier, it is set to become visible in a - * specific version. If the version number used at insert time is larger than - * any version number currently used in lookups, the new rule is said to be - * invisible to lookups. This means that lookups won't find the rule, but the - * rule is immediately available to classifier iterations. - * - * Similarly, a rule can be marked as to be deleted in a future version. To - * delete a rule in a way to not remove the rule before all ongoing lookups are - * finished, the rule should be made invisible in a specific version number. - * Then, when all the lookups use a later version number, the rule can be - * actually removed from the classifier. - * - * Classifiers can hold duplicate rules (rules with the same match criteria and - * priority) when at most one of these duplicates is visible in any given - * lookup version. The caller responsible for classifier modifications must - * maintain this invariant. - * - * The classifier supports versioning for two reasons: - * - * 1. Support for versioned modifications makes it possible to perform an - * arbitrary series of classifier changes as one atomic transaction, - * where intermediate versions of the classifier are not visible to any - * lookups. Also, when a rule is added for a future version, or marked - * for removal after the current version, such modifications can be - * reverted without any visible effects to any of the current lookups. - * - * 2. Performance: Adding (or deleting) a large set of rules can, in - * pathological cases, have a cost proportional to the number of rules - * already in the classifier. When multiple rules are being added (or - * deleted) in one go, though, this pathological case cost can be - * typically avoided, as long as it is OK for any new rules to be - * invisible until the batch change is complete. - * - * Note that the classifier_replace() function replaces a rule immediately, and - * is therefore not safe to use with versioning. It is still available for the - * users that do not use versioning. - * - * - * Deferred Publication - * ==================== - * - * Removing large number of rules from classifier can be costly, as the - * supporting data structures are teared down, in many cases just to be - * re-instantiated right after. In the worst case, as when each rule has a - * different match pattern (mask), the maintenance of the match patterns can - * have cost O(N^2), where N is the number of different match patterns. To - * alleviate this, the classifier supports a "deferred mode", in which changes - * in internal data structures needed for future version lookups may not be - * fully computed yet. The computation is finalized when the deferred mode is - * turned off. - * - * This feature can be used with versioning such that all changes to future - * versions are made in the deferred mode. Then, right before making the new - * version visible to lookups, the deferred mode is turned off so that all the - * data structures are ready for lookups with the new version number. - * - * To use deferred publication, first call classifier_defer(). Then, modify - * the classifier via additions (classifier_insert() with a specific, future - * version number) and deletions (use cls_rule_make_removable_after_version()). - * Then call classifier_publish(), and after that, announce the new version - * number to be used in lookups. - * - * - * Thread-safety - * ============= - * - * The classifier may safely be accessed by many reader threads concurrently - * and by a single writer, or by multiple writers when they guarantee mutually - * exclusive access to classifier modifications. - * - * Since the classifier rules are RCU protected, the rule destruction after - * removal from the classifier must be RCU postponed. Also, when versioning is - * used, the rule removal itself needs to be typically RCU postponed. In this - * case the rule destruction is doubly RCU postponed, i.e., the second - * ovsrcu_postpone() call to destruct the rule is called from the first RCU - * callback that removes the rule. - * - * Rules that have never been visible to lookups are an exception to the above - * rule. Such rules can be removed immediately, but their destruction must - * still be RCU postponed, as the rule's visibility attribute may be examined - * parallel to the rule's removal. */ - -#include "cmap.h" -#include "openvswitch/match.h" -#include "openvswitch/meta-flow.h" -#include "pvector.h" -#include "rculist.h" -#include "openvswitch/type-props.h" -#include "versions.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Classifier internal data structures. */ -struct cls_subtable; -struct cls_match; - -struct mf_field; -typedef OVSRCU_TYPE(struct mf_field *) rcu_field_ptr; -struct trie_node; -typedef OVSRCU_TYPE(struct trie_node *) rcu_trie_ptr; - -/* Prefix trie for a 'field' */ -struct cls_trie { - rcu_field_ptr field; /* Trie field, or NULL. */ - rcu_trie_ptr root; /* NULL if none. */ -}; - -enum { - CLS_MAX_INDICES = 3, /* Maximum number of lookup indices per subtable. */ - CLS_MAX_TRIES = 3 /* Maximum number of prefix trees per classifier. */ -}; - -/* A flow classifier. */ -struct classifier { - int n_rules; /* Total number of rules. */ - uint8_t n_flow_segments; - uint8_t flow_segments[CLS_MAX_INDICES]; /* Flow segment boundaries to use - * for staged lookup. */ - struct cmap subtables_map; /* Contains "struct cls_subtable"s. */ - struct pvector subtables; - struct cmap partitions; /* Contains "struct cls_partition"s. */ - struct cls_trie tries[CLS_MAX_TRIES]; /* Prefix tries. */ - unsigned int n_tries; - bool publish; /* Make changes visible to lookups? */ -}; - -struct cls_conjunction { - uint32_t id; - uint8_t clause; - uint8_t n_clauses; -}; - -/* A rule to be inserted to the classifier. */ -struct cls_rule { - struct rculist node; /* In struct cls_subtable 'rules_list'. */ - const int priority; /* Larger numbers are higher priorities. */ - OVSRCU_TYPE(struct cls_match *) cls_match; /* NULL if not in a - * classifier. */ - const struct minimatch match; /* Matching rule. */ -}; - -/* Constructor/destructor. Must run single-threaded. */ -void classifier_init(struct classifier *, const uint8_t *flow_segments); -void classifier_destroy(struct classifier *); - -/* Modifiers. Caller MUST exclude concurrent calls from other threads. */ -bool classifier_set_prefix_fields(struct classifier *, - const enum mf_field_id *trie_fields, - unsigned int n_trie_fields); - -void cls_rule_init(struct cls_rule *, const struct match *, int priority); -void cls_rule_init_from_minimatch(struct cls_rule *, const struct minimatch *, - int priority); -void cls_rule_clone(struct cls_rule *, const struct cls_rule *); -void cls_rule_move(struct cls_rule *dst, struct cls_rule *src); -void cls_rule_destroy(struct cls_rule *); - -void cls_rule_set_conjunctions(struct cls_rule *, - const struct cls_conjunction *, size_t n); -void cls_rule_make_invisible_in_version(const struct cls_rule *, - ovs_version_t); -void cls_rule_restore_visibility(const struct cls_rule *); - -void classifier_insert(struct classifier *, const struct cls_rule *, - ovs_version_t, const struct cls_conjunction *, - size_t n_conjunctions); -const struct cls_rule *classifier_replace(struct classifier *, - const struct cls_rule *, - ovs_version_t, - const struct cls_conjunction *, - size_t n_conjunctions); -bool classifier_remove(struct classifier *, const struct cls_rule *); -void classifier_remove_assert(struct classifier *, const struct cls_rule *); -static inline void classifier_defer(struct classifier *); -static inline void classifier_publish(struct classifier *); - -/* Lookups. These are RCU protected and may run concurrently with modifiers - * and each other. */ -const struct cls_rule *classifier_lookup(const struct classifier *, - ovs_version_t, struct flow *, - struct flow_wildcards *); -bool classifier_rule_overlaps(const struct classifier *, - const struct cls_rule *, ovs_version_t); -const struct cls_rule *classifier_find_rule_exactly(const struct classifier *, - const struct cls_rule *, - ovs_version_t); -const struct cls_rule *classifier_find_match_exactly(const struct classifier *, - const struct match *, - int priority, - ovs_version_t); -const struct cls_rule *classifier_find_minimatch_exactly( - const struct classifier *, const struct minimatch *, - int priority, ovs_version_t); - -bool classifier_is_empty(const struct classifier *); -int classifier_count(const struct classifier *); - -/* Classifier rule properties. These are RCU protected and may run - * concurrently with modifiers and each other. */ -bool cls_rule_equal(const struct cls_rule *, const struct cls_rule *); -void cls_rule_format(const struct cls_rule *, const struct tun_table *, - const struct ofputil_port_map *, struct ds *); -bool cls_rule_is_catchall(const struct cls_rule *); -bool cls_rule_is_loose_match(const struct cls_rule *rule, - const struct minimatch *criteria); -bool cls_rule_visible_in_version(const struct cls_rule *, ovs_version_t); - -/* Iteration. - * - * Iteration is lockless and RCU-protected. Concurrent threads may perform all - * kinds of concurrent modifications without ruining the iteration. Obviously, - * any modifications may or may not be visible to the concurrent iterator, but - * all the rules not deleted are visited by the iteration. The iterating - * thread may also modify the classifier rules itself. - * - * 'TARGET' iteration only iterates rules matching the 'TARGET' criteria. - * Rather than looping through all the rules and skipping ones that can't - * match, 'TARGET' iteration skips whole subtables, if the 'TARGET' happens to - * be more specific than the subtable. */ -struct cls_cursor { - const struct classifier *cls; - const struct cls_subtable *subtable; - const struct cls_rule *target; - ovs_version_t version; /* Version to iterate. */ - struct pvector_cursor subtables; - const struct cls_rule *rule; -}; - -struct cls_cursor cls_cursor_start(const struct classifier *, - const struct cls_rule *target, - ovs_version_t); -void cls_cursor_advance(struct cls_cursor *); - -#define CLS_FOR_EACH(RULE, MEMBER, CLS) \ - CLS_FOR_EACH_TARGET(RULE, MEMBER, CLS, NULL, OVS_VERSION_MAX) -#define CLS_FOR_EACH_TARGET(RULE, MEMBER, CLS, TARGET, VERSION) \ - for (struct cls_cursor cursor__ = cls_cursor_start(CLS, TARGET, VERSION); \ - (cursor__.rule \ - ? (INIT_CONTAINER(RULE, cursor__.rule, MEMBER), \ - cls_cursor_advance(&cursor__), \ - true) \ - : false); \ - ) - - -static inline void -classifier_defer(struct classifier *cls) -{ - cls->publish = false; -} - -static inline void -classifier_publish(struct classifier *cls) -{ - cls->publish = true; - pvector_publish(&cls->subtables); -} - -#ifdef __cplusplus -} -#endif -#endif /* classifier.h */ Index: openvswitch-2.17.2/include/internal/classifier.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/classifier.h @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 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. + */ + +#ifndef CLASSIFIER_H +#define CLASSIFIER_H 1 + +/* Flow classifier. + * + * + * What? + * ===== + * + * A flow classifier holds any number of "rules", each of which specifies + * values to match for some fields or subfields and a priority. Each OpenFlow + * table is implemented as a flow classifier. + * + * The classifier has two primary design goals. The first is obvious: given a + * set of packet headers, as quickly as possible find the highest-priority rule + * that matches those headers. The following section describes the second + * goal. + * + * + * "Un-wildcarding" + * ================ + * + * A primary goal of the flow classifier is to produce, as a side effect of a + * packet lookup, a wildcard mask that indicates which bits of the packet + * headers were essential to the classification result. Ideally, a 1-bit in + * any position of this mask means that, if the corresponding bit in the packet + * header were flipped, then the classification result might change. A 0-bit + * means that changing the packet header bit would have no effect. Thus, the + * wildcarded bits are the ones that played no role in the classification + * decision. + * + * Such a wildcard mask is useful with datapaths that support installing flows + * that wildcard fields or subfields. If an OpenFlow lookup for a TCP flow + * does not actually look at the TCP source or destination ports, for example, + * then the switch may install into the datapath a flow that wildcards the port + * numbers, which in turn allows the datapath to handle packets that arrive for + * other TCP source or destination ports without additional help from + * ovs-vswitchd. This is useful for the Open vSwitch software and, + * potentially, for ASIC-based switches as well. + * + * Some properties of the wildcard mask: + * + * - "False 1-bits" are acceptable, that is, setting a bit in the wildcard + * mask to 1 will never cause a packet to be forwarded the wrong way. + * As a corollary, a wildcard mask composed of all 1-bits will always + * yield correct (but often needlessly inefficient) behavior. + * + * - "False 0-bits" can cause problems, so they must be avoided. In the + * extreme case, a mask of all 0-bits is only correct if the classifier + * contains only a single flow that matches all packets. + * + * - 0-bits are desirable because they allow the datapath to act more + * autonomously, relying less on ovs-vswitchd to process flow setups, + * thereby improving performance. + * + * - We don't know a good way to generate wildcard masks with the maximum + * (correct) number of 0-bits. We use various approximations, described + * in later sections. + * + * - Wildcard masks for lookups in a given classifier yield a + * non-overlapping set of rules. More specifically: + * + * Consider an classifier C1 filled with an arbitrary collection of rules + * and an empty classifier C2. Now take a set of packet headers H and + * look it up in C1, yielding a highest-priority matching rule R1 and + * wildcard mask M. Form a new classifier rule R2 out of packet headers + * H and mask M, and add R2 to C2 with a fixed priority. If one were to + * do this for every possible set of packet headers H, then this + * process would not attempt to add any overlapping rules to C2, that is, + * any packet lookup using the rules generated by this process matches at + * most one rule in C2. + * + * During the lookup process, the classifier starts out with a wildcard mask + * that is all 0-bits, that is, fully wildcarded. As lookup proceeds, each + * step tends to add constraints to the wildcard mask, that is, change + * wildcarded 0-bits into exact-match 1-bits. We call this "un-wildcarding". + * A lookup step that examines a particular field must un-wildcard that field. + * In general, un-wildcarding is necessary for correctness but undesirable for + * performance. + * + * + * Basic Classifier Design + * ======================= + * + * Suppose that all the rules in a classifier had the same form. For example, + * suppose that they all matched on the source and destination Ethernet address + * and wildcarded all the other fields. Then the obvious way to implement a + * classifier would be a hash table on the source and destination Ethernet + * addresses. If new classification rules came along with a different form, + * you could add a second hash table that hashed on the fields matched in those + * rules. With two hash tables, you look up a given flow in each hash table. + * If there are no matches, the classifier didn't contain a match; if you find + * a match in one of them, that's the result; if you find a match in both of + * them, then the result is the rule with the higher priority. + * + * This is how the classifier works. In a "struct classifier", each form of + * "struct cls_rule" present (based on its ->match.mask) goes into a separate + * "struct cls_subtable". A lookup does a hash lookup in every "struct + * cls_subtable" in the classifier and tracks the highest-priority match that + * it finds. The subtables are kept in a descending priority order according + * to the highest priority rule in each subtable, which allows lookup to skip + * over subtables that can't possibly have a higher-priority match than already + * found. Eliminating lookups through priority ordering aids both classifier + * primary design goals: skipping lookups saves time and avoids un-wildcarding + * fields that those lookups would have examined. + * + * One detail: a classifier can contain multiple rules that are identical other + * than their priority. When this happens, only the highest priority rule out + * of a group of otherwise identical rules is stored directly in the "struct + * cls_subtable", with the other almost-identical rules chained off a linked + * list inside that highest-priority rule. + * + * The following sub-sections describe various optimizations over this simple + * approach. + * + * + * Staged Lookup (Wildcard Optimization) + * ------------------------------------- + * + * Subtable lookup is performed in ranges defined for struct flow, starting + * from metadata (registers, in_port, etc.), then L2 header, L3, and finally + * L4 ports. Whenever it is found that there are no matches in the current + * subtable, the rest of the subtable can be skipped. + * + * Staged lookup does not reduce lookup time, and it may increase it, because + * it changes a single hash table lookup into multiple hash table lookups. + * It reduces un-wildcarding significantly in important use cases. + * + * + * Prefix Tracking (Wildcard Optimization) + * --------------------------------------- + * + * Classifier uses prefix trees ("tries") for tracking the used + * address space, enabling skipping classifier tables containing + * longer masks than necessary for the given address. This reduces + * un-wildcarding for datapath flows in parts of the address space + * without host routes, but consulting extra data structures (the + * tries) may slightly increase lookup time. + * + * Trie lookup is interwoven with staged lookup, so that a trie is + * searched only when the configured trie field becomes relevant for + * the lookup. The trie lookup results are retained so that each trie + * is checked at most once for each classifier lookup. + * + * This implementation tracks the number of rules at each address + * prefix for the whole classifier. More aggressive table skipping + * would be possible by maintaining lists of tables that have prefixes + * at the lengths encountered on tree traversal, or by maintaining + * separate tries for subsets of rules separated by metadata fields. + * + * Prefix tracking is configured via OVSDB "Flow_Table" table, + * "fieldspec" column. "fieldspec" is a string map where a "prefix" + * key tells which fields should be used for prefix tracking. The + * value of the "prefix" key is a comma separated list of field names. + * + * There is a maximum number of fields that can be enabled for any one + * flow table. Currently this limit is 3. + * + * + * Partitioning (Lookup Time and Wildcard Optimization) + * ---------------------------------------------------- + * + * Suppose that a given classifier is being used to handle multiple stages in a + * pipeline using "resubmit", with metadata (that is, the OpenFlow 1.1+ field + * named "metadata") distinguishing between the different stages. For example, + * metadata value 1 might identify ingress rules, metadata value 2 might + * identify ACLs, and metadata value 3 might identify egress rules. Such a + * classifier is essentially partitioned into multiple sub-classifiers on the + * basis of the metadata value. + * + * The classifier has a special optimization to speed up matching in this + * scenario: + * + * - Each cls_subtable that matches on metadata gets a tag derived from the + * subtable's mask, so that it is likely that each subtable has a unique + * tag. (Duplicate tags have a performance cost but do not affect + * correctness.) + * + * - For each metadata value matched by any cls_rule, the classifier + * constructs a "struct cls_partition" indexed by the metadata value. + * The cls_partition has a 'tags' member whose value is the bitwise-OR of + * the tags of each cls_subtable that contains any rule that matches on + * the cls_partition's metadata value. In other words, struct + * cls_partition associates metadata values with subtables that need to + * be checked with flows with that specific metadata value. + * + * Thus, a flow lookup can start by looking up the partition associated with + * the flow's metadata, and then skip over any cls_subtable whose 'tag' does + * not intersect the partition's 'tags'. (The flow must also be looked up in + * any cls_subtable that doesn't match on metadata. We handle that by giving + * any such cls_subtable TAG_ALL as its 'tags' so that it matches any tag.) + * + * Partitioning saves lookup time by reducing the number of subtable lookups. + * Each eliminated subtable lookup also reduces the amount of un-wildcarding. + * + * + * Classifier Versioning + * ===================== + * + * Classifier lookups are always done in a specific classifier version, where + * a version is defined to be a natural number. + * + * When a new rule is added to a classifier, it is set to become visible in a + * specific version. If the version number used at insert time is larger than + * any version number currently used in lookups, the new rule is said to be + * invisible to lookups. This means that lookups won't find the rule, but the + * rule is immediately available to classifier iterations. + * + * Similarly, a rule can be marked as to be deleted in a future version. To + * delete a rule in a way to not remove the rule before all ongoing lookups are + * finished, the rule should be made invisible in a specific version number. + * Then, when all the lookups use a later version number, the rule can be + * actually removed from the classifier. + * + * Classifiers can hold duplicate rules (rules with the same match criteria and + * priority) when at most one of these duplicates is visible in any given + * lookup version. The caller responsible for classifier modifications must + * maintain this invariant. + * + * The classifier supports versioning for two reasons: + * + * 1. Support for versioned modifications makes it possible to perform an + * arbitrary series of classifier changes as one atomic transaction, + * where intermediate versions of the classifier are not visible to any + * lookups. Also, when a rule is added for a future version, or marked + * for removal after the current version, such modifications can be + * reverted without any visible effects to any of the current lookups. + * + * 2. Performance: Adding (or deleting) a large set of rules can, in + * pathological cases, have a cost proportional to the number of rules + * already in the classifier. When multiple rules are being added (or + * deleted) in one go, though, this pathological case cost can be + * typically avoided, as long as it is OK for any new rules to be + * invisible until the batch change is complete. + * + * Note that the classifier_replace() function replaces a rule immediately, and + * is therefore not safe to use with versioning. It is still available for the + * users that do not use versioning. + * + * + * Deferred Publication + * ==================== + * + * Removing large number of rules from classifier can be costly, as the + * supporting data structures are teared down, in many cases just to be + * re-instantiated right after. In the worst case, as when each rule has a + * different match pattern (mask), the maintenance of the match patterns can + * have cost O(N^2), where N is the number of different match patterns. To + * alleviate this, the classifier supports a "deferred mode", in which changes + * in internal data structures needed for future version lookups may not be + * fully computed yet. The computation is finalized when the deferred mode is + * turned off. + * + * This feature can be used with versioning such that all changes to future + * versions are made in the deferred mode. Then, right before making the new + * version visible to lookups, the deferred mode is turned off so that all the + * data structures are ready for lookups with the new version number. + * + * To use deferred publication, first call classifier_defer(). Then, modify + * the classifier via additions (classifier_insert() with a specific, future + * version number) and deletions (use cls_rule_make_removable_after_version()). + * Then call classifier_publish(), and after that, announce the new version + * number to be used in lookups. + * + * + * Thread-safety + * ============= + * + * The classifier may safely be accessed by many reader threads concurrently + * and by a single writer, or by multiple writers when they guarantee mutually + * exclusive access to classifier modifications. + * + * Since the classifier rules are RCU protected, the rule destruction after + * removal from the classifier must be RCU postponed. Also, when versioning is + * used, the rule removal itself needs to be typically RCU postponed. In this + * case the rule destruction is doubly RCU postponed, i.e., the second + * ovsrcu_postpone() call to destruct the rule is called from the first RCU + * callback that removes the rule. + * + * Rules that have never been visible to lookups are an exception to the above + * rule. Such rules can be removed immediately, but their destruction must + * still be RCU postponed, as the rule's visibility attribute may be examined + * parallel to the rule's removal. */ + +#include "internal/cmap.h" +#include "openvswitch/match.h" +#include "openvswitch/meta-flow.h" +#include "internal/pvector.h" +#include "internal/rculist.h" +#include "openvswitch/type-props.h" +#include "internal/versions.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Classifier internal data structures. */ +struct cls_subtable; +struct cls_match; + +struct mf_field; +typedef OVSRCU_TYPE(struct mf_field *) rcu_field_ptr; +struct trie_node; +typedef OVSRCU_TYPE(struct trie_node *) rcu_trie_ptr; + +/* Prefix trie for a 'field' */ +struct cls_trie { + rcu_field_ptr field; /* Trie field, or NULL. */ + rcu_trie_ptr root; /* NULL if none. */ +}; + +enum { + CLS_MAX_INDICES = 3, /* Maximum number of lookup indices per subtable. */ + CLS_MAX_TRIES = 3 /* Maximum number of prefix trees per classifier. */ +}; + +/* A flow classifier. */ +struct classifier { + int n_rules; /* Total number of rules. */ + uint8_t n_flow_segments; + uint8_t flow_segments[CLS_MAX_INDICES]; /* Flow segment boundaries to use + * for staged lookup. */ + struct cmap subtables_map; /* Contains "struct cls_subtable"s. */ + struct pvector subtables; + struct cmap partitions; /* Contains "struct cls_partition"s. */ + struct cls_trie tries[CLS_MAX_TRIES]; /* Prefix tries. */ + unsigned int n_tries; + bool publish; /* Make changes visible to lookups? */ +}; + +struct cls_conjunction { + uint32_t id; + uint8_t clause; + uint8_t n_clauses; +}; + +/* A rule to be inserted to the classifier. */ +struct cls_rule { + struct rculist node; /* In struct cls_subtable 'rules_list'. */ + const int priority; /* Larger numbers are higher priorities. */ + OVSRCU_TYPE(struct cls_match *) cls_match; /* NULL if not in a + * classifier. */ + const struct minimatch match; /* Matching rule. */ +}; + +/* Constructor/destructor. Must run single-threaded. */ +void classifier_init(struct classifier *, const uint8_t *flow_segments); +void classifier_destroy(struct classifier *); + +/* Modifiers. Caller MUST exclude concurrent calls from other threads. */ +bool classifier_set_prefix_fields(struct classifier *, + const enum mf_field_id *trie_fields, + unsigned int n_trie_fields); + +void cls_rule_init(struct cls_rule *, const struct match *, int priority); +void cls_rule_init_from_minimatch(struct cls_rule *, const struct minimatch *, + int priority); +void cls_rule_clone(struct cls_rule *, const struct cls_rule *); +void cls_rule_move(struct cls_rule *dst, struct cls_rule *src); +void cls_rule_destroy(struct cls_rule *); + +void cls_rule_set_conjunctions(struct cls_rule *, + const struct cls_conjunction *, size_t n); +void cls_rule_make_invisible_in_version(const struct cls_rule *, + ovs_version_t); +void cls_rule_restore_visibility(const struct cls_rule *); + +void classifier_insert(struct classifier *, const struct cls_rule *, + ovs_version_t, const struct cls_conjunction *, + size_t n_conjunctions); +const struct cls_rule *classifier_replace(struct classifier *, + const struct cls_rule *, + ovs_version_t, + const struct cls_conjunction *, + size_t n_conjunctions); +bool classifier_remove(struct classifier *, const struct cls_rule *); +void classifier_remove_assert(struct classifier *, const struct cls_rule *); +static inline void classifier_defer(struct classifier *); +static inline void classifier_publish(struct classifier *); + +/* Lookups. These are RCU protected and may run concurrently with modifiers + * and each other. */ +const struct cls_rule *classifier_lookup(const struct classifier *, + ovs_version_t, struct flow *, + struct flow_wildcards *); +bool classifier_rule_overlaps(const struct classifier *, + const struct cls_rule *, ovs_version_t); +const struct cls_rule *classifier_find_rule_exactly(const struct classifier *, + const struct cls_rule *, + ovs_version_t); +const struct cls_rule *classifier_find_match_exactly(const struct classifier *, + const struct match *, + int priority, + ovs_version_t); +const struct cls_rule *classifier_find_minimatch_exactly( + const struct classifier *, const struct minimatch *, + int priority, ovs_version_t); + +bool classifier_is_empty(const struct classifier *); +int classifier_count(const struct classifier *); + +/* Classifier rule properties. These are RCU protected and may run + * concurrently with modifiers and each other. */ +bool cls_rule_equal(const struct cls_rule *, const struct cls_rule *); +void cls_rule_format(const struct cls_rule *, const struct tun_table *, + const struct ofputil_port_map *, struct ds *); +bool cls_rule_is_catchall(const struct cls_rule *); +bool cls_rule_is_loose_match(const struct cls_rule *rule, + const struct minimatch *criteria); +bool cls_rule_visible_in_version(const struct cls_rule *, ovs_version_t); + +/* Iteration. + * + * Iteration is lockless and RCU-protected. Concurrent threads may perform all + * kinds of concurrent modifications without ruining the iteration. Obviously, + * any modifications may or may not be visible to the concurrent iterator, but + * all the rules not deleted are visited by the iteration. The iterating + * thread may also modify the classifier rules itself. + * + * 'TARGET' iteration only iterates rules matching the 'TARGET' criteria. + * Rather than looping through all the rules and skipping ones that can't + * match, 'TARGET' iteration skips whole subtables, if the 'TARGET' happens to + * be more specific than the subtable. */ +struct cls_cursor { + const struct classifier *cls; + const struct cls_subtable *subtable; + const struct cls_rule *target; + ovs_version_t version; /* Version to iterate. */ + struct pvector_cursor subtables; + const struct cls_rule *rule; +}; + +struct cls_cursor cls_cursor_start(const struct classifier *, + const struct cls_rule *target, + ovs_version_t); +void cls_cursor_advance(struct cls_cursor *); + +#define CLS_FOR_EACH(RULE, MEMBER, CLS) \ + CLS_FOR_EACH_TARGET(RULE, MEMBER, CLS, NULL, OVS_VERSION_MAX) +#define CLS_FOR_EACH_TARGET(RULE, MEMBER, CLS, TARGET, VERSION) \ + for (struct cls_cursor cursor__ = cls_cursor_start(CLS, TARGET, VERSION); \ + (cursor__.rule \ + ? (INIT_CONTAINER(RULE, cursor__.rule, MEMBER), \ + cls_cursor_advance(&cursor__), \ + true) \ + : false); \ + ) + + +static inline void +classifier_defer(struct classifier *cls) +{ + cls->publish = false; +} + +static inline void +classifier_publish(struct classifier *cls) +{ + cls->publish = true; + pvector_publish(&cls->subtables); +} + +#ifdef __cplusplus +} +#endif +#endif /* classifier.h */ Index: openvswitch-2.17.2/lib/cmap.h =================================================================== --- openvswitch-2.17.2.orig/lib/cmap.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2014, 2016 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 CMAP_H -#define CMAP_H 1 - -#include -#include -#include "ovs-rcu.h" -#include "util.h" - -/* Concurrent hash map - * =================== - * - * A single-writer, multiple-reader hash table that efficiently supports - * duplicates. - * - * - * Thread-safety - * ============= - * - * The general rules are: - * - * - Only a single thread may safely call into cmap_insert(), - * cmap_remove(), or cmap_replace() at any given time. - * - * - Any number of threads may use functions and macros that search or - * iterate through a given cmap, even in parallel with other threads - * calling cmap_insert(), cmap_remove(), or cmap_replace(). - * - * There is one exception: cmap_find_protected() is only safe if no thread - * is currently calling cmap_insert(), cmap_remove(), or cmap_replace(). - * (Use ordinary cmap_find() if that is not guaranteed.) - * - * - See "Iteration" below for additional thread safety rules. - * - * Writers must use special care to ensure that any elements that they remove - * do not get freed or reused until readers have finished with them. This - * includes inserting the element back into its original cmap or a different - * one. One correct way to do this is to free them from an RCU callback with - * ovsrcu_postpone(). - */ - -/* A concurrent hash map node, to be embedded inside the data structure being - * mapped. - * - * All nodes linked together on a chain have exactly the same hash value. */ -struct cmap_node { - OVSRCU_TYPE(struct cmap_node *) next; /* Next node with same hash. */ -}; - -static inline struct cmap_node * -cmap_node_next(const struct cmap_node *node) -{ - return ovsrcu_get(struct cmap_node *, &node->next); -} - -static inline struct cmap_node * -cmap_node_next_protected(const struct cmap_node *node) -{ - return ovsrcu_get_protected(struct cmap_node *, &node->next); -} - -/* Concurrent hash map. */ -struct cmap { - OVSRCU_TYPE(struct cmap_impl *) impl; -}; - -/* Initializer for an empty cmap. */ -#define CMAP_INITIALIZER { \ - .impl = OVSRCU_INITIALIZER((struct cmap_impl *) &empty_cmap) \ - } -extern OVS_ALIGNED_VAR(CACHE_LINE_SIZE) const struct cmap_impl empty_cmap; - -/* Initialization. */ -void cmap_init(struct cmap *); -void cmap_destroy(struct cmap *); - -/* Count. */ -size_t cmap_count(const struct cmap *); -bool cmap_is_empty(const struct cmap *); - -/* Insertion and deletion. Return the current count after the operation. */ -size_t cmap_insert(struct cmap *, struct cmap_node *, uint32_t hash); -static inline size_t cmap_remove(struct cmap *, struct cmap_node *, - uint32_t hash); -size_t cmap_replace(struct cmap *, struct cmap_node *old_node, - struct cmap_node *new_node, uint32_t hash); - -/* Search. - * - * These macros iterate NODE over all of the nodes in CMAP that have hash value - * equal to HASH. MEMBER must be the name of the 'struct cmap_node' member - * within NODE. - * - * CMAP and HASH are evaluated only once. NODE is evaluated many times. - * - * After a normal exit of the loop (not through a "break;" statement) NODE is - * NULL. - * - * Thread-safety - * ============= - * - * CMAP_NODE_FOR_EACH will reliably visit each of the nodes starting with - * CMAP_NODE, even with concurrent insertions and deletions. (Of - * course, if nodes are being inserted or deleted, it might or might not visit - * the nodes actually being inserted or deleted.) - * - * CMAP_NODE_FOR_EACH_PROTECTED may only be used if the containing CMAP is - * guaranteed not to change during iteration. It may be only slightly faster. - * - * CMAP_FOR_EACH_WITH_HASH will reliably visit each of the nodes with the - * specified hash in CMAP, even with concurrent insertions and deletions. (Of - * course, if nodes with the given HASH are being inserted or deleted, it might - * or might not visit the nodes actually being inserted or deleted.) - * - * CMAP_FOR_EACH_WITH_HASH_PROTECTED may only be used if CMAP is guaranteed not - * to change during iteration. It may be very slightly faster. - */ -#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE) \ - for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE, struct cmap_node); \ - CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ - UPDATE_MULTIVAR(NODE, cmap_node_next(ITER_VAR(NODE)))) -#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE) \ - for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE, struct cmap_node); \ - CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ - UPDATE_MULTIVAR(NODE, cmap_node_next_protected(ITER_VAR(NODE)))) - -#define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP) \ - CMAP_NODE_FOR_EACH(NODE, MEMBER, cmap_find(CMAP, HASH)) -#define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP) \ - CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, cmap_find_protected(CMAP, HASH)) - -const struct cmap_node *cmap_find(const struct cmap *, uint32_t hash); -struct cmap_node *cmap_find_protected(const struct cmap *, uint32_t hash); - -/* Find node by index or find index by hash. The 'index' of a cmap entry is a - * way to combine the specific bucket and the entry of the bucket into a - * convenient single integer value. In other words, it is the index of the - * entry and each entry has an unique index. It is not used internally by - * cmap. - * Currently the functions assume index will not be larger than uint32_t. In - * OvS table size is usually much smaller than this size.*/ -const struct cmap_node * cmap_find_by_index(const struct cmap *, - uint32_t index); -uint32_t cmap_find_index(const struct cmap *, uint32_t hash); - -/* Looks up multiple 'hashes', when the corresponding bit in 'map' is 1, - * and sets the corresponding pointer in 'nodes', if the hash value was - * found from the 'cmap'. In other cases the 'nodes' values are not changed, - * i.e., no NULL pointers are stored there. - * Returns a map where a bit is set to 1 if the corresponding 'nodes' pointer - * was stored, 0 otherwise. - * Generally, the caller wants to use CMAP_NODE_FOR_EACH to verify for - * hash collisions. */ -unsigned long cmap_find_batch(const struct cmap *cmap, unsigned long map, - uint32_t hashes[], - const struct cmap_node *nodes[]); - -/* Iteration. - * - * - * Thread-safety - * ============= - * - * Iteration is safe even in a cmap that is changing concurrently. However: - * - * - In the presence of concurrent calls to cmap_insert(), any given - * iteration might skip some nodes and might visit some nodes more than - * once. If this is a problem, then the iterating code should lock the - * data structure (a rwlock can be used to allow multiple threads to - * iterate in parallel). - * - * - Concurrent calls to cmap_remove() don't have the same problem. (A - * node being deleted may be visited once or not at all. Other nodes - * will be visited once.) - * - * - If the cmap is changing, it is not safe to quiesce while iterating. - * Even if the changes are done by the same thread that's performing the - * iteration (Corollary: it is not safe to call cmap_remove() and quiesce - * in the loop body). - * - * - * Example - * ======= - * - * struct my_node { - * struct cmap_node cmap_node; - * int extra_data; - * }; - * - * struct cmap my_map; - * struct my_node *my_node; - * - * cmap_init(&my_map); - * ...add data... - * CMAP_FOR_EACH (my_node, cmap_node, &my_map) { - * ...operate on my_node... - * } - * - * CMAP_FOR_EACH is "safe" in the sense of HMAP_FOR_EACH_SAFE. That is, it is - * safe to free the current node before going on to the next iteration. Most - * of the time, though, this doesn't matter for a cmap because node - * deallocation has to be postponed until the next grace period. This means - * that this guarantee is useful only in deallocation code already executing at - * postponed time, when it is known that the RCU grace period has already - * expired. - */ - -#define CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER) \ - ((CURSOR)->node \ - ? (INIT_CONTAINER(NODE, (CURSOR)->node, MEMBER), \ - cmap_cursor_advance(CURSOR), \ - true) \ - : (NODE = NULL, false)) - -#define CMAP_CURSOR_FOR_EACH(NODE, MEMBER, CURSOR, CMAP) \ - for (*(CURSOR) = cmap_cursor_start(CMAP); \ - CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER); \ - ) - -#define CMAP_CURSOR_FOR_EACH_CONTINUE(NODE, MEMBER, CURSOR) \ - while (CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER)) - -struct cmap_cursor { - const struct cmap_impl *impl; - uint32_t bucket_idx; - int entry_idx; - struct cmap_node *node; -}; - -struct cmap_cursor cmap_cursor_start(const struct cmap *); -void cmap_cursor_advance(struct cmap_cursor *); - -/* Generate a unique name for the cursor with the __COUNTER__ macro to - * allow nesting of CMAP_FOR_EACH loops. */ -#define CMAP_FOR_EACH__(NODE, MEMBER, CMAP, CURSOR_NAME) \ - for (struct cmap_cursor CURSOR_NAME = cmap_cursor_start(CMAP); \ - CMAP_CURSOR_FOR_EACH__(NODE, &CURSOR_NAME, MEMBER); \ - ) - -#define CMAP_FOR_EACH(NODE, MEMBER, CMAP) \ - CMAP_FOR_EACH__(NODE, MEMBER, CMAP, \ - OVS_JOIN(cursor_, __COUNTER__)) - -static inline struct cmap_node *cmap_first(const struct cmap *); - -/* Another, less preferred, form of iteration, for use in situations where it - * is difficult to maintain a pointer to a cmap_node. */ -struct cmap_position { - unsigned int bucket; - unsigned int entry; - unsigned int offset; -}; - -struct cmap_node *cmap_next_position(const struct cmap *, - struct cmap_position *); - -/* Returns the first node in 'cmap', in arbitrary order, or a null pointer if - * 'cmap' is empty. */ -static inline struct cmap_node * -cmap_first(const struct cmap *cmap) -{ - struct cmap_position pos = { 0, 0, 0 }; - - return cmap_next_position(cmap, &pos); -} - -/* Removes 'node' from 'cmap'. The caller must ensure that 'cmap' cannot - * change concurrently (from another thread). - * - * 'node' must not be destroyed or modified or inserted back into 'cmap' or - * into any other concurrent hash map while any other thread might be accessing - * it. One correct way to do this is to free it from an RCU callback with - * ovsrcu_postpone(). - * - * Returns the current number of nodes in the cmap after the removal. */ -static inline size_t -cmap_remove(struct cmap *cmap, struct cmap_node *node, uint32_t hash) -{ - return cmap_replace(cmap, node, NULL, hash); -} - -#endif /* cmap.h */ Index: openvswitch-2.17.2/include/internal/cmap.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/cmap.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2014, 2016 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 CMAP_H +#define CMAP_H 1 + +#include +#include +#include "openvswitch/ovs-rcu.h" +#include "internal/util.h" + +/* Concurrent hash map + * =================== + * + * A single-writer, multiple-reader hash table that efficiently supports + * duplicates. + * + * + * Thread-safety + * ============= + * + * The general rules are: + * + * - Only a single thread may safely call into cmap_insert(), + * cmap_remove(), or cmap_replace() at any given time. + * + * - Any number of threads may use functions and macros that search or + * iterate through a given cmap, even in parallel with other threads + * calling cmap_insert(), cmap_remove(), or cmap_replace(). + * + * There is one exception: cmap_find_protected() is only safe if no thread + * is currently calling cmap_insert(), cmap_remove(), or cmap_replace(). + * (Use ordinary cmap_find() if that is not guaranteed.) + * + * - See "Iteration" below for additional thread safety rules. + * + * Writers must use special care to ensure that any elements that they remove + * do not get freed or reused until readers have finished with them. This + * includes inserting the element back into its original cmap or a different + * one. One correct way to do this is to free them from an RCU callback with + * ovsrcu_postpone(). + */ + +/* A concurrent hash map node, to be embedded inside the data structure being + * mapped. + * + * All nodes linked together on a chain have exactly the same hash value. */ +struct cmap_node { + OVSRCU_TYPE(struct cmap_node *) next; /* Next node with same hash. */ +}; + +static inline struct cmap_node * +cmap_node_next(const struct cmap_node *node) +{ + return ovsrcu_get(struct cmap_node *, &node->next); +} + +static inline struct cmap_node * +cmap_node_next_protected(const struct cmap_node *node) +{ + return ovsrcu_get_protected(struct cmap_node *, &node->next); +} + +/* Concurrent hash map. */ +struct cmap { + OVSRCU_TYPE(struct cmap_impl *) impl; +}; + +/* Initializer for an empty cmap. */ +#define CMAP_INITIALIZER { \ + .impl = OVSRCU_INITIALIZER((struct cmap_impl *) &empty_cmap) \ + } +extern OVS_ALIGNED_VAR(CACHE_LINE_SIZE) const struct cmap_impl empty_cmap; + +/* Initialization. */ +void cmap_init(struct cmap *); +void cmap_destroy(struct cmap *); + +/* Count. */ +size_t cmap_count(const struct cmap *); +bool cmap_is_empty(const struct cmap *); + +/* Insertion and deletion. Return the current count after the operation. */ +size_t cmap_insert(struct cmap *, struct cmap_node *, uint32_t hash); +static inline size_t cmap_remove(struct cmap *, struct cmap_node *, + uint32_t hash); +size_t cmap_replace(struct cmap *, struct cmap_node *old_node, + struct cmap_node *new_node, uint32_t hash); + +/* Search. + * + * These macros iterate NODE over all of the nodes in CMAP that have hash value + * equal to HASH. MEMBER must be the name of the 'struct cmap_node' member + * within NODE. + * + * CMAP and HASH are evaluated only once. NODE is evaluated many times. + * + * After a normal exit of the loop (not through a "break;" statement) NODE is + * NULL. + * + * Thread-safety + * ============= + * + * CMAP_NODE_FOR_EACH will reliably visit each of the nodes starting with + * CMAP_NODE, even with concurrent insertions and deletions. (Of + * course, if nodes are being inserted or deleted, it might or might not visit + * the nodes actually being inserted or deleted.) + * + * CMAP_NODE_FOR_EACH_PROTECTED may only be used if the containing CMAP is + * guaranteed not to change during iteration. It may be only slightly faster. + * + * CMAP_FOR_EACH_WITH_HASH will reliably visit each of the nodes with the + * specified hash in CMAP, even with concurrent insertions and deletions. (Of + * course, if nodes with the given HASH are being inserted or deleted, it might + * or might not visit the nodes actually being inserted or deleted.) + * + * CMAP_FOR_EACH_WITH_HASH_PROTECTED may only be used if CMAP is guaranteed not + * to change during iteration. It may be very slightly faster. + */ +#define CMAP_NODE_FOR_EACH(NODE, MEMBER, CMAP_NODE) \ + for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE, struct cmap_node); \ + CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ + UPDATE_MULTIVAR(NODE, cmap_node_next(ITER_VAR(NODE)))) +#define CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, CMAP_NODE) \ + for (INIT_MULTIVAR(NODE, MEMBER, CMAP_NODE, struct cmap_node); \ + CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ + UPDATE_MULTIVAR(NODE, cmap_node_next_protected(ITER_VAR(NODE)))) + +#define CMAP_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, CMAP) \ + CMAP_NODE_FOR_EACH(NODE, MEMBER, cmap_find(CMAP, HASH)) +#define CMAP_FOR_EACH_WITH_HASH_PROTECTED(NODE, MEMBER, HASH, CMAP) \ + CMAP_NODE_FOR_EACH_PROTECTED(NODE, MEMBER, cmap_find_protected(CMAP, HASH)) + +const struct cmap_node *cmap_find(const struct cmap *, uint32_t hash); +struct cmap_node *cmap_find_protected(const struct cmap *, uint32_t hash); + +/* Find node by index or find index by hash. The 'index' of a cmap entry is a + * way to combine the specific bucket and the entry of the bucket into a + * convenient single integer value. In other words, it is the index of the + * entry and each entry has an unique index. It is not used internally by + * cmap. + * Currently the functions assume index will not be larger than uint32_t. In + * OvS table size is usually much smaller than this size.*/ +const struct cmap_node * cmap_find_by_index(const struct cmap *, + uint32_t index); +uint32_t cmap_find_index(const struct cmap *, uint32_t hash); + +/* Looks up multiple 'hashes', when the corresponding bit in 'map' is 1, + * and sets the corresponding pointer in 'nodes', if the hash value was + * found from the 'cmap'. In other cases the 'nodes' values are not changed, + * i.e., no NULL pointers are stored there. + * Returns a map where a bit is set to 1 if the corresponding 'nodes' pointer + * was stored, 0 otherwise. + * Generally, the caller wants to use CMAP_NODE_FOR_EACH to verify for + * hash collisions. */ +unsigned long cmap_find_batch(const struct cmap *cmap, unsigned long map, + uint32_t hashes[], + const struct cmap_node *nodes[]); + +/* Iteration. + * + * + * Thread-safety + * ============= + * + * Iteration is safe even in a cmap that is changing concurrently. However: + * + * - In the presence of concurrent calls to cmap_insert(), any given + * iteration might skip some nodes and might visit some nodes more than + * once. If this is a problem, then the iterating code should lock the + * data structure (a rwlock can be used to allow multiple threads to + * iterate in parallel). + * + * - Concurrent calls to cmap_remove() don't have the same problem. (A + * node being deleted may be visited once or not at all. Other nodes + * will be visited once.) + * + * - If the cmap is changing, it is not safe to quiesce while iterating. + * Even if the changes are done by the same thread that's performing the + * iteration (Corollary: it is not safe to call cmap_remove() and quiesce + * in the loop body). + * + * + * Example + * ======= + * + * struct my_node { + * struct cmap_node cmap_node; + * int extra_data; + * }; + * + * struct cmap my_map; + * struct my_node *my_node; + * + * cmap_init(&my_map); + * ...add data... + * CMAP_FOR_EACH (my_node, cmap_node, &my_map) { + * ...operate on my_node... + * } + * + * CMAP_FOR_EACH is "safe" in the sense of HMAP_FOR_EACH_SAFE. That is, it is + * safe to free the current node before going on to the next iteration. Most + * of the time, though, this doesn't matter for a cmap because node + * deallocation has to be postponed until the next grace period. This means + * that this guarantee is useful only in deallocation code already executing at + * postponed time, when it is known that the RCU grace period has already + * expired. + */ + +#define CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER) \ + ((CURSOR)->node \ + ? (INIT_CONTAINER(NODE, (CURSOR)->node, MEMBER), \ + cmap_cursor_advance(CURSOR), \ + true) \ + : (NODE = NULL, false)) + +#define CMAP_CURSOR_FOR_EACH(NODE, MEMBER, CURSOR, CMAP) \ + for (*(CURSOR) = cmap_cursor_start(CMAP); \ + CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER); \ + ) + +#define CMAP_CURSOR_FOR_EACH_CONTINUE(NODE, MEMBER, CURSOR) \ + while (CMAP_CURSOR_FOR_EACH__(NODE, CURSOR, MEMBER)) + +struct cmap_cursor { + const struct cmap_impl *impl; + uint32_t bucket_idx; + int entry_idx; + struct cmap_node *node; +}; + +struct cmap_cursor cmap_cursor_start(const struct cmap *); +void cmap_cursor_advance(struct cmap_cursor *); + +/* Generate a unique name for the cursor with the __COUNTER__ macro to + * allow nesting of CMAP_FOR_EACH loops. */ +#define CMAP_FOR_EACH__(NODE, MEMBER, CMAP, CURSOR_NAME) \ + for (struct cmap_cursor CURSOR_NAME = cmap_cursor_start(CMAP); \ + CMAP_CURSOR_FOR_EACH__(NODE, &CURSOR_NAME, MEMBER); \ + ) + +#define CMAP_FOR_EACH(NODE, MEMBER, CMAP) \ + CMAP_FOR_EACH__(NODE, MEMBER, CMAP, \ + OVS_JOIN(cursor_, __COUNTER__)) + +static inline struct cmap_node *cmap_first(const struct cmap *); + +/* Another, less preferred, form of iteration, for use in situations where it + * is difficult to maintain a pointer to a cmap_node. */ +struct cmap_position { + unsigned int bucket; + unsigned int entry; + unsigned int offset; +}; + +struct cmap_node *cmap_next_position(const struct cmap *, + struct cmap_position *); + +/* Returns the first node in 'cmap', in arbitrary order, or a null pointer if + * 'cmap' is empty. */ +static inline struct cmap_node * +cmap_first(const struct cmap *cmap) +{ + struct cmap_position pos = { 0, 0, 0 }; + + return cmap_next_position(cmap, &pos); +} + +/* Removes 'node' from 'cmap'. The caller must ensure that 'cmap' cannot + * change concurrently (from another thread). + * + * 'node' must not be destroyed or modified or inserted back into 'cmap' or + * into any other concurrent hash map while any other thread might be accessing + * it. One correct way to do this is to free it from an RCU callback with + * ovsrcu_postpone(). + * + * Returns the current number of nodes in the cmap after the removal. */ +static inline size_t +cmap_remove(struct cmap *cmap, struct cmap_node *node, uint32_t hash) +{ + return cmap_replace(cmap, node, NULL, hash); +} + +#endif /* cmap.h */ Index: openvswitch-2.17.2/lib/coverage.h =================================================================== --- openvswitch-2.17.2.orig/lib/coverage.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef COVERAGE_H -#define COVERAGE_H 1 - -/* This file implements a simple form of coverage instrumentation. Points in - * source code that are of interest must be explicitly annotated with - * COVERAGE_INC. The coverage counters may be logged at any time with - * coverage_log(). - * - * This form of coverage instrumentation is intended to be so lightweight that - * it can be enabled in production builds. It is obviously not a substitute - * for traditional coverage instrumentation with e.g. "gcov", but it is still - * a useful debugging tool. */ - -#include "ovs-thread.h" -#include "openvswitch/compiler.h" - -/* Makes coverage_run run every 5000 ms (5 seconds). - * If this value is redefined, the new value must - * divide 60000 (1 minute). */ -#define COVERAGE_RUN_INTERVAL 5000 -BUILD_ASSERT_DECL(60000 % COVERAGE_RUN_INTERVAL == 0); - -#define COVERAGE_CLEAR_INTERVAL 1000 -BUILD_ASSERT_DECL(COVERAGE_RUN_INTERVAL % COVERAGE_CLEAR_INTERVAL == 0); - -/* Defines the moving average array length. */ -#define MIN_AVG_LEN (60000/COVERAGE_RUN_INTERVAL) -#define HR_AVG_LEN 60 - -/* A coverage counter. */ -struct coverage_counter { - const char *const name; /* Textual name. */ - unsigned int (*const count)(void); /* Gets, zeros this thread's count. */ - unsigned long long int total; /* Total count. */ - unsigned long long int last_total; - /* The moving average arrays. */ - unsigned int min[MIN_AVG_LEN]; - unsigned int hr[HR_AVG_LEN]; -}; - -void coverage_counter_register(struct coverage_counter*); - -/* Defines COUNTER. There must be exactly one such definition at file scope - * within a program. */ -#define COVERAGE_DEFINE(COUNTER) \ - DEFINE_STATIC_PER_THREAD_DATA(unsigned int, \ - counter_##COUNTER, 0); \ - static unsigned int COUNTER##_count(void) \ - { \ - unsigned int *countp = counter_##COUNTER##_get(); \ - unsigned int count = *countp; \ - *countp = 0; \ - return count; \ - } \ - static inline void COUNTER##_add(unsigned int n) \ - { \ - *counter_##COUNTER##_get() += n; \ - } \ - extern struct coverage_counter counter_##COUNTER; \ - struct coverage_counter counter_##COUNTER \ - = { #COUNTER, COUNTER##_count, 0, 0, {0}, {0} }; \ - OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ - coverage_counter_register(&counter_##COUNTER); \ - } - -/* Adds 1 to COUNTER. */ -#define COVERAGE_INC(COUNTER) COVERAGE_ADD(COUNTER, 1) - -/* Adds AMOUNT to COUNTER. */ -#define COVERAGE_ADD(COUNTER, AMOUNT) COUNTER##_add(AMOUNT) - -void coverage_init(void); -void coverage_log(void); -void coverage_clear(void); -void coverage_try_clear(void); -void coverage_run(void); - -#endif /* coverage.h */ Index: openvswitch-2.17.2/include/internal/coverage.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/coverage.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef COVERAGE_H +#define COVERAGE_H 1 + +/* This file implements a simple form of coverage instrumentation. Points in + * source code that are of interest must be explicitly annotated with + * COVERAGE_INC. The coverage counters may be logged at any time with + * coverage_log(). + * + * This form of coverage instrumentation is intended to be so lightweight that + * it can be enabled in production builds. It is obviously not a substitute + * for traditional coverage instrumentation with e.g. "gcov", but it is still + * a useful debugging tool. */ + +#include "openvswitch/ovs-thread.h" +#include "openvswitch/compiler.h" + +/* Makes coverage_run run every 5000 ms (5 seconds). + * If this value is redefined, the new value must + * divide 60000 (1 minute). */ +#define COVERAGE_RUN_INTERVAL 5000 +BUILD_ASSERT_DECL(60000 % COVERAGE_RUN_INTERVAL == 0); + +#define COVERAGE_CLEAR_INTERVAL 1000 +BUILD_ASSERT_DECL(COVERAGE_RUN_INTERVAL % COVERAGE_CLEAR_INTERVAL == 0); + +/* Defines the moving average array length. */ +#define MIN_AVG_LEN (60000/COVERAGE_RUN_INTERVAL) +#define HR_AVG_LEN 60 + +/* A coverage counter. */ +struct coverage_counter { + const char *const name; /* Textual name. */ + unsigned int (*const count)(void); /* Gets, zeros this thread's count. */ + unsigned long long int total; /* Total count. */ + unsigned long long int last_total; + /* The moving average arrays. */ + unsigned int min[MIN_AVG_LEN]; + unsigned int hr[HR_AVG_LEN]; +}; + +void coverage_counter_register(struct coverage_counter*); + +/* Defines COUNTER. There must be exactly one such definition at file scope + * within a program. */ +#define COVERAGE_DEFINE(COUNTER) \ + DEFINE_STATIC_PER_THREAD_DATA(unsigned int, \ + counter_##COUNTER, 0); \ + static unsigned int COUNTER##_count(void) \ + { \ + unsigned int *countp = counter_##COUNTER##_get(); \ + unsigned int count = *countp; \ + *countp = 0; \ + return count; \ + } \ + static inline void COUNTER##_add(unsigned int n) \ + { \ + *counter_##COUNTER##_get() += n; \ + } \ + extern struct coverage_counter counter_##COUNTER; \ + struct coverage_counter counter_##COUNTER \ + = { #COUNTER, COUNTER##_count, 0, 0, {0}, {0} }; \ + OVS_CONSTRUCTOR(COUNTER##_init_coverage) { \ + coverage_counter_register(&counter_##COUNTER); \ + } + +/* Adds 1 to COUNTER. */ +#define COVERAGE_INC(COUNTER) COVERAGE_ADD(COUNTER, 1) + +/* Adds AMOUNT to COUNTER. */ +#define COVERAGE_ADD(COUNTER, AMOUNT) COUNTER##_add(AMOUNT) + +void coverage_init(void); +void coverage_log(void); +void coverage_clear(void); +void coverage_try_clear(void); +void coverage_run(void); + +#endif /* coverage.h */ Index: openvswitch-2.17.2/lib/dhcp.h =================================================================== --- openvswitch-2.17.2.orig/lib/dhcp.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2008, 2011 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DHCP_H -#define DHCP_H 1 - -#include -#include "packets.h" -#include "util.h" - -/* Ports used by DHCP. */ -#define DHCP_SERVER_PORT 67 /* Port used by DHCP server. */ -#define DHCP_CLIENT_PORT 68 /* Port used by DHCP client. */ - -#define DHCP_MAGIC_COOKIE 0x63825363 - -#define DHCP_HEADER_LEN 236 -OVS_PACKED( -struct dhcp_header { - uint8_t op; /* DHCP_BOOTREQUEST or DHCP_BOOTREPLY. */ - uint8_t htype; /* ARP_HRD_ETHERNET (typically). */ - uint8_t hlen; /* ETH_ADDR_LEN (typically). */ - uint8_t hops; /* Hop count; set to 0 by client. */ - ovs_be32 xid; /* Transaction ID. */ - ovs_be16 secs; /* Since client started address acquisition. */ - ovs_be16 flags; /* DHCP_FLAGS_*. */ - ovs_be32 ciaddr; /* Client IP, if it has a lease for one. */ - ovs_be32 yiaddr; /* Client ("your") IP address. */ - ovs_be32 siaddr; /* Next server IP address. */ - ovs_be32 giaddr; /* Relay agent IP address. */ - uint8_t chaddr[16]; /* Client hardware address. */ - char sname[64]; /* Optional server host name. */ - char file[128]; /* Boot file name. */ - /* Followed by variable-length options field. */ -}); -BUILD_ASSERT_DECL(DHCP_HEADER_LEN == sizeof(struct dhcp_header)); - -#define DHCP_OP_REQUEST 1 -#define DHCP_OP_REPLY 2 - -#define DHCP_MSG_DISCOVER 1 -#define DHCP_MSG_OFFER 2 -#define DHCP_MSG_REQUEST 3 -#define DHCP_MSG_ACK 5 -#define DHCP_MSG_NAK 6 - -#define DHCP_OPT_PAD 0 -#define DHCP_OPT_REQ_IP 50 -#define DHCP_OPT_MSG_TYPE 53 -#define DHCP_OPT_END 255 - -#endif /* dhcp.h */ Index: openvswitch-2.17.2/include/internal/dhcp.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/dhcp.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2008, 2011 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DHCP_H +#define DHCP_H 1 + +#include +#include "internal/packets.h" +#include "internal/util.h" + +/* Ports used by DHCP. */ +#define DHCP_SERVER_PORT 67 /* Port used by DHCP server. */ +#define DHCP_CLIENT_PORT 68 /* Port used by DHCP client. */ + +#define DHCP_MAGIC_COOKIE 0x63825363 + +#define DHCP_HEADER_LEN 236 +OVS_PACKED( +struct dhcp_header { + uint8_t op; /* DHCP_BOOTREQUEST or DHCP_BOOTREPLY. */ + uint8_t htype; /* ARP_HRD_ETHERNET (typically). */ + uint8_t hlen; /* ETH_ADDR_LEN (typically). */ + uint8_t hops; /* Hop count; set to 0 by client. */ + ovs_be32 xid; /* Transaction ID. */ + ovs_be16 secs; /* Since client started address acquisition. */ + ovs_be16 flags; /* DHCP_FLAGS_*. */ + ovs_be32 ciaddr; /* Client IP, if it has a lease for one. */ + ovs_be32 yiaddr; /* Client ("your") IP address. */ + ovs_be32 siaddr; /* Next server IP address. */ + ovs_be32 giaddr; /* Relay agent IP address. */ + uint8_t chaddr[16]; /* Client hardware address. */ + char sname[64]; /* Optional server host name. */ + char file[128]; /* Boot file name. */ + /* Followed by variable-length options field. */ +}); +BUILD_ASSERT_DECL(DHCP_HEADER_LEN == sizeof(struct dhcp_header)); + +#define DHCP_OP_REQUEST 1 +#define DHCP_OP_REPLY 2 + +#define DHCP_MSG_DISCOVER 1 +#define DHCP_MSG_OFFER 2 +#define DHCP_MSG_REQUEST 3 +#define DHCP_MSG_ACK 5 +#define DHCP_MSG_NAK 6 + +#define DHCP_OPT_PAD 0 +#define DHCP_OPT_REQ_IP 50 +#define DHCP_OPT_MSG_TYPE 53 +#define DHCP_OPT_END 255 + +#endif /* dhcp.h */ Index: openvswitch-2.17.2/lib/dp-packet.h =================================================================== --- openvswitch-2.17.2.orig/lib/dp-packet.h +++ /dev/null @@ -1,1092 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DPBUF_H -#define DPBUF_H 1 - -#include -#include - -#ifdef DPDK_NETDEV -#include -#include -#endif - -#include "netdev-afxdp.h" -#include "netdev-dpdk.h" -#include "openvswitch/list.h" -#include "packets.h" -#include "util.h" -#include "flow.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum OVS_PACKED_ENUM dp_packet_source { - DPBUF_MALLOC, /* Obtained via malloc(). */ - DPBUF_STACK, /* Un-movable stack space or static buffer. */ - DPBUF_STUB, /* Starts on stack, may expand into heap. */ - DPBUF_DPDK, /* buffer data is from DPDK allocated memory. - * ref to dp_packet_init_dpdk() in dp-packet.c. - */ - DPBUF_AFXDP, /* Buffer data from XDP frame. */ -}; - -#define DP_PACKET_CONTEXT_SIZE 64 - -#ifdef DPDK_NETDEV -#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = DPDK_DEF -#else -#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = GENERIC_DEF -#endif - -/* Bit masks for the 'ol_flags' member of the 'dp_packet' structure. */ -enum dp_packet_offload_mask { - /* Value 0 is not used. */ - /* Is the 'rss_hash' valid? */ - DEF_OL_FLAG(DP_PACKET_OL_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, 0x1), - /* Is the 'flow_mark' valid? */ - DEF_OL_FLAG(DP_PACKET_OL_FLOW_MARK, RTE_MBUF_F_RX_FDIR_ID, 0x2), - /* Bad L4 checksum in the packet. */ - DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_BAD, RTE_MBUF_F_RX_L4_CKSUM_BAD, 0x4), - /* Bad IP checksum in the packet. */ - DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_BAD, RTE_MBUF_F_RX_IP_CKSUM_BAD, 0x8), - /* Valid L4 checksum in the packet. */ - DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_GOOD, RTE_MBUF_F_RX_L4_CKSUM_GOOD, - 0x10), - /* Valid IP checksum in the packet. */ - DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_GOOD, RTE_MBUF_F_RX_IP_CKSUM_GOOD, - 0x20), - /* TCP Segmentation Offload. */ - DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_SEG, RTE_MBUF_F_TX_TCP_SEG, 0x40), - /* Offloaded packet is IPv4. */ - DEF_OL_FLAG(DP_PACKET_OL_TX_IPV4, RTE_MBUF_F_TX_IPV4, 0x80), - /* Offloaded packet is IPv6. */ - DEF_OL_FLAG(DP_PACKET_OL_TX_IPV6, RTE_MBUF_F_TX_IPV6, 0x100), - /* Offload TCP checksum. */ - DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_CKSUM, RTE_MBUF_F_TX_TCP_CKSUM, 0x200), - /* Offload UDP checksum. */ - DEF_OL_FLAG(DP_PACKET_OL_TX_UDP_CKSUM, RTE_MBUF_F_TX_UDP_CKSUM, 0x400), - /* Offload SCTP checksum. */ - DEF_OL_FLAG(DP_PACKET_OL_TX_SCTP_CKSUM, RTE_MBUF_F_TX_SCTP_CKSUM, 0x800), - /* Adding new field requires adding to DP_PACKET_OL_SUPPORTED_MASK. */ -}; - -#define DP_PACKET_OL_SUPPORTED_MASK (DP_PACKET_OL_RSS_HASH | \ - DP_PACKET_OL_FLOW_MARK | \ - DP_PACKET_OL_RX_L4_CKSUM_BAD | \ - DP_PACKET_OL_RX_IP_CKSUM_BAD | \ - DP_PACKET_OL_RX_L4_CKSUM_GOOD | \ - DP_PACKET_OL_RX_IP_CKSUM_GOOD | \ - DP_PACKET_OL_TX_TCP_SEG | \ - DP_PACKET_OL_TX_IPV4 | \ - DP_PACKET_OL_TX_IPV6 | \ - DP_PACKET_OL_TX_TCP_CKSUM | \ - DP_PACKET_OL_TX_UDP_CKSUM | \ - DP_PACKET_OL_TX_SCTP_CKSUM) - -#define DP_PACKET_OL_TX_L4_MASK (DP_PACKET_OL_TX_TCP_CKSUM | \ - DP_PACKET_OL_TX_UDP_CKSUM | \ - DP_PACKET_OL_TX_SCTP_CKSUM) -#define DP_PACKET_OL_RX_IP_CKSUM_MASK (DP_PACKET_OL_RX_IP_CKSUM_GOOD | \ - DP_PACKET_OL_RX_IP_CKSUM_BAD) -#define DP_PACKET_OL_RX_L4_CKSUM_MASK (DP_PACKET_OL_RX_L4_CKSUM_GOOD | \ - DP_PACKET_OL_RX_L4_CKSUM_BAD) - -/* Buffer for holding packet data. A dp_packet is automatically reallocated - * as necessary if it grows too large for the available memory. - * By default the packet type is set to Ethernet (PT_ETH). - */ -struct dp_packet { -#ifdef DPDK_NETDEV - struct rte_mbuf mbuf; /* DPDK mbuf */ -#else - void *base_; /* First byte of allocated space. */ - uint16_t allocated_; /* Number of bytes allocated. */ - uint16_t data_ofs; /* First byte actually in use. */ - uint32_t size_; /* Number of bytes in use. */ - uint32_t ol_flags; /* Offloading flags. */ - uint32_t rss_hash; /* Packet hash. */ - uint32_t flow_mark; /* Packet flow mark. */ -#endif - enum dp_packet_source source; /* Source of memory allocated as 'base'. */ - - /* All the following elements of this struct are copied in a single call - * of memcpy in dp_packet_clone_with_headroom. */ - uint16_t l2_pad_size; /* Detected l2 padding size. - * Padding is non-pullable. */ - uint16_t l2_5_ofs; /* MPLS label stack offset, or UINT16_MAX */ - uint16_t l3_ofs; /* Network-level header offset, - * or UINT16_MAX. */ - uint16_t l4_ofs; /* Transport-level header offset, - or UINT16_MAX. */ - uint32_t cutlen; /* length in bytes to cut from the end. */ - ovs_be32 packet_type; /* Packet type as defined in OpenFlow */ - union { - struct pkt_metadata md; - uint64_t data[DP_PACKET_CONTEXT_SIZE / 8]; - }; -}; - -#if HAVE_AF_XDP -struct dp_packet_afxdp { - struct umem_pool *mpool; - struct dp_packet packet; -}; -#endif - -static inline void *dp_packet_data(const struct dp_packet *); -static inline void dp_packet_set_data(struct dp_packet *, void *); -static inline void *dp_packet_base(const struct dp_packet *); -static inline void dp_packet_set_base(struct dp_packet *, void *); - -static inline uint32_t dp_packet_size(const struct dp_packet *); -static inline void dp_packet_set_size(struct dp_packet *, uint32_t); - -static inline uint16_t dp_packet_get_allocated(const struct dp_packet *); -static inline void dp_packet_set_allocated(struct dp_packet *, uint16_t); - -void *dp_packet_resize_l2(struct dp_packet *, int increment); -void *dp_packet_resize_l2_5(struct dp_packet *, int increment); -static inline void *dp_packet_eth(const struct dp_packet *); -static inline void dp_packet_reset_offsets(struct dp_packet *); -static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *); -static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t); -static inline void *dp_packet_l2_5(const struct dp_packet *); -static inline void dp_packet_set_l2_5(struct dp_packet *, void *); -static inline void *dp_packet_l3(const struct dp_packet *); -static inline void dp_packet_set_l3(struct dp_packet *, void *); -static inline void *dp_packet_l4(const struct dp_packet *); -static inline void dp_packet_set_l4(struct dp_packet *, void *); -static inline size_t dp_packet_l4_size(const struct dp_packet *); -static inline const void *dp_packet_get_tcp_payload(const struct dp_packet *); -static inline const void *dp_packet_get_udp_payload(const struct dp_packet *); -static inline const void *dp_packet_get_sctp_payload(const struct dp_packet *); -static inline const void *dp_packet_get_icmp_payload(const struct dp_packet *); -static inline const void *dp_packet_get_nd_payload(const struct dp_packet *); - -void dp_packet_use(struct dp_packet *, void *, size_t); -void dp_packet_use_stub(struct dp_packet *, void *, size_t); -void dp_packet_use_const(struct dp_packet *, const void *, size_t); -#if HAVE_AF_XDP -void dp_packet_use_afxdp(struct dp_packet *, void *, size_t, size_t); -#endif -void dp_packet_init_dpdk(struct dp_packet *); - -void dp_packet_init(struct dp_packet *, size_t); -void dp_packet_uninit(struct dp_packet *); - -struct dp_packet *dp_packet_new(size_t); -struct dp_packet *dp_packet_new_with_headroom(size_t, size_t headroom); -struct dp_packet *dp_packet_clone(const struct dp_packet *); -struct dp_packet *dp_packet_clone_with_headroom(const struct dp_packet *, - size_t headroom); -struct dp_packet *dp_packet_clone_data(const void *, size_t); -struct dp_packet *dp_packet_clone_data_with_headroom(const void *, size_t, - size_t headroom); -void dp_packet_resize(struct dp_packet *b, size_t new_headroom, - size_t new_tailroom); -static inline void dp_packet_delete(struct dp_packet *); -static inline void dp_packet_swap(struct dp_packet *, struct dp_packet *); - -static inline void *dp_packet_at(const struct dp_packet *, size_t offset, - size_t size); -static inline void *dp_packet_at_assert(const struct dp_packet *, - size_t offset, size_t size); -static inline void *dp_packet_tail(const struct dp_packet *); -static inline void *dp_packet_end(const struct dp_packet *); - -void *dp_packet_put_uninit(struct dp_packet *, size_t); -void *dp_packet_put_zeros(struct dp_packet *, size_t); -void *dp_packet_put(struct dp_packet *, const void *, size_t); -char *dp_packet_put_hex(struct dp_packet *, const char *s, size_t *n); -void dp_packet_reserve(struct dp_packet *, size_t); -void dp_packet_reserve_with_tailroom(struct dp_packet *, size_t headroom, - size_t tailroom); -void *dp_packet_push_uninit(struct dp_packet *, size_t); -void *dp_packet_push_zeros(struct dp_packet *, size_t); -void *dp_packet_push(struct dp_packet *, const void *, size_t); - -static inline size_t dp_packet_headroom(const struct dp_packet *); -static inline size_t dp_packet_tailroom(const struct dp_packet *); -void dp_packet_prealloc_headroom(struct dp_packet *, size_t); -void dp_packet_prealloc_tailroom(struct dp_packet *, size_t); -void dp_packet_shift(struct dp_packet *, int); - -static inline void dp_packet_clear(struct dp_packet *); -static inline void *dp_packet_pull(struct dp_packet *, size_t); -static inline void *dp_packet_try_pull(struct dp_packet *, size_t); - -void *dp_packet_steal_data(struct dp_packet *); - -static inline bool dp_packet_equal(const struct dp_packet *, - const struct dp_packet *); - - -/* Frees memory that 'b' points to, as well as 'b' itself. */ -static inline void -dp_packet_delete(struct dp_packet *b) -{ - if (b) { - if (b->source == DPBUF_DPDK) { - /* If this dp_packet was allocated by DPDK it must have been - * created as a dp_packet */ - free_dpdk_buf((struct dp_packet*) b); - return; - } - - if (b->source == DPBUF_AFXDP) { - free_afxdp_buf(b); - return; - } - - dp_packet_uninit(b); - free(b); - } -} - -/* Swaps content of two packets. */ -static inline void -dp_packet_swap(struct dp_packet *a, struct dp_packet *b) -{ - ovs_assert(a->source == DPBUF_MALLOC || a->source == DPBUF_STUB); - ovs_assert(b->source == DPBUF_MALLOC || b->source == DPBUF_STUB); - struct dp_packet c = *a; - - *a = *b; - *b = c; -} - -/* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to - * byte 'offset'. Otherwise, returns a null pointer. */ -static inline void * -dp_packet_at(const struct dp_packet *b, size_t offset, size_t size) -{ - return offset + size <= dp_packet_size(b) - ? (char *) dp_packet_data(b) + offset - : NULL; -} - -/* Returns a pointer to byte 'offset' in 'b', which must contain at least - * 'offset + size' bytes of data. */ -static inline void * -dp_packet_at_assert(const struct dp_packet *b, size_t offset, size_t size) -{ - ovs_assert(offset + size <= dp_packet_size(b)); - return ((char *) dp_packet_data(b)) + offset; -} - -/* Returns a pointer to byte following the last byte of data in use in 'b'. */ -static inline void * -dp_packet_tail(const struct dp_packet *b) -{ - return (char *) dp_packet_data(b) + dp_packet_size(b); -} - -/* Returns a pointer to byte following the last byte allocated for use (but - * not necessarily in use) in 'b'. */ -static inline void * -dp_packet_end(const struct dp_packet *b) -{ - return (char *) dp_packet_base(b) + dp_packet_get_allocated(b); -} - -/* Returns the number of bytes of headroom in 'b', that is, the number of bytes - * of unused space in dp_packet 'b' before the data that is in use. (Most - * commonly, the data in a dp_packet is at its beginning, and thus the - * dp_packet's headroom is 0.) */ -static inline size_t -dp_packet_headroom(const struct dp_packet *b) -{ - return (char *) dp_packet_data(b) - (char *) dp_packet_base(b); -} - -/* Returns the number of bytes that may be appended to the tail end of - * dp_packet 'b' before the dp_packet must be reallocated. */ -static inline size_t -dp_packet_tailroom(const struct dp_packet *b) -{ - return (char *) dp_packet_end(b) - (char *) dp_packet_tail(b); -} - -/* Clears any data from 'b'. */ -static inline void -dp_packet_clear(struct dp_packet *b) -{ - dp_packet_set_data(b, dp_packet_base(b)); - dp_packet_set_size(b, 0); -} - -/* Removes 'size' bytes from the head end of 'b', which must contain at least - * 'size' bytes of data. Returns the first byte of data removed. */ -static inline void * -dp_packet_pull(struct dp_packet *b, size_t size) -{ - void *data = dp_packet_data(b); - ovs_assert(dp_packet_size(b) - dp_packet_l2_pad_size(b) >= size); - dp_packet_set_data(b, (char *) dp_packet_data(b) + size); - dp_packet_set_size(b, dp_packet_size(b) - size); - return data; -} - -/* If 'b' has at least 'size' bytes of data, removes that many bytes from the - * head end of 'b' and returns the first byte removed. Otherwise, returns a - * null pointer without modifying 'b'. */ -static inline void * -dp_packet_try_pull(struct dp_packet *b, size_t size) -{ - return dp_packet_size(b) - dp_packet_l2_pad_size(b) >= size - ? dp_packet_pull(b, size) : NULL; -} - -static inline bool -dp_packet_equal(const struct dp_packet *a, const struct dp_packet *b) -{ - return dp_packet_size(a) == dp_packet_size(b) && - !memcmp(dp_packet_data(a), dp_packet_data(b), dp_packet_size(a)); -} - -static inline bool -dp_packet_is_eth(const struct dp_packet *b) -{ - return b->packet_type == htonl(PT_ETH); -} - -/* Get the start of the Ethernet frame. 'l3_ofs' marks the end of the l2 - * headers, so return NULL if it is not set. */ -static inline void * -dp_packet_eth(const struct dp_packet *b) -{ - return (dp_packet_is_eth(b) && b->l3_ofs != UINT16_MAX) - ? dp_packet_data(b) : NULL; -} - -/* Resets all layer offsets. 'l3' offset must be set before 'l2' can be - * retrieved. */ -static inline void -dp_packet_reset_offsets(struct dp_packet *b) -{ - b->l2_pad_size = 0; - b->l2_5_ofs = UINT16_MAX; - b->l3_ofs = UINT16_MAX; - b->l4_ofs = UINT16_MAX; -} - -static inline uint16_t -dp_packet_l2_pad_size(const struct dp_packet *b) -{ - return b->l2_pad_size; -} - -static inline void -dp_packet_set_l2_pad_size(struct dp_packet *b, uint16_t pad_size) -{ - ovs_assert(pad_size <= dp_packet_size(b)); - b->l2_pad_size = pad_size; -} - -static inline void * -dp_packet_l2_5(const struct dp_packet *b) -{ - return b->l2_5_ofs != UINT16_MAX - ? (char *) dp_packet_data(b) + b->l2_5_ofs - : NULL; -} - -static inline void -dp_packet_set_l2_5(struct dp_packet *b, void *l2_5) -{ - b->l2_5_ofs = l2_5 - ? (char *) l2_5 - (char *) dp_packet_data(b) - : UINT16_MAX; -} - -static inline void * -dp_packet_l3(const struct dp_packet *b) -{ - return b->l3_ofs != UINT16_MAX - ? (char *) dp_packet_data(b) + b->l3_ofs - : NULL; -} - -static inline void -dp_packet_set_l3(struct dp_packet *b, void *l3) -{ - b->l3_ofs = l3 ? (char *) l3 - (char *) dp_packet_data(b) : UINT16_MAX; -} - -static inline void * -dp_packet_l4(const struct dp_packet *b) -{ - return b->l4_ofs != UINT16_MAX - ? (char *) dp_packet_data(b) + b->l4_ofs - : NULL; -} - -static inline void -dp_packet_set_l4(struct dp_packet *b, void *l4) -{ - b->l4_ofs = l4 ? (char *) l4 - (char *) dp_packet_data(b) : UINT16_MAX; -} - -/* Returns the size of the packet from the beginning of the L3 header to the - * end of the L3 payload. Hence L2 padding is not included. */ -static inline size_t -dp_packet_l3_size(const struct dp_packet *b) -{ - return OVS_LIKELY(b->l3_ofs != UINT16_MAX) - ? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l3(b) - - dp_packet_l2_pad_size(b) - : 0; -} - -/* Returns the size of the packet from the beginning of the L4 header to the - * end of the L4 payload. Hence L2 padding is not included. */ -static inline size_t -dp_packet_l4_size(const struct dp_packet *b) -{ - return OVS_LIKELY(b->l4_ofs != UINT16_MAX) - ? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l4(b) - - dp_packet_l2_pad_size(b) - : 0; -} - -static inline const void * -dp_packet_get_tcp_payload(const struct dp_packet *b) -{ - size_t l4_size = dp_packet_l4_size(b); - - if (OVS_LIKELY(l4_size >= TCP_HEADER_LEN)) { - struct tcp_header *tcp = dp_packet_l4(b); - int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4; - - if (OVS_LIKELY(tcp_len >= TCP_HEADER_LEN && tcp_len <= l4_size)) { - return (const char *)tcp + tcp_len; - } - } - return NULL; -} - -static inline uint32_t -dp_packet_get_tcp_payload_length(const struct dp_packet *pkt) -{ - const char *tcp_payload = dp_packet_get_tcp_payload(pkt); - if (tcp_payload) { - return ((char *) dp_packet_tail(pkt) - dp_packet_l2_pad_size(pkt) - - tcp_payload); - } else { - return 0; - } -} - -static inline const void * -dp_packet_get_udp_payload(const struct dp_packet *b) -{ - return OVS_LIKELY(dp_packet_l4_size(b) >= UDP_HEADER_LEN) - ? (const char *)dp_packet_l4(b) + UDP_HEADER_LEN : NULL; -} - -static inline const void * -dp_packet_get_sctp_payload(const struct dp_packet *b) -{ - return OVS_LIKELY(dp_packet_l4_size(b) >= SCTP_HEADER_LEN) - ? (const char *)dp_packet_l4(b) + SCTP_HEADER_LEN : NULL; -} - -static inline const void * -dp_packet_get_icmp_payload(const struct dp_packet *b) -{ - return OVS_LIKELY(dp_packet_l4_size(b) >= ICMP_HEADER_LEN) - ? (const char *)dp_packet_l4(b) + ICMP_HEADER_LEN : NULL; -} - -static inline const void * -dp_packet_get_nd_payload(const struct dp_packet *b) -{ - return OVS_LIKELY(dp_packet_l4_size(b) >= ND_MSG_LEN) - ? (const char *)dp_packet_l4(b) + ND_MSG_LEN : NULL; -} - -#ifdef DPDK_NETDEV -static inline uint64_t * -dp_packet_ol_flags_ptr(const struct dp_packet *b) -{ - return CONST_CAST(uint64_t *, &b->mbuf.ol_flags); -} - -static inline uint32_t * -dp_packet_rss_ptr(const struct dp_packet *b) -{ - return CONST_CAST(uint32_t *, &b->mbuf.hash.rss); -} - -static inline uint32_t * -dp_packet_flow_mark_ptr(const struct dp_packet *b) -{ - return CONST_CAST(uint32_t *, &b->mbuf.hash.fdir.hi); -} - -#else -static inline uint32_t * -dp_packet_ol_flags_ptr(const struct dp_packet *b) -{ - return CONST_CAST(uint32_t *, &b->ol_flags); -} - -static inline uint32_t * -dp_packet_rss_ptr(const struct dp_packet *b) -{ - return CONST_CAST(uint32_t *, &b->rss_hash); -} - -static inline uint32_t * -dp_packet_flow_mark_ptr(const struct dp_packet *b) -{ - return CONST_CAST(uint32_t *, &b->flow_mark); -} -#endif - -#ifdef DPDK_NETDEV -BUILD_ASSERT_DECL(offsetof(struct dp_packet, mbuf) == 0); - -static inline void -dp_packet_init_specific(struct dp_packet *p) -{ - /* This initialization is needed for packets that do not come from DPDK - * interfaces, when vswitchd is built with --with-dpdk. */ - p->mbuf.ol_flags = p->mbuf.tx_offload = p->mbuf.packet_type = 0; - p->mbuf.nb_segs = 1; - p->mbuf.next = NULL; -} - -static inline void * -dp_packet_base(const struct dp_packet *b) -{ - return b->mbuf.buf_addr; -} - -static inline void -dp_packet_set_base(struct dp_packet *b, void *d) -{ - b->mbuf.buf_addr = d; -} - -static inline uint32_t -dp_packet_size(const struct dp_packet *b) -{ - return b->mbuf.pkt_len; -} - -static inline void -dp_packet_set_size(struct dp_packet *b, uint32_t v) -{ - /* netdev-dpdk does not currently support segmentation; consequently, for - * all intents and purposes, 'data_len' (16 bit) and 'pkt_len' (32 bit) may - * be used interchangably. - * - * On the datapath, it is expected that the size of packets - * (and thus 'v') will always be <= UINT16_MAX; this means that there is no - * loss of accuracy in assigning 'v' to 'data_len'. - */ - b->mbuf.data_len = (uint16_t)v; /* Current seg length. */ - b->mbuf.pkt_len = v; /* Total length of all segments linked to - * this segment. */ -} - -static inline uint16_t -__packet_data(const struct dp_packet *b) -{ - return b->mbuf.data_off; -} - -static inline void -__packet_set_data(struct dp_packet *b, uint16_t v) -{ - b->mbuf.data_off = v; -} - -static inline uint16_t -dp_packet_get_allocated(const struct dp_packet *b) -{ - return b->mbuf.buf_len; -} - -static inline void -dp_packet_set_allocated(struct dp_packet *b, uint16_t s) -{ - b->mbuf.buf_len = s; -} - -#else /* DPDK_NETDEV */ - -static inline void -dp_packet_init_specific(struct dp_packet *p OVS_UNUSED) -{ - /* There are no implementation-specific fields for initialization. */ -} - -static inline void * -dp_packet_base(const struct dp_packet *b) -{ - return b->base_; -} - -static inline void -dp_packet_set_base(struct dp_packet *b, void *d) -{ - b->base_ = d; -} - -static inline uint32_t -dp_packet_size(const struct dp_packet *b) -{ - return b->size_; -} - -static inline void -dp_packet_set_size(struct dp_packet *b, uint32_t v) -{ - b->size_ = v; -} - -static inline uint16_t -__packet_data(const struct dp_packet *b) -{ - return b->data_ofs; -} - -static inline void -__packet_set_data(struct dp_packet *b, uint16_t v) -{ - b->data_ofs = v; -} - -static inline uint16_t -dp_packet_get_allocated(const struct dp_packet *b) -{ - return b->allocated_; -} - -static inline void -dp_packet_set_allocated(struct dp_packet *b, uint16_t s) -{ - b->allocated_ = s; -} - -#endif /* DPDK_NETDEV */ - -static inline void -dp_packet_reset_cutlen(struct dp_packet *b) -{ - b->cutlen = 0; -} - -static inline uint32_t -dp_packet_set_cutlen(struct dp_packet *b, uint32_t max_len) -{ - if (max_len < ETH_HEADER_LEN) { - max_len = ETH_HEADER_LEN; - } - - if (max_len >= dp_packet_size(b)) { - b->cutlen = 0; - } else { - b->cutlen = dp_packet_size(b) - max_len; - } - return b->cutlen; -} - -static inline uint32_t -dp_packet_get_cutlen(const struct dp_packet *b) -{ - /* Always in valid range if user uses dp_packet_set_cutlen. */ - return b->cutlen; -} - -static inline uint32_t -dp_packet_get_send_len(const struct dp_packet *b) -{ - return dp_packet_size(b) - dp_packet_get_cutlen(b); -} - -static inline void * -dp_packet_data(const struct dp_packet *b) -{ - return __packet_data(b) != UINT16_MAX - ? (char *) dp_packet_base(b) + __packet_data(b) : NULL; -} - -static inline void -dp_packet_set_data(struct dp_packet *b, void *data) -{ - if (data) { - __packet_set_data(b, (char *) data - (char *) dp_packet_base(b)); - } else { - __packet_set_data(b, UINT16_MAX); - } -} - -static inline void -dp_packet_reset_packet(struct dp_packet *b, int off) -{ - dp_packet_set_size(b, dp_packet_size(b) - off); - dp_packet_set_data(b, ((unsigned char *) dp_packet_data(b) + off)); - dp_packet_reset_offsets(b); -} - -enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */ - -struct dp_packet_batch { - size_t count; - bool trunc; /* true if the batch needs truncate. */ - struct dp_packet *packets[NETDEV_MAX_BURST]; -}; - -static inline void -dp_packet_batch_init(struct dp_packet_batch *batch) -{ - batch->count = 0; - batch->trunc = false; -} - -static inline void -dp_packet_batch_add__(struct dp_packet_batch *batch, - struct dp_packet *packet, size_t limit) -{ - if (batch->count < limit) { - batch->packets[batch->count++] = packet; - } else { - dp_packet_delete(packet); - } -} - -/* When the batch is full, 'packet' will be dropped and freed. */ -static inline void -dp_packet_batch_add(struct dp_packet_batch *batch, struct dp_packet *packet) -{ - dp_packet_batch_add__(batch, packet, NETDEV_MAX_BURST); -} - -static inline size_t -dp_packet_batch_size(const struct dp_packet_batch *batch) -{ - return batch->count; -} - -/* Clear 'batch' for refill. Use dp_packet_batch_refill() to add - * packets back into the 'batch'. */ -static inline void -dp_packet_batch_refill_init(struct dp_packet_batch *batch) -{ - batch->count = 0; -}; - -static inline void -dp_packet_batch_refill(struct dp_packet_batch *batch, - struct dp_packet *packet, size_t idx) -{ - dp_packet_batch_add__(batch, packet, MIN(NETDEV_MAX_BURST, idx + 1)); -} - -static inline void -dp_packet_batch_init_packet(struct dp_packet_batch *batch, struct dp_packet *p) -{ - dp_packet_batch_init(batch); - batch->count = 1; - batch->packets[0] = p; -} - -static inline bool -dp_packet_batch_is_empty(const struct dp_packet_batch *batch) -{ - return !dp_packet_batch_size(batch); -} - -static inline bool -dp_packet_batch_is_full(const struct dp_packet_batch *batch) -{ - return dp_packet_batch_size(batch) == NETDEV_MAX_BURST; -} - -#define DP_PACKET_BATCH_FOR_EACH(IDX, PACKET, BATCH) \ - for (size_t IDX = 0; IDX < dp_packet_batch_size(BATCH); IDX++) \ - if (PACKET = BATCH->packets[IDX], true) - -/* Use this macro for cases where some packets in the 'BATCH' may be - * dropped after going through each packet in the 'BATCH'. - * - * For packets to stay in the 'BATCH', they need to be refilled back - * into the 'BATCH' by calling dp_packet_batch_refill(). Caller owns - * the packets that are not refilled. - * - * Caller needs to supply 'SIZE', that stores the current number of - * packets in 'BATCH'. It is best to declare this variable with - * the 'const' modifier since it should not be modified by - * the iterator. */ -#define DP_PACKET_BATCH_REFILL_FOR_EACH(IDX, SIZE, PACKET, BATCH) \ - for (dp_packet_batch_refill_init(BATCH), IDX=0; IDX < SIZE; IDX++) \ - if (PACKET = BATCH->packets[IDX], true) - -static inline void -dp_packet_batch_clone(struct dp_packet_batch *dst, - struct dp_packet_batch *src) -{ - struct dp_packet *packet; - - dp_packet_batch_init(dst); - DP_PACKET_BATCH_FOR_EACH (i, packet, src) { - if (i + 1 < dp_packet_batch_size(src)) { - OVS_PREFETCH(src->packets[i + 1]); - } - - uint32_t headroom = dp_packet_headroom(packet); - struct dp_packet *pkt_clone; - - pkt_clone = dp_packet_clone_with_headroom(packet, headroom); - dp_packet_batch_add(dst, pkt_clone); - } - dst->trunc = src->trunc; -} - -static inline void -dp_packet_delete_batch(struct dp_packet_batch *batch, bool should_steal) -{ - if (should_steal) { - struct dp_packet *packet; - - DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { - dp_packet_delete(packet); - } - dp_packet_batch_init(batch); - } -} - -static inline void -dp_packet_batch_init_packet_fields(struct dp_packet_batch *batch) -{ - struct dp_packet *packet; - - DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { - dp_packet_reset_cutlen(packet); - packet->packet_type = htonl(PT_ETH); - } -} - -static inline void -dp_packet_batch_apply_cutlen(struct dp_packet_batch *batch) -{ - if (batch->trunc) { - struct dp_packet *packet; - - DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { - dp_packet_set_size(packet, dp_packet_get_send_len(packet)); - dp_packet_reset_cutlen(packet); - } - batch->trunc = false; - } -} - -static inline void -dp_packet_batch_reset_cutlen(struct dp_packet_batch *batch) -{ - if (batch->trunc) { - struct dp_packet *packet; - - DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { - dp_packet_reset_cutlen(packet); - } - batch->trunc = false; - } -} - -/* Returns the RSS hash of the packet 'p'. Note that the returned value is - * correct only if 'dp_packet_rss_valid(p)' returns 'true'. */ -static inline uint32_t -dp_packet_get_rss_hash(const struct dp_packet *p) -{ - return *dp_packet_rss_ptr(p); -} - -static inline void -dp_packet_set_rss_hash(struct dp_packet *p, uint32_t hash) -{ - *dp_packet_rss_ptr(p) = hash; - *dp_packet_ol_flags_ptr(p) |= DP_PACKET_OL_RSS_HASH; -} - -static inline bool -dp_packet_rss_valid(const struct dp_packet *p) -{ - return *dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RSS_HASH; -} - -static inline void -dp_packet_reset_offload(struct dp_packet *p) -{ - *dp_packet_ol_flags_ptr(p) &= ~DP_PACKET_OL_SUPPORTED_MASK; -} - -static inline bool -dp_packet_has_flow_mark(const struct dp_packet *p, uint32_t *mark) -{ - if (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_FLOW_MARK) { - *mark = *dp_packet_flow_mark_ptr(p); - return true; - } - - return false; -} - -static inline void -dp_packet_set_flow_mark(struct dp_packet *p, uint32_t mark) -{ - *dp_packet_flow_mark_ptr(p) = mark; - *dp_packet_ol_flags_ptr(p) |= DP_PACKET_OL_FLOW_MARK; -} - -/* Returns the L4 cksum offload bitmask. */ -static inline uint64_t -dp_packet_hwol_l4_mask(const struct dp_packet *b) -{ - return *dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK; -} - -/* Return true if the packet 'b' requested L4 checksum offload. */ -static inline bool -dp_packet_hwol_tx_l4_checksum(const struct dp_packet *b) -{ - return !!dp_packet_hwol_l4_mask(b); -} - -/* Returns 'true' if packet 'b' is marked for TCP segmentation offloading. */ -static inline bool -dp_packet_hwol_is_tso(const struct dp_packet *b) -{ - return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_TCP_SEG); -} - -/* Returns 'true' if packet 'b' is marked for IPv4 checksum offloading. */ -static inline bool -dp_packet_hwol_is_ipv4(const struct dp_packet *b) -{ - return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_IPV4); -} - -/* Returns 'true' if packet 'b' is marked for TCP checksum offloading. */ -static inline bool -dp_packet_hwol_l4_is_tcp(const struct dp_packet *b) -{ - return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == - DP_PACKET_OL_TX_TCP_CKSUM; -} - -/* Returns 'true' if packet 'b' is marked for UDP checksum offloading. */ -static inline bool -dp_packet_hwol_l4_is_udp(struct dp_packet *b) -{ - return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == - DP_PACKET_OL_TX_UDP_CKSUM; -} - -/* Returns 'true' if packet 'b' is marked for SCTP checksum offloading. */ -static inline bool -dp_packet_hwol_l4_is_sctp(struct dp_packet *b) -{ - return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == - DP_PACKET_OL_TX_SCTP_CKSUM; -} - -/* Mark packet 'b' for IPv4 checksum offloading. */ -static inline void -dp_packet_hwol_set_tx_ipv4(struct dp_packet *b) -{ - *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_IPV4; -} - -/* Mark packet 'b' for IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_tx_ipv6(struct dp_packet *b) -{ - *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_IPV6; -} - -/* Mark packet 'b' for TCP checksum offloading. It implies that either - * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_csum_tcp(struct dp_packet *b) -{ - *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TCP_CKSUM; -} - -/* Mark packet 'b' for UDP checksum offloading. It implies that either - * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_csum_udp(struct dp_packet *b) -{ - *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_UDP_CKSUM; -} - -/* Mark packet 'b' for SCTP checksum offloading. It implies that either - * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ -static inline void -dp_packet_hwol_set_csum_sctp(struct dp_packet *b) -{ - *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_SCTP_CKSUM; -} - -/* Mark packet 'b' for TCP segmentation offloading. It implies that - * either the packet 'b' is marked for IPv4 or IPv6 checksum offloading - * and also for TCP checksum offloading. */ -static inline void -dp_packet_hwol_set_tcp_seg(struct dp_packet *b) -{ - *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TCP_SEG; -} - -static inline bool -dp_packet_ip_checksum_valid(const struct dp_packet *p) -{ - return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_IP_CKSUM_MASK) == - DP_PACKET_OL_RX_IP_CKSUM_GOOD; -} - -static inline bool -dp_packet_ip_checksum_bad(const struct dp_packet *p) -{ - return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_IP_CKSUM_MASK) == - DP_PACKET_OL_RX_IP_CKSUM_BAD; -} - -static inline bool -dp_packet_l4_checksum_valid(const struct dp_packet *p) -{ - return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_L4_CKSUM_MASK) == - DP_PACKET_OL_RX_L4_CKSUM_GOOD; -} - -static inline bool -dp_packet_l4_checksum_bad(const struct dp_packet *p) -{ - return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_L4_CKSUM_MASK) == - DP_PACKET_OL_RX_L4_CKSUM_BAD; -} - -#ifdef __cplusplus -} -#endif - -#endif /* dp-packet.h */ Index: openvswitch-2.17.2/include/internal/dp-packet.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/dp-packet.h @@ -0,0 +1,1092 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DPBUF_H +#define DPBUF_H 1 + +#include +#include + +#ifdef DPDK_NETDEV +#include +#include +#endif + +#include "internal/netdev-afxdp.h" +#include "internal/netdev-dpdk.h" +#include "openvswitch/list.h" +#include "internal/packets.h" +#include "internal/util.h" +#include "internal/flow.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum OVS_PACKED_ENUM dp_packet_source { + DPBUF_MALLOC, /* Obtained via malloc(). */ + DPBUF_STACK, /* Un-movable stack space or static buffer. */ + DPBUF_STUB, /* Starts on stack, may expand into heap. */ + DPBUF_DPDK, /* buffer data is from DPDK allocated memory. + * ref to dp_packet_init_dpdk() in dp-packet.c. + */ + DPBUF_AFXDP, /* Buffer data from XDP frame. */ +}; + +#define DP_PACKET_CONTEXT_SIZE 64 + +#ifdef DPDK_NETDEV +#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = DPDK_DEF +#else +#define DEF_OL_FLAG(NAME, DPDK_DEF, GENERIC_DEF) NAME = GENERIC_DEF +#endif + +/* Bit masks for the 'ol_flags' member of the 'dp_packet' structure. */ +enum dp_packet_offload_mask { + /* Value 0 is not used. */ + /* Is the 'rss_hash' valid? */ + DEF_OL_FLAG(DP_PACKET_OL_RSS_HASH, RTE_MBUF_F_RX_RSS_HASH, 0x1), + /* Is the 'flow_mark' valid? */ + DEF_OL_FLAG(DP_PACKET_OL_FLOW_MARK, RTE_MBUF_F_RX_FDIR_ID, 0x2), + /* Bad L4 checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_BAD, RTE_MBUF_F_RX_L4_CKSUM_BAD, 0x4), + /* Bad IP checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_BAD, RTE_MBUF_F_RX_IP_CKSUM_BAD, 0x8), + /* Valid L4 checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_L4_CKSUM_GOOD, RTE_MBUF_F_RX_L4_CKSUM_GOOD, + 0x10), + /* Valid IP checksum in the packet. */ + DEF_OL_FLAG(DP_PACKET_OL_RX_IP_CKSUM_GOOD, RTE_MBUF_F_RX_IP_CKSUM_GOOD, + 0x20), + /* TCP Segmentation Offload. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_SEG, RTE_MBUF_F_TX_TCP_SEG, 0x40), + /* Offloaded packet is IPv4. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_IPV4, RTE_MBUF_F_TX_IPV4, 0x80), + /* Offloaded packet is IPv6. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_IPV6, RTE_MBUF_F_TX_IPV6, 0x100), + /* Offload TCP checksum. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_TCP_CKSUM, RTE_MBUF_F_TX_TCP_CKSUM, 0x200), + /* Offload UDP checksum. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_UDP_CKSUM, RTE_MBUF_F_TX_UDP_CKSUM, 0x400), + /* Offload SCTP checksum. */ + DEF_OL_FLAG(DP_PACKET_OL_TX_SCTP_CKSUM, RTE_MBUF_F_TX_SCTP_CKSUM, 0x800), + /* Adding new field requires adding to DP_PACKET_OL_SUPPORTED_MASK. */ +}; + +#define DP_PACKET_OL_SUPPORTED_MASK (DP_PACKET_OL_RSS_HASH | \ + DP_PACKET_OL_FLOW_MARK | \ + DP_PACKET_OL_RX_L4_CKSUM_BAD | \ + DP_PACKET_OL_RX_IP_CKSUM_BAD | \ + DP_PACKET_OL_RX_L4_CKSUM_GOOD | \ + DP_PACKET_OL_RX_IP_CKSUM_GOOD | \ + DP_PACKET_OL_TX_TCP_SEG | \ + DP_PACKET_OL_TX_IPV4 | \ + DP_PACKET_OL_TX_IPV6 | \ + DP_PACKET_OL_TX_TCP_CKSUM | \ + DP_PACKET_OL_TX_UDP_CKSUM | \ + DP_PACKET_OL_TX_SCTP_CKSUM) + +#define DP_PACKET_OL_TX_L4_MASK (DP_PACKET_OL_TX_TCP_CKSUM | \ + DP_PACKET_OL_TX_UDP_CKSUM | \ + DP_PACKET_OL_TX_SCTP_CKSUM) +#define DP_PACKET_OL_RX_IP_CKSUM_MASK (DP_PACKET_OL_RX_IP_CKSUM_GOOD | \ + DP_PACKET_OL_RX_IP_CKSUM_BAD) +#define DP_PACKET_OL_RX_L4_CKSUM_MASK (DP_PACKET_OL_RX_L4_CKSUM_GOOD | \ + DP_PACKET_OL_RX_L4_CKSUM_BAD) + +/* Buffer for holding packet data. A dp_packet is automatically reallocated + * as necessary if it grows too large for the available memory. + * By default the packet type is set to Ethernet (PT_ETH). + */ +struct dp_packet { +#ifdef DPDK_NETDEV + struct rte_mbuf mbuf; /* DPDK mbuf */ +#else + void *base_; /* First byte of allocated space. */ + uint16_t allocated_; /* Number of bytes allocated. */ + uint16_t data_ofs; /* First byte actually in use. */ + uint32_t size_; /* Number of bytes in use. */ + uint32_t ol_flags; /* Offloading flags. */ + uint32_t rss_hash; /* Packet hash. */ + uint32_t flow_mark; /* Packet flow mark. */ +#endif + enum dp_packet_source source; /* Source of memory allocated as 'base'. */ + + /* All the following elements of this struct are copied in a single call + * of memcpy in dp_packet_clone_with_headroom. */ + uint16_t l2_pad_size; /* Detected l2 padding size. + * Padding is non-pullable. */ + uint16_t l2_5_ofs; /* MPLS label stack offset, or UINT16_MAX */ + uint16_t l3_ofs; /* Network-level header offset, + * or UINT16_MAX. */ + uint16_t l4_ofs; /* Transport-level header offset, + or UINT16_MAX. */ + uint32_t cutlen; /* length in bytes to cut from the end. */ + ovs_be32 packet_type; /* Packet type as defined in OpenFlow */ + union { + struct pkt_metadata md; + uint64_t data[DP_PACKET_CONTEXT_SIZE / 8]; + }; +}; + +#if HAVE_AF_XDP +struct dp_packet_afxdp { + struct umem_pool *mpool; + struct dp_packet packet; +}; +#endif + +static inline void *dp_packet_data(const struct dp_packet *); +static inline void dp_packet_set_data(struct dp_packet *, void *); +static inline void *dp_packet_base(const struct dp_packet *); +static inline void dp_packet_set_base(struct dp_packet *, void *); + +static inline uint32_t dp_packet_size(const struct dp_packet *); +static inline void dp_packet_set_size(struct dp_packet *, uint32_t); + +static inline uint16_t dp_packet_get_allocated(const struct dp_packet *); +static inline void dp_packet_set_allocated(struct dp_packet *, uint16_t); + +void *dp_packet_resize_l2(struct dp_packet *, int increment); +void *dp_packet_resize_l2_5(struct dp_packet *, int increment); +static inline void *dp_packet_eth(const struct dp_packet *); +static inline void dp_packet_reset_offsets(struct dp_packet *); +static inline uint16_t dp_packet_l2_pad_size(const struct dp_packet *); +static inline void dp_packet_set_l2_pad_size(struct dp_packet *, uint16_t); +static inline void *dp_packet_l2_5(const struct dp_packet *); +static inline void dp_packet_set_l2_5(struct dp_packet *, void *); +static inline void *dp_packet_l3(const struct dp_packet *); +static inline void dp_packet_set_l3(struct dp_packet *, void *); +static inline void *dp_packet_l4(const struct dp_packet *); +static inline void dp_packet_set_l4(struct dp_packet *, void *); +static inline size_t dp_packet_l4_size(const struct dp_packet *); +static inline const void *dp_packet_get_tcp_payload(const struct dp_packet *); +static inline const void *dp_packet_get_udp_payload(const struct dp_packet *); +static inline const void *dp_packet_get_sctp_payload(const struct dp_packet *); +static inline const void *dp_packet_get_icmp_payload(const struct dp_packet *); +static inline const void *dp_packet_get_nd_payload(const struct dp_packet *); + +void dp_packet_use(struct dp_packet *, void *, size_t); +void dp_packet_use_stub(struct dp_packet *, void *, size_t); +void dp_packet_use_const(struct dp_packet *, const void *, size_t); +#if HAVE_AF_XDP +void dp_packet_use_afxdp(struct dp_packet *, void *, size_t, size_t); +#endif +void dp_packet_init_dpdk(struct dp_packet *); + +void dp_packet_init(struct dp_packet *, size_t); +void dp_packet_uninit(struct dp_packet *); + +struct dp_packet *dp_packet_new(size_t); +struct dp_packet *dp_packet_new_with_headroom(size_t, size_t headroom); +struct dp_packet *dp_packet_clone(const struct dp_packet *); +struct dp_packet *dp_packet_clone_with_headroom(const struct dp_packet *, + size_t headroom); +struct dp_packet *dp_packet_clone_data(const void *, size_t); +struct dp_packet *dp_packet_clone_data_with_headroom(const void *, size_t, + size_t headroom); +void dp_packet_resize(struct dp_packet *b, size_t new_headroom, + size_t new_tailroom); +static inline void dp_packet_delete(struct dp_packet *); +static inline void dp_packet_swap(struct dp_packet *, struct dp_packet *); + +static inline void *dp_packet_at(const struct dp_packet *, size_t offset, + size_t size); +static inline void *dp_packet_at_assert(const struct dp_packet *, + size_t offset, size_t size); +static inline void *dp_packet_tail(const struct dp_packet *); +static inline void *dp_packet_end(const struct dp_packet *); + +void *dp_packet_put_uninit(struct dp_packet *, size_t); +void *dp_packet_put_zeros(struct dp_packet *, size_t); +void *dp_packet_put(struct dp_packet *, const void *, size_t); +char *dp_packet_put_hex(struct dp_packet *, const char *s, size_t *n); +void dp_packet_reserve(struct dp_packet *, size_t); +void dp_packet_reserve_with_tailroom(struct dp_packet *, size_t headroom, + size_t tailroom); +void *dp_packet_push_uninit(struct dp_packet *, size_t); +void *dp_packet_push_zeros(struct dp_packet *, size_t); +void *dp_packet_push(struct dp_packet *, const void *, size_t); + +static inline size_t dp_packet_headroom(const struct dp_packet *); +static inline size_t dp_packet_tailroom(const struct dp_packet *); +void dp_packet_prealloc_headroom(struct dp_packet *, size_t); +void dp_packet_prealloc_tailroom(struct dp_packet *, size_t); +void dp_packet_shift(struct dp_packet *, int); + +static inline void dp_packet_clear(struct dp_packet *); +static inline void *dp_packet_pull(struct dp_packet *, size_t); +static inline void *dp_packet_try_pull(struct dp_packet *, size_t); + +void *dp_packet_steal_data(struct dp_packet *); + +static inline bool dp_packet_equal(const struct dp_packet *, + const struct dp_packet *); + + +/* Frees memory that 'b' points to, as well as 'b' itself. */ +static inline void +dp_packet_delete(struct dp_packet *b) +{ + if (b) { + if (b->source == DPBUF_DPDK) { + /* If this dp_packet was allocated by DPDK it must have been + * created as a dp_packet */ + free_dpdk_buf((struct dp_packet*) b); + return; + } + + if (b->source == DPBUF_AFXDP) { + free_afxdp_buf(b); + return; + } + + dp_packet_uninit(b); + free(b); + } +} + +/* Swaps content of two packets. */ +static inline void +dp_packet_swap(struct dp_packet *a, struct dp_packet *b) +{ + ovs_assert(a->source == DPBUF_MALLOC || a->source == DPBUF_STUB); + ovs_assert(b->source == DPBUF_MALLOC || b->source == DPBUF_STUB); + struct dp_packet c = *a; + + *a = *b; + *b = c; +} + +/* If 'b' contains at least 'offset + size' bytes of data, returns a pointer to + * byte 'offset'. Otherwise, returns a null pointer. */ +static inline void * +dp_packet_at(const struct dp_packet *b, size_t offset, size_t size) +{ + return offset + size <= dp_packet_size(b) + ? (char *) dp_packet_data(b) + offset + : NULL; +} + +/* Returns a pointer to byte 'offset' in 'b', which must contain at least + * 'offset + size' bytes of data. */ +static inline void * +dp_packet_at_assert(const struct dp_packet *b, size_t offset, size_t size) +{ + ovs_assert(offset + size <= dp_packet_size(b)); + return ((char *) dp_packet_data(b)) + offset; +} + +/* Returns a pointer to byte following the last byte of data in use in 'b'. */ +static inline void * +dp_packet_tail(const struct dp_packet *b) +{ + return (char *) dp_packet_data(b) + dp_packet_size(b); +} + +/* Returns a pointer to byte following the last byte allocated for use (but + * not necessarily in use) in 'b'. */ +static inline void * +dp_packet_end(const struct dp_packet *b) +{ + return (char *) dp_packet_base(b) + dp_packet_get_allocated(b); +} + +/* Returns the number of bytes of headroom in 'b', that is, the number of bytes + * of unused space in dp_packet 'b' before the data that is in use. (Most + * commonly, the data in a dp_packet is at its beginning, and thus the + * dp_packet's headroom is 0.) */ +static inline size_t +dp_packet_headroom(const struct dp_packet *b) +{ + return (char *) dp_packet_data(b) - (char *) dp_packet_base(b); +} + +/* Returns the number of bytes that may be appended to the tail end of + * dp_packet 'b' before the dp_packet must be reallocated. */ +static inline size_t +dp_packet_tailroom(const struct dp_packet *b) +{ + return (char *) dp_packet_end(b) - (char *) dp_packet_tail(b); +} + +/* Clears any data from 'b'. */ +static inline void +dp_packet_clear(struct dp_packet *b) +{ + dp_packet_set_data(b, dp_packet_base(b)); + dp_packet_set_size(b, 0); +} + +/* Removes 'size' bytes from the head end of 'b', which must contain at least + * 'size' bytes of data. Returns the first byte of data removed. */ +static inline void * +dp_packet_pull(struct dp_packet *b, size_t size) +{ + void *data = dp_packet_data(b); + ovs_assert(dp_packet_size(b) - dp_packet_l2_pad_size(b) >= size); + dp_packet_set_data(b, (char *) dp_packet_data(b) + size); + dp_packet_set_size(b, dp_packet_size(b) - size); + return data; +} + +/* If 'b' has at least 'size' bytes of data, removes that many bytes from the + * head end of 'b' and returns the first byte removed. Otherwise, returns a + * null pointer without modifying 'b'. */ +static inline void * +dp_packet_try_pull(struct dp_packet *b, size_t size) +{ + return dp_packet_size(b) - dp_packet_l2_pad_size(b) >= size + ? dp_packet_pull(b, size) : NULL; +} + +static inline bool +dp_packet_equal(const struct dp_packet *a, const struct dp_packet *b) +{ + return dp_packet_size(a) == dp_packet_size(b) && + !memcmp(dp_packet_data(a), dp_packet_data(b), dp_packet_size(a)); +} + +static inline bool +dp_packet_is_eth(const struct dp_packet *b) +{ + return b->packet_type == htonl(PT_ETH); +} + +/* Get the start of the Ethernet frame. 'l3_ofs' marks the end of the l2 + * headers, so return NULL if it is not set. */ +static inline void * +dp_packet_eth(const struct dp_packet *b) +{ + return (dp_packet_is_eth(b) && b->l3_ofs != UINT16_MAX) + ? dp_packet_data(b) : NULL; +} + +/* Resets all layer offsets. 'l3' offset must be set before 'l2' can be + * retrieved. */ +static inline void +dp_packet_reset_offsets(struct dp_packet *b) +{ + b->l2_pad_size = 0; + b->l2_5_ofs = UINT16_MAX; + b->l3_ofs = UINT16_MAX; + b->l4_ofs = UINT16_MAX; +} + +static inline uint16_t +dp_packet_l2_pad_size(const struct dp_packet *b) +{ + return b->l2_pad_size; +} + +static inline void +dp_packet_set_l2_pad_size(struct dp_packet *b, uint16_t pad_size) +{ + ovs_assert(pad_size <= dp_packet_size(b)); + b->l2_pad_size = pad_size; +} + +static inline void * +dp_packet_l2_5(const struct dp_packet *b) +{ + return b->l2_5_ofs != UINT16_MAX + ? (char *) dp_packet_data(b) + b->l2_5_ofs + : NULL; +} + +static inline void +dp_packet_set_l2_5(struct dp_packet *b, void *l2_5) +{ + b->l2_5_ofs = l2_5 + ? (char *) l2_5 - (char *) dp_packet_data(b) + : UINT16_MAX; +} + +static inline void * +dp_packet_l3(const struct dp_packet *b) +{ + return b->l3_ofs != UINT16_MAX + ? (char *) dp_packet_data(b) + b->l3_ofs + : NULL; +} + +static inline void +dp_packet_set_l3(struct dp_packet *b, void *l3) +{ + b->l3_ofs = l3 ? (char *) l3 - (char *) dp_packet_data(b) : UINT16_MAX; +} + +static inline void * +dp_packet_l4(const struct dp_packet *b) +{ + return b->l4_ofs != UINT16_MAX + ? (char *) dp_packet_data(b) + b->l4_ofs + : NULL; +} + +static inline void +dp_packet_set_l4(struct dp_packet *b, void *l4) +{ + b->l4_ofs = l4 ? (char *) l4 - (char *) dp_packet_data(b) : UINT16_MAX; +} + +/* Returns the size of the packet from the beginning of the L3 header to the + * end of the L3 payload. Hence L2 padding is not included. */ +static inline size_t +dp_packet_l3_size(const struct dp_packet *b) +{ + return OVS_LIKELY(b->l3_ofs != UINT16_MAX) + ? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l3(b) + - dp_packet_l2_pad_size(b) + : 0; +} + +/* Returns the size of the packet from the beginning of the L4 header to the + * end of the L4 payload. Hence L2 padding is not included. */ +static inline size_t +dp_packet_l4_size(const struct dp_packet *b) +{ + return OVS_LIKELY(b->l4_ofs != UINT16_MAX) + ? (const char *)dp_packet_tail(b) - (const char *)dp_packet_l4(b) + - dp_packet_l2_pad_size(b) + : 0; +} + +static inline const void * +dp_packet_get_tcp_payload(const struct dp_packet *b) +{ + size_t l4_size = dp_packet_l4_size(b); + + if (OVS_LIKELY(l4_size >= TCP_HEADER_LEN)) { + struct tcp_header *tcp = dp_packet_l4(b); + int tcp_len = TCP_OFFSET(tcp->tcp_ctl) * 4; + + if (OVS_LIKELY(tcp_len >= TCP_HEADER_LEN && tcp_len <= l4_size)) { + return (const char *)tcp + tcp_len; + } + } + return NULL; +} + +static inline uint32_t +dp_packet_get_tcp_payload_length(const struct dp_packet *pkt) +{ + const char *tcp_payload = dp_packet_get_tcp_payload(pkt); + if (tcp_payload) { + return ((char *) dp_packet_tail(pkt) - dp_packet_l2_pad_size(pkt) + - tcp_payload); + } else { + return 0; + } +} + +static inline const void * +dp_packet_get_udp_payload(const struct dp_packet *b) +{ + return OVS_LIKELY(dp_packet_l4_size(b) >= UDP_HEADER_LEN) + ? (const char *)dp_packet_l4(b) + UDP_HEADER_LEN : NULL; +} + +static inline const void * +dp_packet_get_sctp_payload(const struct dp_packet *b) +{ + return OVS_LIKELY(dp_packet_l4_size(b) >= SCTP_HEADER_LEN) + ? (const char *)dp_packet_l4(b) + SCTP_HEADER_LEN : NULL; +} + +static inline const void * +dp_packet_get_icmp_payload(const struct dp_packet *b) +{ + return OVS_LIKELY(dp_packet_l4_size(b) >= ICMP_HEADER_LEN) + ? (const char *)dp_packet_l4(b) + ICMP_HEADER_LEN : NULL; +} + +static inline const void * +dp_packet_get_nd_payload(const struct dp_packet *b) +{ + return OVS_LIKELY(dp_packet_l4_size(b) >= ND_MSG_LEN) + ? (const char *)dp_packet_l4(b) + ND_MSG_LEN : NULL; +} + +#ifdef DPDK_NETDEV +static inline uint64_t * +dp_packet_ol_flags_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint64_t *, &b->mbuf.ol_flags); +} + +static inline uint32_t * +dp_packet_rss_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->mbuf.hash.rss); +} + +static inline uint32_t * +dp_packet_flow_mark_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->mbuf.hash.fdir.hi); +} + +#else +static inline uint32_t * +dp_packet_ol_flags_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->ol_flags); +} + +static inline uint32_t * +dp_packet_rss_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->rss_hash); +} + +static inline uint32_t * +dp_packet_flow_mark_ptr(const struct dp_packet *b) +{ + return CONST_CAST(uint32_t *, &b->flow_mark); +} +#endif + +#ifdef DPDK_NETDEV +BUILD_ASSERT_DECL(offsetof(struct dp_packet, mbuf) == 0); + +static inline void +dp_packet_init_specific(struct dp_packet *p) +{ + /* This initialization is needed for packets that do not come from DPDK + * interfaces, when vswitchd is built with --with-dpdk. */ + p->mbuf.ol_flags = p->mbuf.tx_offload = p->mbuf.packet_type = 0; + p->mbuf.nb_segs = 1; + p->mbuf.next = NULL; +} + +static inline void * +dp_packet_base(const struct dp_packet *b) +{ + return b->mbuf.buf_addr; +} + +static inline void +dp_packet_set_base(struct dp_packet *b, void *d) +{ + b->mbuf.buf_addr = d; +} + +static inline uint32_t +dp_packet_size(const struct dp_packet *b) +{ + return b->mbuf.pkt_len; +} + +static inline void +dp_packet_set_size(struct dp_packet *b, uint32_t v) +{ + /* netdev-dpdk does not currently support segmentation; consequently, for + * all intents and purposes, 'data_len' (16 bit) and 'pkt_len' (32 bit) may + * be used interchangably. + * + * On the datapath, it is expected that the size of packets + * (and thus 'v') will always be <= UINT16_MAX; this means that there is no + * loss of accuracy in assigning 'v' to 'data_len'. + */ + b->mbuf.data_len = (uint16_t)v; /* Current seg length. */ + b->mbuf.pkt_len = v; /* Total length of all segments linked to + * this segment. */ +} + +static inline uint16_t +__packet_data(const struct dp_packet *b) +{ + return b->mbuf.data_off; +} + +static inline void +__packet_set_data(struct dp_packet *b, uint16_t v) +{ + b->mbuf.data_off = v; +} + +static inline uint16_t +dp_packet_get_allocated(const struct dp_packet *b) +{ + return b->mbuf.buf_len; +} + +static inline void +dp_packet_set_allocated(struct dp_packet *b, uint16_t s) +{ + b->mbuf.buf_len = s; +} + +#else /* DPDK_NETDEV */ + +static inline void +dp_packet_init_specific(struct dp_packet *p OVS_UNUSED) +{ + /* There are no implementation-specific fields for initialization. */ +} + +static inline void * +dp_packet_base(const struct dp_packet *b) +{ + return b->base_; +} + +static inline void +dp_packet_set_base(struct dp_packet *b, void *d) +{ + b->base_ = d; +} + +static inline uint32_t +dp_packet_size(const struct dp_packet *b) +{ + return b->size_; +} + +static inline void +dp_packet_set_size(struct dp_packet *b, uint32_t v) +{ + b->size_ = v; +} + +static inline uint16_t +__packet_data(const struct dp_packet *b) +{ + return b->data_ofs; +} + +static inline void +__packet_set_data(struct dp_packet *b, uint16_t v) +{ + b->data_ofs = v; +} + +static inline uint16_t +dp_packet_get_allocated(const struct dp_packet *b) +{ + return b->allocated_; +} + +static inline void +dp_packet_set_allocated(struct dp_packet *b, uint16_t s) +{ + b->allocated_ = s; +} + +#endif /* DPDK_NETDEV */ + +static inline void +dp_packet_reset_cutlen(struct dp_packet *b) +{ + b->cutlen = 0; +} + +static inline uint32_t +dp_packet_set_cutlen(struct dp_packet *b, uint32_t max_len) +{ + if (max_len < ETH_HEADER_LEN) { + max_len = ETH_HEADER_LEN; + } + + if (max_len >= dp_packet_size(b)) { + b->cutlen = 0; + } else { + b->cutlen = dp_packet_size(b) - max_len; + } + return b->cutlen; +} + +static inline uint32_t +dp_packet_get_cutlen(const struct dp_packet *b) +{ + /* Always in valid range if user uses dp_packet_set_cutlen. */ + return b->cutlen; +} + +static inline uint32_t +dp_packet_get_send_len(const struct dp_packet *b) +{ + return dp_packet_size(b) - dp_packet_get_cutlen(b); +} + +static inline void * +dp_packet_data(const struct dp_packet *b) +{ + return __packet_data(b) != UINT16_MAX + ? (char *) dp_packet_base(b) + __packet_data(b) : NULL; +} + +static inline void +dp_packet_set_data(struct dp_packet *b, void *data) +{ + if (data) { + __packet_set_data(b, (char *) data - (char *) dp_packet_base(b)); + } else { + __packet_set_data(b, UINT16_MAX); + } +} + +static inline void +dp_packet_reset_packet(struct dp_packet *b, int off) +{ + dp_packet_set_size(b, dp_packet_size(b) - off); + dp_packet_set_data(b, ((unsigned char *) dp_packet_data(b) + off)); + dp_packet_reset_offsets(b); +} + +enum { NETDEV_MAX_BURST = 32 }; /* Maximum number packets in a batch. */ + +struct dp_packet_batch { + size_t count; + bool trunc; /* true if the batch needs truncate. */ + struct dp_packet *packets[NETDEV_MAX_BURST]; +}; + +static inline void +dp_packet_batch_init(struct dp_packet_batch *batch) +{ + batch->count = 0; + batch->trunc = false; +} + +static inline void +dp_packet_batch_add__(struct dp_packet_batch *batch, + struct dp_packet *packet, size_t limit) +{ + if (batch->count < limit) { + batch->packets[batch->count++] = packet; + } else { + dp_packet_delete(packet); + } +} + +/* When the batch is full, 'packet' will be dropped and freed. */ +static inline void +dp_packet_batch_add(struct dp_packet_batch *batch, struct dp_packet *packet) +{ + dp_packet_batch_add__(batch, packet, NETDEV_MAX_BURST); +} + +static inline size_t +dp_packet_batch_size(const struct dp_packet_batch *batch) +{ + return batch->count; +} + +/* Clear 'batch' for refill. Use dp_packet_batch_refill() to add + * packets back into the 'batch'. */ +static inline void +dp_packet_batch_refill_init(struct dp_packet_batch *batch) +{ + batch->count = 0; +}; + +static inline void +dp_packet_batch_refill(struct dp_packet_batch *batch, + struct dp_packet *packet, size_t idx) +{ + dp_packet_batch_add__(batch, packet, MIN(NETDEV_MAX_BURST, idx + 1)); +} + +static inline void +dp_packet_batch_init_packet(struct dp_packet_batch *batch, struct dp_packet *p) +{ + dp_packet_batch_init(batch); + batch->count = 1; + batch->packets[0] = p; +} + +static inline bool +dp_packet_batch_is_empty(const struct dp_packet_batch *batch) +{ + return !dp_packet_batch_size(batch); +} + +static inline bool +dp_packet_batch_is_full(const struct dp_packet_batch *batch) +{ + return dp_packet_batch_size(batch) == NETDEV_MAX_BURST; +} + +#define DP_PACKET_BATCH_FOR_EACH(IDX, PACKET, BATCH) \ + for (size_t IDX = 0; IDX < dp_packet_batch_size(BATCH); IDX++) \ + if (PACKET = BATCH->packets[IDX], true) + +/* Use this macro for cases where some packets in the 'BATCH' may be + * dropped after going through each packet in the 'BATCH'. + * + * For packets to stay in the 'BATCH', they need to be refilled back + * into the 'BATCH' by calling dp_packet_batch_refill(). Caller owns + * the packets that are not refilled. + * + * Caller needs to supply 'SIZE', that stores the current number of + * packets in 'BATCH'. It is best to declare this variable with + * the 'const' modifier since it should not be modified by + * the iterator. */ +#define DP_PACKET_BATCH_REFILL_FOR_EACH(IDX, SIZE, PACKET, BATCH) \ + for (dp_packet_batch_refill_init(BATCH), IDX=0; IDX < SIZE; IDX++) \ + if (PACKET = BATCH->packets[IDX], true) + +static inline void +dp_packet_batch_clone(struct dp_packet_batch *dst, + struct dp_packet_batch *src) +{ + struct dp_packet *packet; + + dp_packet_batch_init(dst); + DP_PACKET_BATCH_FOR_EACH (i, packet, src) { + if (i + 1 < dp_packet_batch_size(src)) { + OVS_PREFETCH(src->packets[i + 1]); + } + + uint32_t headroom = dp_packet_headroom(packet); + struct dp_packet *pkt_clone; + + pkt_clone = dp_packet_clone_with_headroom(packet, headroom); + dp_packet_batch_add(dst, pkt_clone); + } + dst->trunc = src->trunc; +} + +static inline void +dp_packet_delete_batch(struct dp_packet_batch *batch, bool should_steal) +{ + if (should_steal) { + struct dp_packet *packet; + + DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { + dp_packet_delete(packet); + } + dp_packet_batch_init(batch); + } +} + +static inline void +dp_packet_batch_init_packet_fields(struct dp_packet_batch *batch) +{ + struct dp_packet *packet; + + DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { + dp_packet_reset_cutlen(packet); + packet->packet_type = htonl(PT_ETH); + } +} + +static inline void +dp_packet_batch_apply_cutlen(struct dp_packet_batch *batch) +{ + if (batch->trunc) { + struct dp_packet *packet; + + DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { + dp_packet_set_size(packet, dp_packet_get_send_len(packet)); + dp_packet_reset_cutlen(packet); + } + batch->trunc = false; + } +} + +static inline void +dp_packet_batch_reset_cutlen(struct dp_packet_batch *batch) +{ + if (batch->trunc) { + struct dp_packet *packet; + + DP_PACKET_BATCH_FOR_EACH (i, packet, batch) { + dp_packet_reset_cutlen(packet); + } + batch->trunc = false; + } +} + +/* Returns the RSS hash of the packet 'p'. Note that the returned value is + * correct only if 'dp_packet_rss_valid(p)' returns 'true'. */ +static inline uint32_t +dp_packet_get_rss_hash(const struct dp_packet *p) +{ + return *dp_packet_rss_ptr(p); +} + +static inline void +dp_packet_set_rss_hash(struct dp_packet *p, uint32_t hash) +{ + *dp_packet_rss_ptr(p) = hash; + *dp_packet_ol_flags_ptr(p) |= DP_PACKET_OL_RSS_HASH; +} + +static inline bool +dp_packet_rss_valid(const struct dp_packet *p) +{ + return *dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RSS_HASH; +} + +static inline void +dp_packet_reset_offload(struct dp_packet *p) +{ + *dp_packet_ol_flags_ptr(p) &= ~DP_PACKET_OL_SUPPORTED_MASK; +} + +static inline bool +dp_packet_has_flow_mark(const struct dp_packet *p, uint32_t *mark) +{ + if (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_FLOW_MARK) { + *mark = *dp_packet_flow_mark_ptr(p); + return true; + } + + return false; +} + +static inline void +dp_packet_set_flow_mark(struct dp_packet *p, uint32_t mark) +{ + *dp_packet_flow_mark_ptr(p) = mark; + *dp_packet_ol_flags_ptr(p) |= DP_PACKET_OL_FLOW_MARK; +} + +/* Returns the L4 cksum offload bitmask. */ +static inline uint64_t +dp_packet_hwol_l4_mask(const struct dp_packet *b) +{ + return *dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK; +} + +/* Return true if the packet 'b' requested L4 checksum offload. */ +static inline bool +dp_packet_hwol_tx_l4_checksum(const struct dp_packet *b) +{ + return !!dp_packet_hwol_l4_mask(b); +} + +/* Returns 'true' if packet 'b' is marked for TCP segmentation offloading. */ +static inline bool +dp_packet_hwol_is_tso(const struct dp_packet *b) +{ + return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_TCP_SEG); +} + +/* Returns 'true' if packet 'b' is marked for IPv4 checksum offloading. */ +static inline bool +dp_packet_hwol_is_ipv4(const struct dp_packet *b) +{ + return !!(*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_IPV4); +} + +/* Returns 'true' if packet 'b' is marked for TCP checksum offloading. */ +static inline bool +dp_packet_hwol_l4_is_tcp(const struct dp_packet *b) +{ + return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == + DP_PACKET_OL_TX_TCP_CKSUM; +} + +/* Returns 'true' if packet 'b' is marked for UDP checksum offloading. */ +static inline bool +dp_packet_hwol_l4_is_udp(struct dp_packet *b) +{ + return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == + DP_PACKET_OL_TX_UDP_CKSUM; +} + +/* Returns 'true' if packet 'b' is marked for SCTP checksum offloading. */ +static inline bool +dp_packet_hwol_l4_is_sctp(struct dp_packet *b) +{ + return (*dp_packet_ol_flags_ptr(b) & DP_PACKET_OL_TX_L4_MASK) == + DP_PACKET_OL_TX_SCTP_CKSUM; +} + +/* Mark packet 'b' for IPv4 checksum offloading. */ +static inline void +dp_packet_hwol_set_tx_ipv4(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_IPV4; +} + +/* Mark packet 'b' for IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_tx_ipv6(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_IPV6; +} + +/* Mark packet 'b' for TCP checksum offloading. It implies that either + * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_csum_tcp(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TCP_CKSUM; +} + +/* Mark packet 'b' for UDP checksum offloading. It implies that either + * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_csum_udp(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_UDP_CKSUM; +} + +/* Mark packet 'b' for SCTP checksum offloading. It implies that either + * the packet 'b' is marked for IPv4 or IPv6 checksum offloading. */ +static inline void +dp_packet_hwol_set_csum_sctp(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_SCTP_CKSUM; +} + +/* Mark packet 'b' for TCP segmentation offloading. It implies that + * either the packet 'b' is marked for IPv4 or IPv6 checksum offloading + * and also for TCP checksum offloading. */ +static inline void +dp_packet_hwol_set_tcp_seg(struct dp_packet *b) +{ + *dp_packet_ol_flags_ptr(b) |= DP_PACKET_OL_TX_TCP_SEG; +} + +static inline bool +dp_packet_ip_checksum_valid(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_IP_CKSUM_MASK) == + DP_PACKET_OL_RX_IP_CKSUM_GOOD; +} + +static inline bool +dp_packet_ip_checksum_bad(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_IP_CKSUM_MASK) == + DP_PACKET_OL_RX_IP_CKSUM_BAD; +} + +static inline bool +dp_packet_l4_checksum_valid(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_L4_CKSUM_MASK) == + DP_PACKET_OL_RX_L4_CKSUM_GOOD; +} + +static inline bool +dp_packet_l4_checksum_bad(const struct dp_packet *p) +{ + return (*dp_packet_ol_flags_ptr(p) & DP_PACKET_OL_RX_L4_CKSUM_MASK) == + DP_PACKET_OL_RX_L4_CKSUM_BAD; +} + +#ifdef __cplusplus +} +#endif + +#endif /* dp-packet.h */ Index: openvswitch-2.17.2/lib/flow.h =================================================================== --- openvswitch-2.17.2.orig/lib/flow.h +++ /dev/null @@ -1,1215 +0,0 @@ -/* - * 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. - */ -#ifndef FLOW_H -#define FLOW_H 1 - -#include -#include -#include -#include -#include -#include -#include "bitmap.h" -#include "byte-order.h" -#include "openvswitch/compiler.h" -#include "openflow/nicira-ext.h" -#include "openflow/openflow.h" -#include "openvswitch/flow.h" -#include "packets.h" -#include "hash.h" -#include "util.h" - -struct dpif_flow_stats; -struct dpif_flow_attrs; -struct ds; -struct flow_wildcards; -struct minimask; -struct dp_packet; -struct ofputil_port_map; -struct pkt_metadata; -struct match; - -/* Some flow fields are mutually exclusive or only appear within the flow - * pipeline. IPv6 headers are bigger than IPv4 and MPLS, and IPv6 ND packets - * are bigger than TCP,UDP and IGMP packets. */ -#define FLOW_MAX_PACKET_U64S (FLOW_U64S \ - /* Unused in datapath */ - FLOW_U64_SIZE(regs) \ - - FLOW_U64_SIZE(metadata) \ - /* L2.5/3 */ - FLOW_U64_SIZE(nw_src) /* incl. nw_dst */ \ - - FLOW_U64_SIZE(mpls_lse) \ - /* L4 */ - FLOW_U64_SIZE(tp_src) \ - ) - -extern const uint8_t flow_segment_u64s[]; - -/* Configured maximum VLAN headers. */ -extern int flow_vlan_limit; - -#define FLOW_U64_OFFSET(FIELD) \ - (offsetof(struct flow, FIELD) / sizeof(uint64_t)) -#define FLOW_U64_OFFREM(FIELD) \ - (offsetof(struct flow, FIELD) % sizeof(uint64_t)) - -/* Number of 64-bit units spanned by a 'FIELD'. */ -#define FLOW_U64_SIZE(FIELD) \ - DIV_ROUND_UP(FLOW_U64_OFFREM(FIELD) + MEMBER_SIZEOF(struct flow, FIELD), \ - sizeof(uint64_t)) - -void flow_extract(struct dp_packet *, struct flow *); - -void flow_zero_wildcards(struct flow *, const struct flow_wildcards *); -void flow_unwildcard_tp_ports(const struct flow *, struct flow_wildcards *); -void flow_get_metadata(const struct flow *, struct match *flow_metadata); -struct netdev *flow_get_tunnel_netdev(struct flow_tnl *tunnel); - -const char *ct_state_to_string(uint32_t state); -uint32_t ct_state_from_string(const char *); -bool parse_ct_state(const char *state_str, uint32_t default_state, - uint32_t *ct_state, struct ds *); -bool validate_ct_state(uint32_t state, struct ds *); -void flow_clear_conntrack(struct flow *); - -char *flow_to_string(const struct flow *, const struct ofputil_port_map *); -void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t), - uint32_t flags, char del); -void format_flags_masked(struct ds *ds, const char *name, - const char *(*bit_to_string)(uint32_t), - uint32_t flags, uint32_t mask, uint32_t max_mask); -void format_packet_type_masked(struct ds *, ovs_be32 value, ovs_be32 mask); -int parse_flags(const char *s, const char *(*bit_to_string)(uint32_t), - char end, const char *field_name, char **res_string, - uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask); - -void flow_format(struct ds *, const struct flow *, - const struct ofputil_port_map *); -void flow_print(FILE *, const struct flow *, const struct ofputil_port_map *); -static inline int flow_compare_3way(const struct flow *, const struct flow *); -static inline bool flow_equal(const struct flow *, const struct flow *); -static inline size_t flow_hash(const struct flow *, uint32_t basis); - -void flow_set_dl_vlan(struct flow *, ovs_be16 vid, int id); -void flow_fix_vlan_tpid(struct flow *); -void flow_set_vlan_vid(struct flow *, ovs_be16 vid); -void flow_set_vlan_pcp(struct flow *, uint8_t pcp, int id); - -void flow_limit_vlans(int vlan_limit); -int flow_count_vlan_headers(const struct flow *); -void flow_skip_common_vlan_headers(const struct flow *a, int *p_an, - const struct flow *b, int *p_bn); -void flow_pop_vlan(struct flow*, struct flow_wildcards*); -void flow_push_vlan_uninit(struct flow*, struct flow_wildcards*); - -int flow_count_mpls_labels(const struct flow *, struct flow_wildcards *); -int flow_count_common_mpls_labels(const struct flow *a, int an, - const struct flow *b, int bn, - struct flow_wildcards *wc); -void flow_push_mpls(struct flow *, int n, ovs_be16 mpls_eth_type, - struct flow_wildcards *, bool clear_flow_L3); -bool flow_pop_mpls(struct flow *, int n, ovs_be16 eth_type, - struct flow_wildcards *); -void flow_set_mpls_label(struct flow *, int idx, ovs_be32 label); -void flow_set_mpls_ttl(struct flow *, int idx, uint8_t ttl); -void flow_set_mpls_tc(struct flow *, int idx, uint8_t tc); -void flow_set_mpls_bos(struct flow *, int idx, uint8_t stack); -void flow_set_mpls_lse(struct flow *, int idx, ovs_be32 lse); - -void flow_compose(struct dp_packet *, const struct flow *, - const void *l7, size_t l7_len); -void packet_expand(struct dp_packet *, const struct flow *, size_t size); - -bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, - uint8_t *nw_frag, - const struct ovs_16aligned_ip6_frag **frag_hdr); -bool parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key); -uint16_t parse_tcp_flags(struct dp_packet *packet, ovs_be16 *dl_type_p, - uint8_t *nw_frag_p, ovs_be16 *first_vlan_tci_p); - -static inline uint64_t -flow_get_xreg(const struct flow *flow, int idx) -{ - return ((uint64_t) flow->regs[idx * 2] << 32) | flow->regs[idx * 2 + 1]; -} - -static inline void -flow_set_xreg(struct flow *flow, int idx, uint64_t value) -{ - flow->regs[idx * 2] = value >> 32; - flow->regs[idx * 2 + 1] = value; -} - -static inline ovs_u128 -flow_get_xxreg(const struct flow *flow, int idx) -{ - ovs_u128 value; - - value.u64.hi = (uint64_t) flow->regs[idx * 4] << 32; - value.u64.hi |= flow->regs[idx * 4 + 1]; - value.u64.lo = (uint64_t) flow->regs[idx * 4 + 2] << 32; - value.u64.lo |= flow->regs[idx * 4 + 3]; - - return value; -} - -static inline void -flow_set_xxreg(struct flow *flow, int idx, ovs_u128 value) -{ - flow->regs[idx * 4] = value.u64.hi >> 32; - flow->regs[idx * 4 + 1] = value.u64.hi; - flow->regs[idx * 4 + 2] = value.u64.lo >> 32; - flow->regs[idx * 4 + 3] = value.u64.lo; -} - -static inline int -flow_compare_3way(const struct flow *a, const struct flow *b) -{ - return memcmp(a, b, sizeof *a); -} - -static inline bool -flow_equal(const struct flow *a, const struct flow *b) -{ - return !flow_compare_3way(a, b); -} - -static inline size_t -flow_hash(const struct flow *flow, uint32_t basis) -{ - return hash_bytes64((const uint64_t *)flow, sizeof *flow, basis); -} - -static inline uint16_t -ofp_to_u16(ofp_port_t ofp_port) -{ - return (OVS_FORCE uint16_t) ofp_port; -} - -static inline uint32_t -odp_to_u32(odp_port_t odp_port) -{ - return (OVS_FORCE uint32_t) odp_port; -} - -static inline uint32_t -ofp11_to_u32(ofp11_port_t ofp11_port) -{ - return (OVS_FORCE uint32_t) ofp11_port; -} - -static inline ofp_port_t -u16_to_ofp(uint16_t port) -{ - return OFP_PORT_C(port); -} - -static inline odp_port_t -u32_to_odp(uint32_t port) -{ - return ODP_PORT_C(port); -} - -static inline ofp11_port_t -u32_to_ofp11(uint32_t port) -{ - return OFP11_PORT_C(port); -} - -static inline uint32_t -hash_ofp_port(ofp_port_t ofp_port) -{ - return hash_int(ofp_to_u16(ofp_port), 0); -} - -static inline uint32_t -hash_odp_port(odp_port_t odp_port) -{ - return hash_int(odp_to_u32(odp_port), 0); -} - -uint32_t flow_hash_5tuple(const struct flow *flow, uint32_t basis); -uint32_t flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis); -uint32_t flow_hash_symmetric_l2(const struct flow *flow, uint32_t basis); -uint32_t flow_hash_symmetric_l3l4(const struct flow *flow, uint32_t basis, - bool inc_udp_ports ); -uint32_t flow_hash_symmetric_l3(const struct flow *flow, uint32_t basis); - -/* Initialize a flow with random fields that matter for nx_hash_fields. */ -void flow_random_hash_fields(struct flow *); -void flow_mask_hash_fields(const struct flow *, struct flow_wildcards *, - enum nx_hash_fields); -uint32_t flow_hash_fields(const struct flow *, enum nx_hash_fields, - uint16_t basis); -const char *flow_hash_fields_to_str(enum nx_hash_fields); -bool flow_hash_fields_valid(enum nx_hash_fields); - -uint32_t flow_hash_in_wildcards(const struct flow *, - const struct flow_wildcards *, - uint32_t basis); - -bool flow_equal_except(const struct flow *a, const struct flow *b, - const struct flow_wildcards *); - -/* Bitmap for flow values. For each 1-bit the corresponding flow value is - * explicitly specified, other values are zeroes. - * - * map_t must be wide enough to hold any member of struct flow. */ -typedef unsigned long long map_t; -#define MAP_T_BITS (sizeof(map_t) * CHAR_BIT) -#define MAP_1 (map_t)1 -#define MAP_MAX TYPE_MAXIMUM(map_t) - -#define MAP_IS_SET(MAP, IDX) ((MAP) & (MAP_1 << (IDX))) - -/* Iterate through the indices of all 1-bits in 'MAP'. */ -#define MAP_FOR_EACH_INDEX(IDX, MAP) \ - ULLONG_FOR_EACH_1(IDX, MAP) - -#define FLOWMAP_UNITS DIV_ROUND_UP(FLOW_U64S, MAP_T_BITS) - -struct flowmap { - map_t bits[FLOWMAP_UNITS]; -}; - -#define FLOWMAP_EMPTY_INITIALIZER { { 0 } } - -static inline void flowmap_init(struct flowmap *); -static inline bool flowmap_equal(struct flowmap, struct flowmap); -static inline bool flowmap_is_set(const struct flowmap *, size_t idx); -static inline bool flowmap_are_set(const struct flowmap *, size_t idx, - unsigned int n_bits); -static inline void flowmap_set(struct flowmap *, size_t idx, - unsigned int n_bits); -static inline void flowmap_clear(struct flowmap *, size_t idx, - unsigned int n_bits); -static inline struct flowmap flowmap_or(struct flowmap, struct flowmap); -static inline struct flowmap flowmap_and(struct flowmap, struct flowmap); -static inline bool flowmap_is_empty(struct flowmap); -static inline unsigned int flowmap_n_1bits(struct flowmap); - -#define FLOWMAP_HAS_FIELD(FM, FIELD) \ - flowmap_are_set(FM, FLOW_U64_OFFSET(FIELD), FLOW_U64_SIZE(FIELD)) - -#define FLOWMAP_SET(FM, FIELD) \ - flowmap_set(FM, FLOW_U64_OFFSET(FIELD), FLOW_U64_SIZE(FIELD)) - -#define FLOWMAP_SET__(FM, FIELD, SIZE) \ - flowmap_set(FM, FLOW_U64_OFFSET(FIELD), \ - DIV_ROUND_UP(SIZE, sizeof(uint64_t))) - -/* XXX: Only works for full 64-bit units. */ -#define FLOWMAP_CLEAR(FM, FIELD) \ - BUILD_ASSERT_DECL(FLOW_U64_OFFREM(FIELD) == 0); \ - BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->FIELD) % sizeof(uint64_t) == 0); \ - flowmap_clear(FM, FLOW_U64_OFFSET(FIELD), FLOW_U64_SIZE(FIELD)) - -/* Iterate through all units in 'FMAP'. */ -#define FLOWMAP_FOR_EACH_UNIT(UNIT) \ - for ((UNIT) = 0; (UNIT) < FLOWMAP_UNITS; (UNIT)++) - -/* Iterate through all map units in 'FMAP'. */ -#define FLOWMAP_FOR_EACH_MAP(MAP, FLOWMAP) \ - for (size_t unit__ = 0; \ - unit__ < FLOWMAP_UNITS && ((MAP) = (FLOWMAP).bits[unit__], true); \ - unit__++) - -struct flowmap_aux; -static inline bool flowmap_next_index(struct flowmap_aux *, size_t *idx); - -#define FLOWMAP_AUX_INITIALIZER(FLOWMAP) { .unit = 0, .map = (FLOWMAP) } - -/* Iterate through all struct flow u64 indices specified by 'MAP'. This is a - * slower but easier version of the FLOWMAP_FOR_EACH_MAP() & - * MAP_FOR_EACH_INDEX() combination. */ -#define FLOWMAP_FOR_EACH_INDEX(IDX, MAP) \ - for (struct flowmap_aux aux__ = FLOWMAP_AUX_INITIALIZER(MAP); \ - flowmap_next_index(&aux__, &(IDX));) - -/* Flowmap inline implementations. */ -static inline void -flowmap_init(struct flowmap *fm) -{ - memset(fm, 0, sizeof *fm); -} - -static inline bool -flowmap_equal(struct flowmap a, struct flowmap b) -{ - return !memcmp(&a, &b, sizeof a); -} - -static inline bool -flowmap_is_set(const struct flowmap *fm, size_t idx) -{ - return (fm->bits[idx / MAP_T_BITS] & (MAP_1 << (idx % MAP_T_BITS))) != 0; -} - -/* Returns 'true' if any of the 'n_bits' bits starting at 'idx' are set in - * 'fm'. 'n_bits' can be at most MAP_T_BITS. */ -static inline bool -flowmap_are_set(const struct flowmap *fm, size_t idx, unsigned int n_bits) -{ - map_t n_bits_mask = (MAP_1 << n_bits) - 1; - size_t unit = idx / MAP_T_BITS; - - idx %= MAP_T_BITS; - - if (fm->bits[unit] & (n_bits_mask << idx)) { - return true; - } - /* The seemingly unnecessary bounds check on 'unit' is a workaround for a - * false-positive array out of bounds error by GCC 4.9. */ - if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { - /* Check the remaining bits from the next unit. */ - return fm->bits[unit + 1] & (n_bits_mask >> (MAP_T_BITS - idx)); - } - return false; -} - -/* Set the 'n_bits' consecutive bits in 'fm', starting at bit 'idx'. - * 'n_bits' can be at most MAP_T_BITS. */ -static inline void -flowmap_set(struct flowmap *fm, size_t idx, unsigned int n_bits) -{ - map_t n_bits_mask = (MAP_1 << n_bits) - 1; - size_t unit = idx / MAP_T_BITS; - - idx %= MAP_T_BITS; - - fm->bits[unit] |= n_bits_mask << idx; - /* The seemingly unnecessary bounds check on 'unit' is a workaround for a - * false-positive array out of bounds error by GCC 4.9. */ - if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { - /* 'MAP_T_BITS - idx' bits were set on 'unit', set the remaining - * bits from the next unit. */ - fm->bits[unit + 1] |= n_bits_mask >> (MAP_T_BITS - idx); - } -} - -/* Clears the 'n_bits' consecutive bits in 'fm', starting at bit 'idx'. - * 'n_bits' can be at most MAP_T_BITS. */ -static inline void -flowmap_clear(struct flowmap *fm, size_t idx, unsigned int n_bits) -{ - map_t n_bits_mask = (MAP_1 << n_bits) - 1; - size_t unit = idx / MAP_T_BITS; - - idx %= MAP_T_BITS; - - fm->bits[unit] &= ~(n_bits_mask << idx); - /* The seemingly unnecessary bounds check on 'unit' is a workaround for a - * false-positive array out of bounds error by GCC 4.9. */ - if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { - /* 'MAP_T_BITS - idx' bits were cleared on 'unit', clear the - * remaining bits from the next unit. */ - fm->bits[unit + 1] &= ~(n_bits_mask >> (MAP_T_BITS - idx)); - } -} - -/* OR the bits in the flowmaps. */ -static inline struct flowmap -flowmap_or(struct flowmap a, struct flowmap b) -{ - struct flowmap map; - size_t unit; - - FLOWMAP_FOR_EACH_UNIT (unit) { - map.bits[unit] = a.bits[unit] | b.bits[unit]; - } - return map; -} - -/* AND the bits in the flowmaps. */ -static inline struct flowmap -flowmap_and(struct flowmap a, struct flowmap b) -{ - struct flowmap map; - size_t unit; - - FLOWMAP_FOR_EACH_UNIT (unit) { - map.bits[unit] = a.bits[unit] & b.bits[unit]; - } - return map; -} - -static inline bool -flowmap_is_empty(struct flowmap fm) -{ - map_t map; - - FLOWMAP_FOR_EACH_MAP (map, fm) { - if (map) { - return false; - } - } - return true; -} - -static inline unsigned int -flowmap_n_1bits(struct flowmap fm) -{ - unsigned int n_1bits = 0; - size_t unit; - - FLOWMAP_FOR_EACH_UNIT (unit) { - n_1bits += count_1bits(fm.bits[unit]); - } - return n_1bits; -} - -struct flowmap_aux { - size_t unit; - struct flowmap map; -}; - -static inline bool -flowmap_next_index(struct flowmap_aux *aux, size_t *idx) -{ - for (;;) { - map_t *map = &aux->map.bits[aux->unit]; - if (*map) { - *idx = aux->unit * MAP_T_BITS + raw_ctz(*map); - *map = zero_rightmost_1bit(*map); - return true; - } - if (++aux->unit >= FLOWMAP_UNITS) { - return false; - } - } -} - - -/* Compressed flow. */ - -/* A sparse representation of a "struct flow". - * - * A "struct flow" is fairly large and tends to be mostly zeros. Sparse - * representation has two advantages. First, it saves memory and, more - * importantly, minimizes the number of accessed cache lines. Second, it saves - * time when the goal is to iterate over only the nonzero parts of the struct. - * - * The map member hold one bit for each uint64_t in a "struct flow". Each - * 0-bit indicates that the corresponding uint64_t is zero, each 1-bit that it - * *may* be nonzero (see below how this applies to minimasks). - * - * The values indicated by 'map' always follow the miniflow in memory. The - * user of the miniflow is responsible for always having enough storage after - * the struct miniflow corresponding to the number of 1-bits in maps. - * - * Elements in values array are allowed to be zero. This is useful for "struct - * minimatch", for which ensuring that the miniflow and minimask members have - * same maps allows optimization. This allowance applies only to a miniflow - * that is not a mask. That is, a minimask may NOT have zero elements in its - * values. - * - * A miniflow is always dynamically allocated so that the maps are followed by - * at least as many elements as there are 1-bits in maps. */ -struct miniflow { - struct flowmap map; - /* Followed by: - * uint64_t values[n]; - * where 'n' is miniflow_n_values(miniflow). */ -}; -BUILD_ASSERT_DECL(sizeof(struct miniflow) % sizeof(uint64_t) == 0); - -#define MINIFLOW_VALUES_SIZE(COUNT) ((COUNT) * sizeof(uint64_t)) - -static inline uint64_t *miniflow_values(struct miniflow *mf) -{ - return (uint64_t *)(mf + 1); -} - -static inline const uint64_t *miniflow_get_values(const struct miniflow *mf) -{ - return (const uint64_t *)(mf + 1); -} - -struct pkt_metadata; - -/* The 'dst' must follow with buffer space for FLOW_U64S 64-bit units. - * 'dst->map' is ignored on input and set on output to indicate which fields - * were extracted. */ -void miniflow_extract(struct dp_packet *packet, struct miniflow *dst); -void miniflow_map_init(struct miniflow *, const struct flow *); -void flow_wc_map(const struct flow *, struct flowmap *); -size_t miniflow_alloc(struct miniflow *dsts[], size_t n, - const struct miniflow *src); -void miniflow_init(struct miniflow *, const struct flow *); -void miniflow_clone(struct miniflow *, const struct miniflow *, - size_t n_values); -struct miniflow * miniflow_create(const struct flow *); - -void miniflow_expand(const struct miniflow *, struct flow *); - -static inline uint64_t flow_u64_value(const struct flow *flow, size_t index) -{ - return ((uint64_t *)flow)[index]; -} - -static inline uint64_t *flow_u64_lvalue(struct flow *flow, size_t index) -{ - return &((uint64_t *)flow)[index]; -} - -static inline size_t -miniflow_n_values(const struct miniflow *flow) -{ - return flowmap_n_1bits(flow->map); -} - -struct flow_for_each_in_maps_aux { - const struct flow *flow; - struct flowmap_aux map_aux; -}; - -static inline bool -flow_values_get_next_in_maps(struct flow_for_each_in_maps_aux *aux, - uint64_t *value) -{ - size_t idx; - - if (flowmap_next_index(&aux->map_aux, &idx)) { - *value = flow_u64_value(aux->flow, idx); - return true; - } - return false; -} - -/* Iterate through all flow u64 values specified by 'MAPS'. */ -#define FLOW_FOR_EACH_IN_MAPS(VALUE, FLOW, MAPS) \ - for (struct flow_for_each_in_maps_aux aux__ \ - = { (FLOW), FLOWMAP_AUX_INITIALIZER(MAPS) }; \ - flow_values_get_next_in_maps(&aux__, &(VALUE));) - -struct mf_for_each_in_map_aux { - size_t unit; /* Current 64-bit unit of the flowmaps - being processed. */ - struct flowmap fmap; /* Remaining 1-bits corresponding to the - 64-bit words in 'values' */ - struct flowmap map; /* Remaining 1-bits corresponding to the - 64-bit words of interest. */ - const uint64_t *values; /* 64-bit words corresponding to the - 1-bits in 'fmap'. */ -}; - -/* Get the data from 'aux->values' corresponding to the next lowest 1-bit - * in 'aux->map', given that 'aux->values' points to an array of 64-bit - * words corresponding to the 1-bits in 'aux->fmap', starting from the - * rightmost 1-bit. - * - * Returns 'true' if the traversal is incomplete, 'false' otherwise. - * 'aux' is prepared for the next iteration after each call. - * - * This is used to traverse through, for example, the values in a miniflow - * representation of a flow key selected by non-zero 64-bit words in a - * corresponding subtable mask. */ -static inline bool -mf_get_next_in_map(struct mf_for_each_in_map_aux *aux, - uint64_t *value) -{ - map_t *map, *fmap; - map_t rm1bit; - - /* Skip empty map units. */ - while (OVS_UNLIKELY(!*(map = &aux->map.bits[aux->unit]))) { - /* Skip remaining data in the current unit before advancing - * to the next. */ - aux->values += count_1bits(aux->fmap.bits[aux->unit]); - if (++aux->unit == FLOWMAP_UNITS) { - return false; - } - } - - rm1bit = rightmost_1bit(*map); - *map -= rm1bit; - fmap = &aux->fmap.bits[aux->unit]; - - /* If the rightmost 1-bit found from the current unit in 'aux->map' - * ('rm1bit') is also present in 'aux->fmap', store the corresponding - * value from 'aux->values' to '*value', otherwise store 0. */ - if (OVS_LIKELY(*fmap & rm1bit)) { - /* Skip all 64-bit words in 'values' preceding the one corresponding - * to 'rm1bit'. */ - map_t trash = *fmap & (rm1bit - 1); - - /* Avoid resetting 'fmap' and calling count_1bits() when trash is - * zero. */ - if (trash) { - *fmap -= trash; - aux->values += count_1bits(trash); - } - - *value = *aux->values; - } else { - *value = 0; - } - return true; -} - -/* Iterate through miniflow u64 values specified by 'FLOWMAP'. */ -#define MINIFLOW_FOR_EACH_IN_FLOWMAP(VALUE, FLOW, FLOWMAP) \ - for (struct mf_for_each_in_map_aux aux__ = \ - { 0, (FLOW)->map, (FLOWMAP), miniflow_get_values(FLOW) }; \ - mf_get_next_in_map(&aux__, &(VALUE));) - -/* This can be used when it is known that 'idx' is set in 'map'. */ -static inline const uint64_t * -miniflow_values_get__(const uint64_t *values, map_t map, size_t idx) -{ - return values + count_1bits(map & ((MAP_1 << idx) - 1)); -} - -/* This can be used when it is known that 'u64_idx' is set in - * the map of 'mf'. */ -static inline const uint64_t * -miniflow_get__(const struct miniflow *mf, size_t idx) -{ - const uint64_t *values = miniflow_get_values(mf); - const map_t *map = mf->map.bits; - - while (idx >= MAP_T_BITS) { - idx -= MAP_T_BITS; - values += count_1bits(*map++); - } - return miniflow_values_get__(values, *map, idx); -} - -#define MINIFLOW_IN_MAP(MF, IDX) flowmap_is_set(&(MF)->map, IDX) - -/* Get the value of the struct flow 'FIELD' as up to 8 byte wide integer type - * 'TYPE' from miniflow 'MF'. */ -#define MINIFLOW_GET_TYPE(MF, TYPE, FIELD) \ - (BUILD_ASSERT(sizeof(TYPE) == sizeof(((struct flow *)0)->FIELD)), \ - BUILD_ASSERT_GCCONLY(__builtin_types_compatible_p(TYPE, typeof(((struct flow *)0)->FIELD))), \ - MINIFLOW_GET_TYPE__(MF, TYPE, FIELD)) - -/* Like MINIFLOW_GET_TYPE, but without checking that TYPE is the correct width - * for FIELD. (This is useful for deliberately reading adjacent fields in one - * go.) */ -#define MINIFLOW_GET_TYPE__(MF, TYPE, FIELD) \ - (MINIFLOW_IN_MAP(MF, FLOW_U64_OFFSET(FIELD)) \ - ? ((OVS_FORCE const TYPE *)miniflow_get__(MF, FLOW_U64_OFFSET(FIELD))) \ - [FLOW_U64_OFFREM(FIELD) / sizeof(TYPE)] \ - : 0) - -#define MINIFLOW_GET_U128(FLOW, FIELD) \ - (ovs_u128) { .u64 = { \ - (MINIFLOW_IN_MAP(FLOW, FLOW_U64_OFFSET(FIELD)) ? \ - *miniflow_get__(FLOW, FLOW_U64_OFFSET(FIELD)) : 0), \ - (MINIFLOW_IN_MAP(FLOW, FLOW_U64_OFFSET(FIELD) + 1) ? \ - *miniflow_get__(FLOW, FLOW_U64_OFFSET(FIELD) + 1) : 0) } } - -#define MINIFLOW_GET_U8(FLOW, FIELD) \ - MINIFLOW_GET_TYPE(FLOW, uint8_t, FIELD) -#define MINIFLOW_GET_U16(FLOW, FIELD) \ - MINIFLOW_GET_TYPE(FLOW, uint16_t, FIELD) -#define MINIFLOW_GET_BE16(FLOW, FIELD) \ - MINIFLOW_GET_TYPE(FLOW, ovs_be16, FIELD) -#define MINIFLOW_GET_U32(FLOW, FIELD) \ - MINIFLOW_GET_TYPE(FLOW, uint32_t, FIELD) -#define MINIFLOW_GET_BE32(FLOW, FIELD) \ - MINIFLOW_GET_TYPE(FLOW, ovs_be32, FIELD) -#define MINIFLOW_GET_U64(FLOW, FIELD) \ - MINIFLOW_GET_TYPE(FLOW, uint64_t, FIELD) -#define MINIFLOW_GET_BE64(FLOW, FIELD) \ - MINIFLOW_GET_TYPE(FLOW, ovs_be64, FIELD) - -static inline uint64_t miniflow_get(const struct miniflow *, - unsigned int u64_ofs); -static inline uint32_t miniflow_get_u32(const struct miniflow *, - unsigned int u32_ofs); -static inline ovs_be32 miniflow_get_be32(const struct miniflow *, - unsigned int be32_ofs); -static inline uint16_t miniflow_get_vid(const struct miniflow *, size_t); -static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *); -static inline ovs_be64 miniflow_get_metadata(const struct miniflow *); -static inline uint64_t miniflow_get_tun_metadata_present_map( - const struct miniflow *); -static inline uint32_t miniflow_get_recirc_id(const struct miniflow *); -static inline uint32_t miniflow_get_dp_hash(const struct miniflow *); -static inline ovs_be32 miniflow_get_ports(const struct miniflow *); - -bool miniflow_equal(const struct miniflow *a, const struct miniflow *b); -bool miniflow_equal_in_minimask(const struct miniflow *a, - const struct miniflow *b, - const struct minimask *); -bool miniflow_equal_flow_in_minimask(const struct miniflow *a, - const struct flow *b, - const struct minimask *); -uint32_t miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis); - - -/* Compressed flow wildcards. */ - -/* A sparse representation of a "struct flow_wildcards". - * - * See the large comment on struct miniflow for details. - * - * Note: While miniflow can have zero data for a 1-bit in the map, - * a minimask may not! We rely on this in the implementation. */ -struct minimask { - struct miniflow masks; -}; - -void minimask_init(struct minimask *, const struct flow_wildcards *); -struct minimask * minimask_create(const struct flow_wildcards *); -void minimask_combine(struct minimask *dst, - const struct minimask *a, const struct minimask *b, - uint64_t storage[FLOW_U64S]); - -void minimask_expand(const struct minimask *, struct flow_wildcards *); - -static inline uint32_t minimask_get_u32(const struct minimask *, - unsigned int u32_ofs); -static inline ovs_be32 minimask_get_be32(const struct minimask *, - unsigned int be32_ofs); -static inline uint16_t minimask_get_vid_mask(const struct minimask *, size_t); -static inline ovs_be64 minimask_get_metadata_mask(const struct minimask *); - -bool minimask_equal(const struct minimask *a, const struct minimask *b); -bool minimask_has_extra(const struct minimask *, const struct minimask *); - - -/* Returns true if 'mask' matches every packet, false if 'mask' fixes any bits - * or fields. */ -static inline bool -minimask_is_catchall(const struct minimask *mask) -{ - /* For every 1-bit in mask's map, the corresponding value is non-zero, - * so the only way the mask can not fix any bits or fields is for the - * map the be zero. */ - return flowmap_is_empty(mask->masks.map); -} - -/* Returns the uint64_t that would be at byte offset '8 * u64_ofs' if 'flow' - * were expanded into a "struct flow". */ -static inline uint64_t miniflow_get(const struct miniflow *flow, - unsigned int u64_ofs) -{ - return MINIFLOW_IN_MAP(flow, u64_ofs) ? *miniflow_get__(flow, u64_ofs) : 0; -} - -static inline uint32_t miniflow_get_u32(const struct miniflow *flow, - unsigned int u32_ofs) -{ - uint64_t value = miniflow_get(flow, u32_ofs / 2); - -#if WORDS_BIGENDIAN - return (u32_ofs & 1) ? value : value >> 32; -#else - return (u32_ofs & 1) ? value >> 32 : value; -#endif -} - -static inline ovs_be32 miniflow_get_be32(const struct miniflow *flow, - unsigned int be32_ofs) -{ - return (OVS_FORCE ovs_be32)miniflow_get_u32(flow, be32_ofs); -} - -/* Returns the VID within the vlan_tci member of the "struct flow" represented - * by 'flow'. */ -static inline uint16_t -miniflow_get_vid(const struct miniflow *flow, size_t n) -{ - if (n < FLOW_MAX_VLAN_HEADERS) { - union flow_vlan_hdr hdr = { - .qtag = MINIFLOW_GET_BE32(flow, vlans[n].qtag) - }; - return vlan_tci_to_vid(hdr.tci); - } - return 0; -} - -/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'mask' - * were expanded into a "struct flow_wildcards". */ -static inline uint32_t -minimask_get_u32(const struct minimask *mask, unsigned int u32_ofs) -{ - return miniflow_get_u32(&mask->masks, u32_ofs); -} - -static inline ovs_be32 -minimask_get_be32(const struct minimask *mask, unsigned int be32_ofs) -{ - return (OVS_FORCE ovs_be32)minimask_get_u32(mask, be32_ofs); -} - -/* Returns the VID mask within the vlan_tci member of the "struct - * flow_wildcards" represented by 'mask'. */ -static inline uint16_t -minimask_get_vid_mask(const struct minimask *mask, size_t n) -{ - return miniflow_get_vid(&mask->masks, n); -} - -/* Returns the value of the "tcp_flags" field in 'flow'. */ -static inline uint16_t -miniflow_get_tcp_flags(const struct miniflow *flow) -{ - return ntohs(MINIFLOW_GET_BE16(flow, tcp_flags)); -} - -/* Returns the value of the OpenFlow 1.1+ "metadata" field in 'flow'. */ -static inline ovs_be64 -miniflow_get_metadata(const struct miniflow *flow) -{ - return MINIFLOW_GET_BE64(flow, metadata); -} - -/* Returns the bitmap that indicates which tunnel metadata fields are present - * in 'flow'. */ -static inline uint64_t -miniflow_get_tun_metadata_present_map(const struct miniflow *flow) -{ - return MINIFLOW_GET_U64(flow, tunnel.metadata.present.map); -} - -/* Returns the recirc_id in 'flow.' */ -static inline uint32_t -miniflow_get_recirc_id(const struct miniflow *flow) -{ - return MINIFLOW_GET_U32(flow, recirc_id); -} - -/* Returns the dp_hash in 'flow.' */ -static inline uint32_t -miniflow_get_dp_hash(const struct miniflow *flow) -{ - return MINIFLOW_GET_U32(flow, dp_hash); -} - -/* Returns the 'tp_src' and 'tp_dst' fields together as one piece of data. */ -static inline ovs_be32 -miniflow_get_ports(const struct miniflow *flow) -{ - return MINIFLOW_GET_TYPE__(flow, ovs_be32, tp_src); -} - -/* Returns the mask for the OpenFlow 1.1+ "metadata" field in 'mask'. - * - * The return value is all-1-bits if 'mask' matches on the whole value of the - * metadata field, all-0-bits if 'mask' entirely wildcards the metadata field, - * or some other value if the metadata field is partially matched, partially - * wildcarded. */ -static inline ovs_be64 -minimask_get_metadata_mask(const struct minimask *mask) -{ - return MINIFLOW_GET_BE64(&mask->masks, metadata); -} - -/* Perform a bitwise OR of miniflow 'src' flow data specified in 'subset' with - * the equivalent fields in 'dst', storing the result in 'dst'. 'subset' must - * be a subset of 'src's map. */ -static inline void -flow_union_with_miniflow_subset(struct flow *dst, const struct miniflow *src, - struct flowmap subset) -{ - uint64_t *dst_u64 = (uint64_t *) dst; - const uint64_t *p = miniflow_get_values(src); - map_t map; - - FLOWMAP_FOR_EACH_MAP (map, subset) { - size_t idx; - - MAP_FOR_EACH_INDEX(idx, map) { - dst_u64[idx] |= *p++; - } - dst_u64 += MAP_T_BITS; - } -} - -/* Perform a bitwise OR of miniflow 'src' flow data with the equivalent - * fields in 'dst', storing the result in 'dst'. */ -static inline void -flow_union_with_miniflow(struct flow *dst, const struct miniflow *src) -{ - flow_union_with_miniflow_subset(dst, src, src->map); -} - -static inline bool is_ct_valid(const struct flow *flow, - const struct flow_wildcards *mask, - struct flow_wildcards *wc) -{ - /* Matches are checked with 'mask' and without 'wc'. */ - if (mask && !wc) { - /* Must match at least one of the bits that implies a valid - * conntrack entry, or an explicit not-invalid. */ - return flow->ct_state & (CS_NEW | CS_ESTABLISHED | CS_RELATED - | CS_REPLY_DIR | CS_SRC_NAT | CS_DST_NAT) - || (flow->ct_state & CS_TRACKED - && mask->masks.ct_state & CS_INVALID - && !(flow->ct_state & CS_INVALID)); - } - /* Else we are checking a fully extracted flow, where valid CT state always - * has either 'new', 'established', or 'reply_dir' bit set. */ -#define CS_VALID_MASK (CS_NEW | CS_ESTABLISHED | CS_REPLY_DIR) - if (wc) { - wc->masks.ct_state |= CS_VALID_MASK; - } - return flow->ct_state & CS_VALID_MASK; -} - -static inline void -pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow) -{ - /* Update this function whenever struct flow changes. */ - BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42); - - md->recirc_id = flow->recirc_id; - md->dp_hash = flow->dp_hash; - flow_tnl_copy__(&md->tunnel, &flow->tunnel); - md->skb_priority = flow->skb_priority; - md->pkt_mark = flow->pkt_mark; - md->in_port = flow->in_port; - md->ct_state = flow->ct_state; - md->ct_zone = flow->ct_zone; - md->ct_mark = flow->ct_mark; - md->ct_label = flow->ct_label; - - md->ct_orig_tuple_ipv6 = false; - if (flow->dl_type && is_ct_valid(flow, NULL, NULL)) { - if (flow->dl_type == htons(ETH_TYPE_IP)) { - md->ct_orig_tuple.ipv4 = (struct ovs_key_ct_tuple_ipv4) { - flow->ct_nw_src, - flow->ct_nw_dst, - flow->ct_tp_src, - flow->ct_tp_dst, - flow->ct_nw_proto, - }; - } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { - md->ct_orig_tuple_ipv6 = true; - md->ct_orig_tuple.ipv6 = (struct ovs_key_ct_tuple_ipv6) { - flow->ct_ipv6_src, - flow->ct_ipv6_dst, - flow->ct_tp_src, - flow->ct_tp_dst, - flow->ct_nw_proto, - }; - } else { - /* Reset ct_orig_tuple for other types. */ - memset(&md->ct_orig_tuple, 0, sizeof md->ct_orig_tuple); - } - } else { - memset(&md->ct_orig_tuple, 0, sizeof md->ct_orig_tuple); - } -} - -/* Often, during translation we need to read a value from a flow('FLOW') and - * unwildcard the corresponding bits in the wildcards('WC'). This macro makes - * it easier to do that. */ - -#define FLOW_WC_GET_AND_MASK_WC(FLOW, WC, FIELD) \ - (((WC) ? WC_MASK_FIELD(WC, FIELD) : NULL), ((FLOW)->FIELD)) - -static inline bool is_ethernet(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (wc) { - WC_MASK_FIELD(wc, packet_type); - } - return flow->packet_type == htonl(PT_ETH); -} - -static inline ovs_be16 get_dl_type(const struct flow *flow) -{ - if (flow->packet_type == htonl(PT_ETH)) { - return flow->dl_type; - } else if (pt_ns(flow->packet_type) == OFPHTN_ETHERTYPE) { - return pt_ns_type_be(flow->packet_type); - } else { - return htons(FLOW_DL_TYPE_NONE); - } -} - -static inline bool is_vlan(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (!is_ethernet(flow, wc)) { - return false; - } - if (wc) { - WC_MASK_FIELD_MASK(wc, vlans[0].tci, htons(VLAN_CFI)); - } - return (flow->vlans[0].tci & htons(VLAN_CFI)) != 0; -} - -static inline bool is_ip_any(const struct flow *flow) -{ - return dl_type_is_ip_any(get_dl_type(flow)); -} - -static inline bool is_ip_proto(const struct flow *flow, uint8_t ip_proto, - struct flow_wildcards *wc) -{ - if (is_ip_any(flow)) { - if (wc) { - WC_MASK_FIELD(wc, nw_proto); - } - return flow->nw_proto == ip_proto; - } - return false; -} - -static inline bool is_tcp(const struct flow *flow, - struct flow_wildcards *wc) -{ - return is_ip_proto(flow, IPPROTO_TCP, wc); -} - -static inline bool is_udp(const struct flow *flow, - struct flow_wildcards *wc) -{ - return is_ip_proto(flow, IPPROTO_UDP, wc); -} - -static inline bool is_sctp(const struct flow *flow, - struct flow_wildcards *wc) -{ - return is_ip_proto(flow, IPPROTO_SCTP, wc); -} - -static inline bool is_icmpv4(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (get_dl_type(flow) == htons(ETH_TYPE_IP)) { - if (wc) { - memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); - } - return flow->nw_proto == IPPROTO_ICMP; - } - return false; -} - -static inline bool is_icmpv6(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (get_dl_type(flow) == htons(ETH_TYPE_IPV6)) { - if (wc) { - memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); - } - return flow->nw_proto == IPPROTO_ICMPV6; - } - return false; -} - -static inline bool is_nd(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (is_icmpv6(flow, wc)) { - if (wc) { - memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst); - } - if (flow->tp_dst != htons(0)) { - return false; - } - - if (wc) { - memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); - } - return (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) || - flow->tp_src == htons(ND_NEIGHBOR_ADVERT)); - } - return false; -} - -static inline bool is_arp(const struct flow *flow) -{ - return (flow->dl_type == htons(ETH_TYPE_ARP)); -} - -static inline bool is_garp(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (is_arp(flow)) { - return (FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_src) == - FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_dst)); - } - - return false; -} - -static inline bool is_igmp(const struct flow *flow, struct flow_wildcards *wc) -{ - if (get_dl_type(flow) == htons(ETH_TYPE_IP)) { - if (wc) { - memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); - } - return flow->nw_proto == IPPROTO_IGMP; - } - return false; -} - -static inline bool is_mld(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (is_icmpv6(flow, wc)) { - if (wc) { - memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); - } - return (flow->tp_src == htons(MLD_QUERY) - || flow->tp_src == htons(MLD_REPORT) - || flow->tp_src == htons(MLD_DONE) - || flow->tp_src == htons(MLD2_REPORT)); - } - return false; -} - -static inline bool is_mld_query(const struct flow *flow, - struct flow_wildcards *wc) -{ - if (is_icmpv6(flow, wc)) { - if (wc) { - memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); - } - return flow->tp_src == htons(MLD_QUERY); - } - return false; -} - -static inline bool is_mld_report(const struct flow *flow, - struct flow_wildcards *wc) -{ - return is_mld(flow, wc) && !is_mld_query(flow, wc); -} - -static inline bool is_stp(const struct flow *flow) -{ - return (flow->dl_type == htons(FLOW_DL_TYPE_NONE) - && eth_addr_equals(flow->dl_dst, eth_addr_stp)); -} - -/* Returns true if flow->tp_dst equals 'port'. If 'wc' is nonnull, sets - * appropriate bits in wc->masks.tp_dst to account for the test. - * - * The caller must already have ensured that 'flow' is a protocol for which - * tp_dst is relevant. */ -static inline bool tp_dst_equals(const struct flow *flow, uint16_t port, - struct flow_wildcards *wc) -{ - uint16_t diff = port ^ ntohs(flow->tp_dst); - if (wc) { - if (diff) { - /* Set mask for the most significant mismatching bit. */ - int ofs = raw_clz64((uint64_t) diff << 48); /* range [0,15] */ - wc->masks.tp_dst |= htons(0x8000 >> ofs); - } else { - /* Must match all bits. */ - wc->masks.tp_dst = OVS_BE16_MAX; - } - } - return !diff; -} - -#endif /* flow.h */ Index: openvswitch-2.17.2/include/internal/flow.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/flow.h @@ -0,0 +1,1215 @@ +/* + * 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. + */ +#ifndef FLOW_H +#define FLOW_H 1 + +#include +#include +#include +#include +#include +#include +#include "internal/bitmap.h" +#include "internal/byte-order.h" +#include "openvswitch/compiler.h" +#include "openflow/nicira-ext.h" +#include "openflow/openflow.h" +#include "openvswitch/flow.h" +#include "internal/packets.h" +#include "internal/hash.h" +#include "internal/util.h" + +struct dpif_flow_stats; +struct dpif_flow_attrs; +struct ds; +struct flow_wildcards; +struct minimask; +struct dp_packet; +struct ofputil_port_map; +struct pkt_metadata; +struct match; + +/* Some flow fields are mutually exclusive or only appear within the flow + * pipeline. IPv6 headers are bigger than IPv4 and MPLS, and IPv6 ND packets + * are bigger than TCP,UDP and IGMP packets. */ +#define FLOW_MAX_PACKET_U64S (FLOW_U64S \ + /* Unused in datapath */ - FLOW_U64_SIZE(regs) \ + - FLOW_U64_SIZE(metadata) \ + /* L2.5/3 */ - FLOW_U64_SIZE(nw_src) /* incl. nw_dst */ \ + - FLOW_U64_SIZE(mpls_lse) \ + /* L4 */ - FLOW_U64_SIZE(tp_src) \ + ) + +extern const uint8_t flow_segment_u64s[]; + +/* Configured maximum VLAN headers. */ +extern int flow_vlan_limit; + +#define FLOW_U64_OFFSET(FIELD) \ + (offsetof(struct flow, FIELD) / sizeof(uint64_t)) +#define FLOW_U64_OFFREM(FIELD) \ + (offsetof(struct flow, FIELD) % sizeof(uint64_t)) + +/* Number of 64-bit units spanned by a 'FIELD'. */ +#define FLOW_U64_SIZE(FIELD) \ + DIV_ROUND_UP(FLOW_U64_OFFREM(FIELD) + MEMBER_SIZEOF(struct flow, FIELD), \ + sizeof(uint64_t)) + +void flow_extract(struct dp_packet *, struct flow *); + +void flow_zero_wildcards(struct flow *, const struct flow_wildcards *); +void flow_unwildcard_tp_ports(const struct flow *, struct flow_wildcards *); +void flow_get_metadata(const struct flow *, struct match *flow_metadata); +struct netdev *flow_get_tunnel_netdev(struct flow_tnl *tunnel); + +const char *ct_state_to_string(uint32_t state); +uint32_t ct_state_from_string(const char *); +bool parse_ct_state(const char *state_str, uint32_t default_state, + uint32_t *ct_state, struct ds *); +bool validate_ct_state(uint32_t state, struct ds *); +void flow_clear_conntrack(struct flow *); + +char *flow_to_string(const struct flow *, const struct ofputil_port_map *); +void format_flags(struct ds *ds, const char *(*bit_to_string)(uint32_t), + uint32_t flags, char del); +void format_flags_masked(struct ds *ds, const char *name, + const char *(*bit_to_string)(uint32_t), + uint32_t flags, uint32_t mask, uint32_t max_mask); +void format_packet_type_masked(struct ds *, ovs_be32 value, ovs_be32 mask); +int parse_flags(const char *s, const char *(*bit_to_string)(uint32_t), + char end, const char *field_name, char **res_string, + uint32_t *res_flags, uint32_t allowed, uint32_t *res_mask); + +void flow_format(struct ds *, const struct flow *, + const struct ofputil_port_map *); +void flow_print(FILE *, const struct flow *, const struct ofputil_port_map *); +static inline int flow_compare_3way(const struct flow *, const struct flow *); +static inline bool flow_equal(const struct flow *, const struct flow *); +static inline size_t flow_hash(const struct flow *, uint32_t basis); + +void flow_set_dl_vlan(struct flow *, ovs_be16 vid, int id); +void flow_fix_vlan_tpid(struct flow *); +void flow_set_vlan_vid(struct flow *, ovs_be16 vid); +void flow_set_vlan_pcp(struct flow *, uint8_t pcp, int id); + +void flow_limit_vlans(int vlan_limit); +int flow_count_vlan_headers(const struct flow *); +void flow_skip_common_vlan_headers(const struct flow *a, int *p_an, + const struct flow *b, int *p_bn); +void flow_pop_vlan(struct flow*, struct flow_wildcards*); +void flow_push_vlan_uninit(struct flow*, struct flow_wildcards*); + +int flow_count_mpls_labels(const struct flow *, struct flow_wildcards *); +int flow_count_common_mpls_labels(const struct flow *a, int an, + const struct flow *b, int bn, + struct flow_wildcards *wc); +void flow_push_mpls(struct flow *, int n, ovs_be16 mpls_eth_type, + struct flow_wildcards *, bool clear_flow_L3); +bool flow_pop_mpls(struct flow *, int n, ovs_be16 eth_type, + struct flow_wildcards *); +void flow_set_mpls_label(struct flow *, int idx, ovs_be32 label); +void flow_set_mpls_ttl(struct flow *, int idx, uint8_t ttl); +void flow_set_mpls_tc(struct flow *, int idx, uint8_t tc); +void flow_set_mpls_bos(struct flow *, int idx, uint8_t stack); +void flow_set_mpls_lse(struct flow *, int idx, ovs_be32 lse); + +void flow_compose(struct dp_packet *, const struct flow *, + const void *l7, size_t l7_len); +void packet_expand(struct dp_packet *, const struct flow *, size_t size); + +bool parse_ipv6_ext_hdrs(const void **datap, size_t *sizep, uint8_t *nw_proto, + uint8_t *nw_frag, + const struct ovs_16aligned_ip6_frag **frag_hdr); +bool parse_nsh(const void **datap, size_t *sizep, struct ovs_key_nsh *key); +uint16_t parse_tcp_flags(struct dp_packet *packet, ovs_be16 *dl_type_p, + uint8_t *nw_frag_p, ovs_be16 *first_vlan_tci_p); + +static inline uint64_t +flow_get_xreg(const struct flow *flow, int idx) +{ + return ((uint64_t) flow->regs[idx * 2] << 32) | flow->regs[idx * 2 + 1]; +} + +static inline void +flow_set_xreg(struct flow *flow, int idx, uint64_t value) +{ + flow->regs[idx * 2] = value >> 32; + flow->regs[idx * 2 + 1] = value; +} + +static inline ovs_u128 +flow_get_xxreg(const struct flow *flow, int idx) +{ + ovs_u128 value; + + value.u64.hi = (uint64_t) flow->regs[idx * 4] << 32; + value.u64.hi |= flow->regs[idx * 4 + 1]; + value.u64.lo = (uint64_t) flow->regs[idx * 4 + 2] << 32; + value.u64.lo |= flow->regs[idx * 4 + 3]; + + return value; +} + +static inline void +flow_set_xxreg(struct flow *flow, int idx, ovs_u128 value) +{ + flow->regs[idx * 4] = value.u64.hi >> 32; + flow->regs[idx * 4 + 1] = value.u64.hi; + flow->regs[idx * 4 + 2] = value.u64.lo >> 32; + flow->regs[idx * 4 + 3] = value.u64.lo; +} + +static inline int +flow_compare_3way(const struct flow *a, const struct flow *b) +{ + return memcmp(a, b, sizeof *a); +} + +static inline bool +flow_equal(const struct flow *a, const struct flow *b) +{ + return !flow_compare_3way(a, b); +} + +static inline size_t +flow_hash(const struct flow *flow, uint32_t basis) +{ + return hash_bytes64((const uint64_t *)flow, sizeof *flow, basis); +} + +static inline uint16_t +ofp_to_u16(ofp_port_t ofp_port) +{ + return (OVS_FORCE uint16_t) ofp_port; +} + +static inline uint32_t +odp_to_u32(odp_port_t odp_port) +{ + return (OVS_FORCE uint32_t) odp_port; +} + +static inline uint32_t +ofp11_to_u32(ofp11_port_t ofp11_port) +{ + return (OVS_FORCE uint32_t) ofp11_port; +} + +static inline ofp_port_t +u16_to_ofp(uint16_t port) +{ + return OFP_PORT_C(port); +} + +static inline odp_port_t +u32_to_odp(uint32_t port) +{ + return ODP_PORT_C(port); +} + +static inline ofp11_port_t +u32_to_ofp11(uint32_t port) +{ + return OFP11_PORT_C(port); +} + +static inline uint32_t +hash_ofp_port(ofp_port_t ofp_port) +{ + return hash_int(ofp_to_u16(ofp_port), 0); +} + +static inline uint32_t +hash_odp_port(odp_port_t odp_port) +{ + return hash_int(odp_to_u32(odp_port), 0); +} + +uint32_t flow_hash_5tuple(const struct flow *flow, uint32_t basis); +uint32_t flow_hash_symmetric_l4(const struct flow *flow, uint32_t basis); +uint32_t flow_hash_symmetric_l2(const struct flow *flow, uint32_t basis); +uint32_t flow_hash_symmetric_l3l4(const struct flow *flow, uint32_t basis, + bool inc_udp_ports ); +uint32_t flow_hash_symmetric_l3(const struct flow *flow, uint32_t basis); + +/* Initialize a flow with random fields that matter for nx_hash_fields. */ +void flow_random_hash_fields(struct flow *); +void flow_mask_hash_fields(const struct flow *, struct flow_wildcards *, + enum nx_hash_fields); +uint32_t flow_hash_fields(const struct flow *, enum nx_hash_fields, + uint16_t basis); +const char *flow_hash_fields_to_str(enum nx_hash_fields); +bool flow_hash_fields_valid(enum nx_hash_fields); + +uint32_t flow_hash_in_wildcards(const struct flow *, + const struct flow_wildcards *, + uint32_t basis); + +bool flow_equal_except(const struct flow *a, const struct flow *b, + const struct flow_wildcards *); + +/* Bitmap for flow values. For each 1-bit the corresponding flow value is + * explicitly specified, other values are zeroes. + * + * map_t must be wide enough to hold any member of struct flow. */ +typedef unsigned long long map_t; +#define MAP_T_BITS (sizeof(map_t) * CHAR_BIT) +#define MAP_1 (map_t)1 +#define MAP_MAX TYPE_MAXIMUM(map_t) + +#define MAP_IS_SET(MAP, IDX) ((MAP) & (MAP_1 << (IDX))) + +/* Iterate through the indices of all 1-bits in 'MAP'. */ +#define MAP_FOR_EACH_INDEX(IDX, MAP) \ + ULLONG_FOR_EACH_1(IDX, MAP) + +#define FLOWMAP_UNITS DIV_ROUND_UP(FLOW_U64S, MAP_T_BITS) + +struct flowmap { + map_t bits[FLOWMAP_UNITS]; +}; + +#define FLOWMAP_EMPTY_INITIALIZER { { 0 } } + +static inline void flowmap_init(struct flowmap *); +static inline bool flowmap_equal(struct flowmap, struct flowmap); +static inline bool flowmap_is_set(const struct flowmap *, size_t idx); +static inline bool flowmap_are_set(const struct flowmap *, size_t idx, + unsigned int n_bits); +static inline void flowmap_set(struct flowmap *, size_t idx, + unsigned int n_bits); +static inline void flowmap_clear(struct flowmap *, size_t idx, + unsigned int n_bits); +static inline struct flowmap flowmap_or(struct flowmap, struct flowmap); +static inline struct flowmap flowmap_and(struct flowmap, struct flowmap); +static inline bool flowmap_is_empty(struct flowmap); +static inline unsigned int flowmap_n_1bits(struct flowmap); + +#define FLOWMAP_HAS_FIELD(FM, FIELD) \ + flowmap_are_set(FM, FLOW_U64_OFFSET(FIELD), FLOW_U64_SIZE(FIELD)) + +#define FLOWMAP_SET(FM, FIELD) \ + flowmap_set(FM, FLOW_U64_OFFSET(FIELD), FLOW_U64_SIZE(FIELD)) + +#define FLOWMAP_SET__(FM, FIELD, SIZE) \ + flowmap_set(FM, FLOW_U64_OFFSET(FIELD), \ + DIV_ROUND_UP(SIZE, sizeof(uint64_t))) + +/* XXX: Only works for full 64-bit units. */ +#define FLOWMAP_CLEAR(FM, FIELD) \ + BUILD_ASSERT_DECL(FLOW_U64_OFFREM(FIELD) == 0); \ + BUILD_ASSERT_DECL(sizeof(((struct flow *)0)->FIELD) % sizeof(uint64_t) == 0); \ + flowmap_clear(FM, FLOW_U64_OFFSET(FIELD), FLOW_U64_SIZE(FIELD)) + +/* Iterate through all units in 'FMAP'. */ +#define FLOWMAP_FOR_EACH_UNIT(UNIT) \ + for ((UNIT) = 0; (UNIT) < FLOWMAP_UNITS; (UNIT)++) + +/* Iterate through all map units in 'FMAP'. */ +#define FLOWMAP_FOR_EACH_MAP(MAP, FLOWMAP) \ + for (size_t unit__ = 0; \ + unit__ < FLOWMAP_UNITS && ((MAP) = (FLOWMAP).bits[unit__], true); \ + unit__++) + +struct flowmap_aux; +static inline bool flowmap_next_index(struct flowmap_aux *, size_t *idx); + +#define FLOWMAP_AUX_INITIALIZER(FLOWMAP) { .unit = 0, .map = (FLOWMAP) } + +/* Iterate through all struct flow u64 indices specified by 'MAP'. This is a + * slower but easier version of the FLOWMAP_FOR_EACH_MAP() & + * MAP_FOR_EACH_INDEX() combination. */ +#define FLOWMAP_FOR_EACH_INDEX(IDX, MAP) \ + for (struct flowmap_aux aux__ = FLOWMAP_AUX_INITIALIZER(MAP); \ + flowmap_next_index(&aux__, &(IDX));) + +/* Flowmap inline implementations. */ +static inline void +flowmap_init(struct flowmap *fm) +{ + memset(fm, 0, sizeof *fm); +} + +static inline bool +flowmap_equal(struct flowmap a, struct flowmap b) +{ + return !memcmp(&a, &b, sizeof a); +} + +static inline bool +flowmap_is_set(const struct flowmap *fm, size_t idx) +{ + return (fm->bits[idx / MAP_T_BITS] & (MAP_1 << (idx % MAP_T_BITS))) != 0; +} + +/* Returns 'true' if any of the 'n_bits' bits starting at 'idx' are set in + * 'fm'. 'n_bits' can be at most MAP_T_BITS. */ +static inline bool +flowmap_are_set(const struct flowmap *fm, size_t idx, unsigned int n_bits) +{ + map_t n_bits_mask = (MAP_1 << n_bits) - 1; + size_t unit = idx / MAP_T_BITS; + + idx %= MAP_T_BITS; + + if (fm->bits[unit] & (n_bits_mask << idx)) { + return true; + } + /* The seemingly unnecessary bounds check on 'unit' is a workaround for a + * false-positive array out of bounds error by GCC 4.9. */ + if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { + /* Check the remaining bits from the next unit. */ + return fm->bits[unit + 1] & (n_bits_mask >> (MAP_T_BITS - idx)); + } + return false; +} + +/* Set the 'n_bits' consecutive bits in 'fm', starting at bit 'idx'. + * 'n_bits' can be at most MAP_T_BITS. */ +static inline void +flowmap_set(struct flowmap *fm, size_t idx, unsigned int n_bits) +{ + map_t n_bits_mask = (MAP_1 << n_bits) - 1; + size_t unit = idx / MAP_T_BITS; + + idx %= MAP_T_BITS; + + fm->bits[unit] |= n_bits_mask << idx; + /* The seemingly unnecessary bounds check on 'unit' is a workaround for a + * false-positive array out of bounds error by GCC 4.9. */ + if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { + /* 'MAP_T_BITS - idx' bits were set on 'unit', set the remaining + * bits from the next unit. */ + fm->bits[unit + 1] |= n_bits_mask >> (MAP_T_BITS - idx); + } +} + +/* Clears the 'n_bits' consecutive bits in 'fm', starting at bit 'idx'. + * 'n_bits' can be at most MAP_T_BITS. */ +static inline void +flowmap_clear(struct flowmap *fm, size_t idx, unsigned int n_bits) +{ + map_t n_bits_mask = (MAP_1 << n_bits) - 1; + size_t unit = idx / MAP_T_BITS; + + idx %= MAP_T_BITS; + + fm->bits[unit] &= ~(n_bits_mask << idx); + /* The seemingly unnecessary bounds check on 'unit' is a workaround for a + * false-positive array out of bounds error by GCC 4.9. */ + if (unit + 1 < FLOWMAP_UNITS && idx + n_bits > MAP_T_BITS) { + /* 'MAP_T_BITS - idx' bits were cleared on 'unit', clear the + * remaining bits from the next unit. */ + fm->bits[unit + 1] &= ~(n_bits_mask >> (MAP_T_BITS - idx)); + } +} + +/* OR the bits in the flowmaps. */ +static inline struct flowmap +flowmap_or(struct flowmap a, struct flowmap b) +{ + struct flowmap map; + size_t unit; + + FLOWMAP_FOR_EACH_UNIT (unit) { + map.bits[unit] = a.bits[unit] | b.bits[unit]; + } + return map; +} + +/* AND the bits in the flowmaps. */ +static inline struct flowmap +flowmap_and(struct flowmap a, struct flowmap b) +{ + struct flowmap map; + size_t unit; + + FLOWMAP_FOR_EACH_UNIT (unit) { + map.bits[unit] = a.bits[unit] & b.bits[unit]; + } + return map; +} + +static inline bool +flowmap_is_empty(struct flowmap fm) +{ + map_t map; + + FLOWMAP_FOR_EACH_MAP (map, fm) { + if (map) { + return false; + } + } + return true; +} + +static inline unsigned int +flowmap_n_1bits(struct flowmap fm) +{ + unsigned int n_1bits = 0; + size_t unit; + + FLOWMAP_FOR_EACH_UNIT (unit) { + n_1bits += count_1bits(fm.bits[unit]); + } + return n_1bits; +} + +struct flowmap_aux { + size_t unit; + struct flowmap map; +}; + +static inline bool +flowmap_next_index(struct flowmap_aux *aux, size_t *idx) +{ + for (;;) { + map_t *map = &aux->map.bits[aux->unit]; + if (*map) { + *idx = aux->unit * MAP_T_BITS + raw_ctz(*map); + *map = zero_rightmost_1bit(*map); + return true; + } + if (++aux->unit >= FLOWMAP_UNITS) { + return false; + } + } +} + + +/* Compressed flow. */ + +/* A sparse representation of a "struct flow". + * + * A "struct flow" is fairly large and tends to be mostly zeros. Sparse + * representation has two advantages. First, it saves memory and, more + * importantly, minimizes the number of accessed cache lines. Second, it saves + * time when the goal is to iterate over only the nonzero parts of the struct. + * + * The map member hold one bit for each uint64_t in a "struct flow". Each + * 0-bit indicates that the corresponding uint64_t is zero, each 1-bit that it + * *may* be nonzero (see below how this applies to minimasks). + * + * The values indicated by 'map' always follow the miniflow in memory. The + * user of the miniflow is responsible for always having enough storage after + * the struct miniflow corresponding to the number of 1-bits in maps. + * + * Elements in values array are allowed to be zero. This is useful for "struct + * minimatch", for which ensuring that the miniflow and minimask members have + * same maps allows optimization. This allowance applies only to a miniflow + * that is not a mask. That is, a minimask may NOT have zero elements in its + * values. + * + * A miniflow is always dynamically allocated so that the maps are followed by + * at least as many elements as there are 1-bits in maps. */ +struct miniflow { + struct flowmap map; + /* Followed by: + * uint64_t values[n]; + * where 'n' is miniflow_n_values(miniflow). */ +}; +BUILD_ASSERT_DECL(sizeof(struct miniflow) % sizeof(uint64_t) == 0); + +#define MINIFLOW_VALUES_SIZE(COUNT) ((COUNT) * sizeof(uint64_t)) + +static inline uint64_t *miniflow_values(struct miniflow *mf) +{ + return (uint64_t *)(mf + 1); +} + +static inline const uint64_t *miniflow_get_values(const struct miniflow *mf) +{ + return (const uint64_t *)(mf + 1); +} + +struct pkt_metadata; + +/* The 'dst' must follow with buffer space for FLOW_U64S 64-bit units. + * 'dst->map' is ignored on input and set on output to indicate which fields + * were extracted. */ +void miniflow_extract(struct dp_packet *packet, struct miniflow *dst); +void miniflow_map_init(struct miniflow *, const struct flow *); +void flow_wc_map(const struct flow *, struct flowmap *); +size_t miniflow_alloc(struct miniflow *dsts[], size_t n, + const struct miniflow *src); +void miniflow_init(struct miniflow *, const struct flow *); +void miniflow_clone(struct miniflow *, const struct miniflow *, + size_t n_values); +struct miniflow * miniflow_create(const struct flow *); + +void miniflow_expand(const struct miniflow *, struct flow *); + +static inline uint64_t flow_u64_value(const struct flow *flow, size_t index) +{ + return ((uint64_t *)flow)[index]; +} + +static inline uint64_t *flow_u64_lvalue(struct flow *flow, size_t index) +{ + return &((uint64_t *)flow)[index]; +} + +static inline size_t +miniflow_n_values(const struct miniflow *flow) +{ + return flowmap_n_1bits(flow->map); +} + +struct flow_for_each_in_maps_aux { + const struct flow *flow; + struct flowmap_aux map_aux; +}; + +static inline bool +flow_values_get_next_in_maps(struct flow_for_each_in_maps_aux *aux, + uint64_t *value) +{ + size_t idx; + + if (flowmap_next_index(&aux->map_aux, &idx)) { + *value = flow_u64_value(aux->flow, idx); + return true; + } + return false; +} + +/* Iterate through all flow u64 values specified by 'MAPS'. */ +#define FLOW_FOR_EACH_IN_MAPS(VALUE, FLOW, MAPS) \ + for (struct flow_for_each_in_maps_aux aux__ \ + = { (FLOW), FLOWMAP_AUX_INITIALIZER(MAPS) }; \ + flow_values_get_next_in_maps(&aux__, &(VALUE));) + +struct mf_for_each_in_map_aux { + size_t unit; /* Current 64-bit unit of the flowmaps + being processed. */ + struct flowmap fmap; /* Remaining 1-bits corresponding to the + 64-bit words in 'values' */ + struct flowmap map; /* Remaining 1-bits corresponding to the + 64-bit words of interest. */ + const uint64_t *values; /* 64-bit words corresponding to the + 1-bits in 'fmap'. */ +}; + +/* Get the data from 'aux->values' corresponding to the next lowest 1-bit + * in 'aux->map', given that 'aux->values' points to an array of 64-bit + * words corresponding to the 1-bits in 'aux->fmap', starting from the + * rightmost 1-bit. + * + * Returns 'true' if the traversal is incomplete, 'false' otherwise. + * 'aux' is prepared for the next iteration after each call. + * + * This is used to traverse through, for example, the values in a miniflow + * representation of a flow key selected by non-zero 64-bit words in a + * corresponding subtable mask. */ +static inline bool +mf_get_next_in_map(struct mf_for_each_in_map_aux *aux, + uint64_t *value) +{ + map_t *map, *fmap; + map_t rm1bit; + + /* Skip empty map units. */ + while (OVS_UNLIKELY(!*(map = &aux->map.bits[aux->unit]))) { + /* Skip remaining data in the current unit before advancing + * to the next. */ + aux->values += count_1bits(aux->fmap.bits[aux->unit]); + if (++aux->unit == FLOWMAP_UNITS) { + return false; + } + } + + rm1bit = rightmost_1bit(*map); + *map -= rm1bit; + fmap = &aux->fmap.bits[aux->unit]; + + /* If the rightmost 1-bit found from the current unit in 'aux->map' + * ('rm1bit') is also present in 'aux->fmap', store the corresponding + * value from 'aux->values' to '*value', otherwise store 0. */ + if (OVS_LIKELY(*fmap & rm1bit)) { + /* Skip all 64-bit words in 'values' preceding the one corresponding + * to 'rm1bit'. */ + map_t trash = *fmap & (rm1bit - 1); + + /* Avoid resetting 'fmap' and calling count_1bits() when trash is + * zero. */ + if (trash) { + *fmap -= trash; + aux->values += count_1bits(trash); + } + + *value = *aux->values; + } else { + *value = 0; + } + return true; +} + +/* Iterate through miniflow u64 values specified by 'FLOWMAP'. */ +#define MINIFLOW_FOR_EACH_IN_FLOWMAP(VALUE, FLOW, FLOWMAP) \ + for (struct mf_for_each_in_map_aux aux__ = \ + { 0, (FLOW)->map, (FLOWMAP), miniflow_get_values(FLOW) }; \ + mf_get_next_in_map(&aux__, &(VALUE));) + +/* This can be used when it is known that 'idx' is set in 'map'. */ +static inline const uint64_t * +miniflow_values_get__(const uint64_t *values, map_t map, size_t idx) +{ + return values + count_1bits(map & ((MAP_1 << idx) - 1)); +} + +/* This can be used when it is known that 'u64_idx' is set in + * the map of 'mf'. */ +static inline const uint64_t * +miniflow_get__(const struct miniflow *mf, size_t idx) +{ + const uint64_t *values = miniflow_get_values(mf); + const map_t *map = mf->map.bits; + + while (idx >= MAP_T_BITS) { + idx -= MAP_T_BITS; + values += count_1bits(*map++); + } + return miniflow_values_get__(values, *map, idx); +} + +#define MINIFLOW_IN_MAP(MF, IDX) flowmap_is_set(&(MF)->map, IDX) + +/* Get the value of the struct flow 'FIELD' as up to 8 byte wide integer type + * 'TYPE' from miniflow 'MF'. */ +#define MINIFLOW_GET_TYPE(MF, TYPE, FIELD) \ + (BUILD_ASSERT(sizeof(TYPE) == sizeof(((struct flow *)0)->FIELD)), \ + BUILD_ASSERT_GCCONLY(__builtin_types_compatible_p(TYPE, typeof(((struct flow *)0)->FIELD))), \ + MINIFLOW_GET_TYPE__(MF, TYPE, FIELD)) + +/* Like MINIFLOW_GET_TYPE, but without checking that TYPE is the correct width + * for FIELD. (This is useful for deliberately reading adjacent fields in one + * go.) */ +#define MINIFLOW_GET_TYPE__(MF, TYPE, FIELD) \ + (MINIFLOW_IN_MAP(MF, FLOW_U64_OFFSET(FIELD)) \ + ? ((OVS_FORCE const TYPE *)miniflow_get__(MF, FLOW_U64_OFFSET(FIELD))) \ + [FLOW_U64_OFFREM(FIELD) / sizeof(TYPE)] \ + : 0) + +#define MINIFLOW_GET_U128(FLOW, FIELD) \ + (ovs_u128) { .u64 = { \ + (MINIFLOW_IN_MAP(FLOW, FLOW_U64_OFFSET(FIELD)) ? \ + *miniflow_get__(FLOW, FLOW_U64_OFFSET(FIELD)) : 0), \ + (MINIFLOW_IN_MAP(FLOW, FLOW_U64_OFFSET(FIELD) + 1) ? \ + *miniflow_get__(FLOW, FLOW_U64_OFFSET(FIELD) + 1) : 0) } } + +#define MINIFLOW_GET_U8(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, uint8_t, FIELD) +#define MINIFLOW_GET_U16(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, uint16_t, FIELD) +#define MINIFLOW_GET_BE16(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, ovs_be16, FIELD) +#define MINIFLOW_GET_U32(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, uint32_t, FIELD) +#define MINIFLOW_GET_BE32(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, ovs_be32, FIELD) +#define MINIFLOW_GET_U64(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, uint64_t, FIELD) +#define MINIFLOW_GET_BE64(FLOW, FIELD) \ + MINIFLOW_GET_TYPE(FLOW, ovs_be64, FIELD) + +static inline uint64_t miniflow_get(const struct miniflow *, + unsigned int u64_ofs); +static inline uint32_t miniflow_get_u32(const struct miniflow *, + unsigned int u32_ofs); +static inline ovs_be32 miniflow_get_be32(const struct miniflow *, + unsigned int be32_ofs); +static inline uint16_t miniflow_get_vid(const struct miniflow *, size_t); +static inline uint16_t miniflow_get_tcp_flags(const struct miniflow *); +static inline ovs_be64 miniflow_get_metadata(const struct miniflow *); +static inline uint64_t miniflow_get_tun_metadata_present_map( + const struct miniflow *); +static inline uint32_t miniflow_get_recirc_id(const struct miniflow *); +static inline uint32_t miniflow_get_dp_hash(const struct miniflow *); +static inline ovs_be32 miniflow_get_ports(const struct miniflow *); + +bool miniflow_equal(const struct miniflow *a, const struct miniflow *b); +bool miniflow_equal_in_minimask(const struct miniflow *a, + const struct miniflow *b, + const struct minimask *); +bool miniflow_equal_flow_in_minimask(const struct miniflow *a, + const struct flow *b, + const struct minimask *); +uint32_t miniflow_hash_5tuple(const struct miniflow *flow, uint32_t basis); + + +/* Compressed flow wildcards. */ + +/* A sparse representation of a "struct flow_wildcards". + * + * See the large comment on struct miniflow for details. + * + * Note: While miniflow can have zero data for a 1-bit in the map, + * a minimask may not! We rely on this in the implementation. */ +struct minimask { + struct miniflow masks; +}; + +void minimask_init(struct minimask *, const struct flow_wildcards *); +struct minimask * minimask_create(const struct flow_wildcards *); +void minimask_combine(struct minimask *dst, + const struct minimask *a, const struct minimask *b, + uint64_t storage[FLOW_U64S]); + +void minimask_expand(const struct minimask *, struct flow_wildcards *); + +static inline uint32_t minimask_get_u32(const struct minimask *, + unsigned int u32_ofs); +static inline ovs_be32 minimask_get_be32(const struct minimask *, + unsigned int be32_ofs); +static inline uint16_t minimask_get_vid_mask(const struct minimask *, size_t); +static inline ovs_be64 minimask_get_metadata_mask(const struct minimask *); + +bool minimask_equal(const struct minimask *a, const struct minimask *b); +bool minimask_has_extra(const struct minimask *, const struct minimask *); + + +/* Returns true if 'mask' matches every packet, false if 'mask' fixes any bits + * or fields. */ +static inline bool +minimask_is_catchall(const struct minimask *mask) +{ + /* For every 1-bit in mask's map, the corresponding value is non-zero, + * so the only way the mask can not fix any bits or fields is for the + * map the be zero. */ + return flowmap_is_empty(mask->masks.map); +} + +/* Returns the uint64_t that would be at byte offset '8 * u64_ofs' if 'flow' + * were expanded into a "struct flow". */ +static inline uint64_t miniflow_get(const struct miniflow *flow, + unsigned int u64_ofs) +{ + return MINIFLOW_IN_MAP(flow, u64_ofs) ? *miniflow_get__(flow, u64_ofs) : 0; +} + +static inline uint32_t miniflow_get_u32(const struct miniflow *flow, + unsigned int u32_ofs) +{ + uint64_t value = miniflow_get(flow, u32_ofs / 2); + +#if WORDS_BIGENDIAN + return (u32_ofs & 1) ? value : value >> 32; +#else + return (u32_ofs & 1) ? value >> 32 : value; +#endif +} + +static inline ovs_be32 miniflow_get_be32(const struct miniflow *flow, + unsigned int be32_ofs) +{ + return (OVS_FORCE ovs_be32)miniflow_get_u32(flow, be32_ofs); +} + +/* Returns the VID within the vlan_tci member of the "struct flow" represented + * by 'flow'. */ +static inline uint16_t +miniflow_get_vid(const struct miniflow *flow, size_t n) +{ + if (n < FLOW_MAX_VLAN_HEADERS) { + union flow_vlan_hdr hdr = { + .qtag = MINIFLOW_GET_BE32(flow, vlans[n].qtag) + }; + return vlan_tci_to_vid(hdr.tci); + } + return 0; +} + +/* Returns the uint32_t that would be at byte offset '4 * u32_ofs' if 'mask' + * were expanded into a "struct flow_wildcards". */ +static inline uint32_t +minimask_get_u32(const struct minimask *mask, unsigned int u32_ofs) +{ + return miniflow_get_u32(&mask->masks, u32_ofs); +} + +static inline ovs_be32 +minimask_get_be32(const struct minimask *mask, unsigned int be32_ofs) +{ + return (OVS_FORCE ovs_be32)minimask_get_u32(mask, be32_ofs); +} + +/* Returns the VID mask within the vlan_tci member of the "struct + * flow_wildcards" represented by 'mask'. */ +static inline uint16_t +minimask_get_vid_mask(const struct minimask *mask, size_t n) +{ + return miniflow_get_vid(&mask->masks, n); +} + +/* Returns the value of the "tcp_flags" field in 'flow'. */ +static inline uint16_t +miniflow_get_tcp_flags(const struct miniflow *flow) +{ + return ntohs(MINIFLOW_GET_BE16(flow, tcp_flags)); +} + +/* Returns the value of the OpenFlow 1.1+ "metadata" field in 'flow'. */ +static inline ovs_be64 +miniflow_get_metadata(const struct miniflow *flow) +{ + return MINIFLOW_GET_BE64(flow, metadata); +} + +/* Returns the bitmap that indicates which tunnel metadata fields are present + * in 'flow'. */ +static inline uint64_t +miniflow_get_tun_metadata_present_map(const struct miniflow *flow) +{ + return MINIFLOW_GET_U64(flow, tunnel.metadata.present.map); +} + +/* Returns the recirc_id in 'flow.' */ +static inline uint32_t +miniflow_get_recirc_id(const struct miniflow *flow) +{ + return MINIFLOW_GET_U32(flow, recirc_id); +} + +/* Returns the dp_hash in 'flow.' */ +static inline uint32_t +miniflow_get_dp_hash(const struct miniflow *flow) +{ + return MINIFLOW_GET_U32(flow, dp_hash); +} + +/* Returns the 'tp_src' and 'tp_dst' fields together as one piece of data. */ +static inline ovs_be32 +miniflow_get_ports(const struct miniflow *flow) +{ + return MINIFLOW_GET_TYPE__(flow, ovs_be32, tp_src); +} + +/* Returns the mask for the OpenFlow 1.1+ "metadata" field in 'mask'. + * + * The return value is all-1-bits if 'mask' matches on the whole value of the + * metadata field, all-0-bits if 'mask' entirely wildcards the metadata field, + * or some other value if the metadata field is partially matched, partially + * wildcarded. */ +static inline ovs_be64 +minimask_get_metadata_mask(const struct minimask *mask) +{ + return MINIFLOW_GET_BE64(&mask->masks, metadata); +} + +/* Perform a bitwise OR of miniflow 'src' flow data specified in 'subset' with + * the equivalent fields in 'dst', storing the result in 'dst'. 'subset' must + * be a subset of 'src's map. */ +static inline void +flow_union_with_miniflow_subset(struct flow *dst, const struct miniflow *src, + struct flowmap subset) +{ + uint64_t *dst_u64 = (uint64_t *) dst; + const uint64_t *p = miniflow_get_values(src); + map_t map; + + FLOWMAP_FOR_EACH_MAP (map, subset) { + size_t idx; + + MAP_FOR_EACH_INDEX(idx, map) { + dst_u64[idx] |= *p++; + } + dst_u64 += MAP_T_BITS; + } +} + +/* Perform a bitwise OR of miniflow 'src' flow data with the equivalent + * fields in 'dst', storing the result in 'dst'. */ +static inline void +flow_union_with_miniflow(struct flow *dst, const struct miniflow *src) +{ + flow_union_with_miniflow_subset(dst, src, src->map); +} + +static inline bool is_ct_valid(const struct flow *flow, + const struct flow_wildcards *mask, + struct flow_wildcards *wc) +{ + /* Matches are checked with 'mask' and without 'wc'. */ + if (mask && !wc) { + /* Must match at least one of the bits that implies a valid + * conntrack entry, or an explicit not-invalid. */ + return flow->ct_state & (CS_NEW | CS_ESTABLISHED | CS_RELATED + | CS_REPLY_DIR | CS_SRC_NAT | CS_DST_NAT) + || (flow->ct_state & CS_TRACKED + && mask->masks.ct_state & CS_INVALID + && !(flow->ct_state & CS_INVALID)); + } + /* Else we are checking a fully extracted flow, where valid CT state always + * has either 'new', 'established', or 'reply_dir' bit set. */ +#define CS_VALID_MASK (CS_NEW | CS_ESTABLISHED | CS_REPLY_DIR) + if (wc) { + wc->masks.ct_state |= CS_VALID_MASK; + } + return flow->ct_state & CS_VALID_MASK; +} + +static inline void +pkt_metadata_from_flow(struct pkt_metadata *md, const struct flow *flow) +{ + /* Update this function whenever struct flow changes. */ + BUILD_ASSERT_DECL(FLOW_WC_SEQ == 42); + + md->recirc_id = flow->recirc_id; + md->dp_hash = flow->dp_hash; + flow_tnl_copy__(&md->tunnel, &flow->tunnel); + md->skb_priority = flow->skb_priority; + md->pkt_mark = flow->pkt_mark; + md->in_port = flow->in_port; + md->ct_state = flow->ct_state; + md->ct_zone = flow->ct_zone; + md->ct_mark = flow->ct_mark; + md->ct_label = flow->ct_label; + + md->ct_orig_tuple_ipv6 = false; + if (flow->dl_type && is_ct_valid(flow, NULL, NULL)) { + if (flow->dl_type == htons(ETH_TYPE_IP)) { + md->ct_orig_tuple.ipv4 = (struct ovs_key_ct_tuple_ipv4) { + flow->ct_nw_src, + flow->ct_nw_dst, + flow->ct_tp_src, + flow->ct_tp_dst, + flow->ct_nw_proto, + }; + } else if (flow->dl_type == htons(ETH_TYPE_IPV6)) { + md->ct_orig_tuple_ipv6 = true; + md->ct_orig_tuple.ipv6 = (struct ovs_key_ct_tuple_ipv6) { + flow->ct_ipv6_src, + flow->ct_ipv6_dst, + flow->ct_tp_src, + flow->ct_tp_dst, + flow->ct_nw_proto, + }; + } else { + /* Reset ct_orig_tuple for other types. */ + memset(&md->ct_orig_tuple, 0, sizeof md->ct_orig_tuple); + } + } else { + memset(&md->ct_orig_tuple, 0, sizeof md->ct_orig_tuple); + } +} + +/* Often, during translation we need to read a value from a flow('FLOW') and + * unwildcard the corresponding bits in the wildcards('WC'). This macro makes + * it easier to do that. */ + +#define FLOW_WC_GET_AND_MASK_WC(FLOW, WC, FIELD) \ + (((WC) ? WC_MASK_FIELD(WC, FIELD) : NULL), ((FLOW)->FIELD)) + +static inline bool is_ethernet(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (wc) { + WC_MASK_FIELD(wc, packet_type); + } + return flow->packet_type == htonl(PT_ETH); +} + +static inline ovs_be16 get_dl_type(const struct flow *flow) +{ + if (flow->packet_type == htonl(PT_ETH)) { + return flow->dl_type; + } else if (pt_ns(flow->packet_type) == OFPHTN_ETHERTYPE) { + return pt_ns_type_be(flow->packet_type); + } else { + return htons(FLOW_DL_TYPE_NONE); + } +} + +static inline bool is_vlan(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (!is_ethernet(flow, wc)) { + return false; + } + if (wc) { + WC_MASK_FIELD_MASK(wc, vlans[0].tci, htons(VLAN_CFI)); + } + return (flow->vlans[0].tci & htons(VLAN_CFI)) != 0; +} + +static inline bool is_ip_any(const struct flow *flow) +{ + return dl_type_is_ip_any(get_dl_type(flow)); +} + +static inline bool is_ip_proto(const struct flow *flow, uint8_t ip_proto, + struct flow_wildcards *wc) +{ + if (is_ip_any(flow)) { + if (wc) { + WC_MASK_FIELD(wc, nw_proto); + } + return flow->nw_proto == ip_proto; + } + return false; +} + +static inline bool is_tcp(const struct flow *flow, + struct flow_wildcards *wc) +{ + return is_ip_proto(flow, IPPROTO_TCP, wc); +} + +static inline bool is_udp(const struct flow *flow, + struct flow_wildcards *wc) +{ + return is_ip_proto(flow, IPPROTO_UDP, wc); +} + +static inline bool is_sctp(const struct flow *flow, + struct flow_wildcards *wc) +{ + return is_ip_proto(flow, IPPROTO_SCTP, wc); +} + +static inline bool is_icmpv4(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (get_dl_type(flow) == htons(ETH_TYPE_IP)) { + if (wc) { + memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); + } + return flow->nw_proto == IPPROTO_ICMP; + } + return false; +} + +static inline bool is_icmpv6(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (get_dl_type(flow) == htons(ETH_TYPE_IPV6)) { + if (wc) { + memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); + } + return flow->nw_proto == IPPROTO_ICMPV6; + } + return false; +} + +static inline bool is_nd(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (is_icmpv6(flow, wc)) { + if (wc) { + memset(&wc->masks.tp_dst, 0xff, sizeof wc->masks.tp_dst); + } + if (flow->tp_dst != htons(0)) { + return false; + } + + if (wc) { + memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); + } + return (flow->tp_src == htons(ND_NEIGHBOR_SOLICIT) || + flow->tp_src == htons(ND_NEIGHBOR_ADVERT)); + } + return false; +} + +static inline bool is_arp(const struct flow *flow) +{ + return (flow->dl_type == htons(ETH_TYPE_ARP)); +} + +static inline bool is_garp(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (is_arp(flow)) { + return (FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_src) == + FLOW_WC_GET_AND_MASK_WC(flow, wc, nw_dst)); + } + + return false; +} + +static inline bool is_igmp(const struct flow *flow, struct flow_wildcards *wc) +{ + if (get_dl_type(flow) == htons(ETH_TYPE_IP)) { + if (wc) { + memset(&wc->masks.nw_proto, 0xff, sizeof wc->masks.nw_proto); + } + return flow->nw_proto == IPPROTO_IGMP; + } + return false; +} + +static inline bool is_mld(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (is_icmpv6(flow, wc)) { + if (wc) { + memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); + } + return (flow->tp_src == htons(MLD_QUERY) + || flow->tp_src == htons(MLD_REPORT) + || flow->tp_src == htons(MLD_DONE) + || flow->tp_src == htons(MLD2_REPORT)); + } + return false; +} + +static inline bool is_mld_query(const struct flow *flow, + struct flow_wildcards *wc) +{ + if (is_icmpv6(flow, wc)) { + if (wc) { + memset(&wc->masks.tp_src, 0xff, sizeof wc->masks.tp_src); + } + return flow->tp_src == htons(MLD_QUERY); + } + return false; +} + +static inline bool is_mld_report(const struct flow *flow, + struct flow_wildcards *wc) +{ + return is_mld(flow, wc) && !is_mld_query(flow, wc); +} + +static inline bool is_stp(const struct flow *flow) +{ + return (flow->dl_type == htons(FLOW_DL_TYPE_NONE) + && eth_addr_equals(flow->dl_dst, eth_addr_stp)); +} + +/* Returns true if flow->tp_dst equals 'port'. If 'wc' is nonnull, sets + * appropriate bits in wc->masks.tp_dst to account for the test. + * + * The caller must already have ensured that 'flow' is a protocol for which + * tp_dst is relevant. */ +static inline bool tp_dst_equals(const struct flow *flow, uint16_t port, + struct flow_wildcards *wc) +{ + uint16_t diff = port ^ ntohs(flow->tp_dst); + if (wc) { + if (diff) { + /* Set mask for the most significant mismatching bit. */ + int ofs = raw_clz64((uint64_t) diff << 48); /* range [0,15] */ + wc->masks.tp_dst |= htons(0x8000 >> ofs); + } else { + /* Must match all bits. */ + wc->masks.tp_dst = OVS_BE16_MAX; + } + } + return !diff; +} + +#endif /* flow.h */ Index: openvswitch-2.17.2/lib/hash.h =================================================================== --- openvswitch-2.17.2.orig/lib/hash.h +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2014, 2016 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 HASH_H -#define HASH_H 1 - -#include -#include -#include -#include -#include "util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -static inline uint32_t -hash_rot(uint32_t x, int k) -{ - return (x << k) | (x >> (32 - k)); -} - -uint32_t hash_bytes(const void *, size_t n_bytes, uint32_t basis); -/* The hash input must be a word larger than 128 bits. */ -void hash_bytes128(const void *_, size_t n_bytes, uint32_t basis, - ovs_u128 *out); - -static inline uint32_t hash_int(uint32_t x, uint32_t basis); -static inline uint32_t hash_2words(uint32_t, uint32_t); -static inline uint32_t hash_uint64(const uint64_t); -static inline uint32_t hash_uint64_basis(const uint64_t x, - const uint32_t basis); -uint32_t hash_3words(uint32_t, uint32_t, uint32_t); - -static inline uint32_t hash_boolean(bool x, uint32_t basis); -uint32_t hash_double(double, uint32_t basis); - -static inline uint32_t hash_pointer(const void *, uint32_t basis); -static inline uint32_t hash_string(const char *, uint32_t basis); - -/* Murmurhash by Austin Appleby, - * from https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp - * - * The upstream license there says: - * - * MurmurHash3 was written by Austin Appleby, and is placed in the public - * domain. The author hereby disclaims copyright to this source code. - * - * See hash_words() for sample usage. */ - -static inline uint32_t mhash_add__(uint32_t hash, uint32_t data) -{ - /* zero-valued 'data' will not change the 'hash' value */ - if (!data) { - return hash; - } - - data *= 0xcc9e2d51; - data = hash_rot(data, 15); - data *= 0x1b873593; - return hash ^ data; -} - -static inline uint32_t mhash_add(uint32_t hash, uint32_t data) -{ - hash = mhash_add__(hash, data); - hash = hash_rot(hash, 13); - return hash * 5 + 0xe6546b64; -} - -static inline uint32_t mhash_finish(uint32_t hash) -{ - hash ^= hash >> 16; - hash *= 0x85ebca6b; - hash ^= hash >> 13; - hash *= 0xc2b2ae35; - hash ^= hash >> 16; - return hash; -} - -static inline uint32_t hash_add(uint32_t hash, uint32_t data); -static inline uint32_t hash_add64(uint32_t hash, uint64_t data); - -static inline uint32_t hash_add_words(uint32_t, const uint32_t *, size_t); -static inline uint32_t hash_add_words64(uint32_t, const uint64_t *, size_t); -static inline uint32_t hash_add_bytes32(uint32_t, const uint32_t *, size_t); -static inline uint32_t hash_add_bytes64(uint32_t, const uint64_t *, size_t); - -#if (defined(__ARM_FEATURE_CRC32) && defined(__aarch64__)) -#include "hash-aarch64.h" - -#elif !(defined(__SSE4_2__) && defined(__x86_64__)) -/* Mhash-based implementation. */ - -static inline uint32_t hash_add(uint32_t hash, uint32_t data) -{ - return mhash_add(hash, data); -} - -static inline uint32_t hash_add64(uint32_t hash, uint64_t data) -{ - return hash_add(hash_add(hash, data), data >> 32); -} - -static inline uint32_t hash_finish(uint32_t hash, uint32_t final) -{ - return mhash_finish(hash ^ final); -} - -/* Returns the hash of the 'n' 32-bit words at 'p', starting from 'basis'. - * 'p' must be properly aligned. - * - * This is inlined for the compiler to have access to the 'n_words', which - * in many cases is a constant. */ -static inline uint32_t -hash_words_inline(const uint32_t *p, size_t n_words, uint32_t basis) -{ - return hash_finish(hash_add_words(basis, p, n_words), n_words * 4); -} - -static inline uint32_t -hash_words64_inline(const uint64_t *p, size_t n_words, uint32_t basis) -{ - return hash_finish(hash_add_words64(basis, p, n_words), n_words * 8); -} - -static inline uint32_t hash_pointer(const void *p, uint32_t basis) -{ - /* Often pointers are hashed simply by casting to integer type, but that - * has pitfalls since the lower bits of a pointer are often all 0 for - * alignment reasons. It's hard to guess where the entropy really is, so - * we give up here and just use a high-quality hash function. - * - * The double cast suppresses a warning on 64-bit systems about casting to - * an integer to different size. That's OK in this case, since most of the - * entropy in the pointer is almost certainly in the lower 32 bits. */ - return hash_int((uint32_t) (uintptr_t) p, basis); -} - -static inline uint32_t hash_2words(uint32_t x, uint32_t y) -{ - return hash_finish(hash_add(hash_add(x, 0), y), 8); -} - -static inline uint32_t hash_uint64_basis(const uint64_t x, - const uint32_t basis) -{ - return hash_finish(hash_add64(basis, x), 8); -} - -static inline uint32_t hash_uint64(const uint64_t x) -{ - return hash_uint64_basis(x, 0); -} - -#else /* __SSE4_2__ && __x86_64__ */ -#include - -static inline uint32_t hash_add(uint32_t hash, uint32_t data) -{ - return _mm_crc32_u32(hash, data); -} - -/* Add the halves of 'data' in the memory order. */ -static inline uint32_t hash_add64(uint32_t hash, uint64_t data) -{ - return _mm_crc32_u64(hash, data); -} - -static inline uint32_t hash_finish(uint64_t hash, uint64_t final) -{ - /* The finishing multiplier 0x805204f3 has been experimentally - * derived to pass the testsuite hash tests. */ - hash = _mm_crc32_u64(hash, final) * 0x805204f3; - return hash ^ (uint32_t)hash >> 16; /* Increase entropy in LSBs. */ -} - -/* Returns the hash of the 'n' 32-bit words at 'p_', starting from 'basis'. - * We access 'p_' as a uint64_t pointer, which is fine for __SSE_4_2__. - * - * This is inlined for the compiler to have access to the 'n_words', which - * in many cases is a constant. */ -static inline uint32_t -hash_words_inline(const uint32_t p_[], size_t n_words, uint32_t basis) -{ - const uint64_t *p = (const void *)p_; - uint64_t hash1 = basis; - uint64_t hash2 = 0; - uint64_t hash3 = n_words; - const uint32_t *endp = (const uint32_t *)p + n_words; - const uint64_t *limit = p + n_words / 2 - 3; - - while (p <= limit) { - hash1 = _mm_crc32_u64(hash1, p[0]); - hash2 = _mm_crc32_u64(hash2, p[1]); - hash3 = _mm_crc32_u64(hash3, p[2]); - p += 3; - } - switch (endp - (const uint32_t *)p) { - case 1: - hash1 = _mm_crc32_u32(hash1, *(const uint32_t *)&p[0]); - break; - case 2: - hash1 = _mm_crc32_u64(hash1, p[0]); - break; - case 3: - hash1 = _mm_crc32_u64(hash1, p[0]); - hash2 = _mm_crc32_u32(hash2, *(const uint32_t *)&p[1]); - break; - case 4: - hash1 = _mm_crc32_u64(hash1, p[0]); - hash2 = _mm_crc32_u64(hash2, p[1]); - break; - case 5: - hash1 = _mm_crc32_u64(hash1, p[0]); - hash2 = _mm_crc32_u64(hash2, p[1]); - hash3 = _mm_crc32_u32(hash3, *(const uint32_t *)&p[2]); - break; - } - return hash_finish(hash1, hash2 << 32 | hash3); -} - -/* A simpler version for 64-bit data. - * 'n_words' is the count of 64-bit words, basis is 64 bits. */ -static inline uint32_t -hash_words64_inline(const uint64_t *p, size_t n_words, uint32_t basis) -{ - uint64_t hash1 = basis; - uint64_t hash2 = 0; - uint64_t hash3 = n_words; - const uint64_t *endp = p + n_words; - const uint64_t *limit = endp - 3; - - while (p <= limit) { - hash1 = _mm_crc32_u64(hash1, p[0]); - hash2 = _mm_crc32_u64(hash2, p[1]); - hash3 = _mm_crc32_u64(hash3, p[2]); - p += 3; - } - switch (endp - p) { - case 1: - hash1 = _mm_crc32_u64(hash1, p[0]); - break; - case 2: - hash1 = _mm_crc32_u64(hash1, p[0]); - hash2 = _mm_crc32_u64(hash2, p[1]); - break; - } - return hash_finish(hash1, hash2 << 32 | hash3); -} - -static inline uint32_t hash_uint64_basis(const uint64_t x, - const uint32_t basis) -{ - /* '23' chosen to mix bits enough for the test-hash to pass. */ - return hash_finish(hash_add64(basis, x), 23); -} - -static inline uint32_t hash_uint64(const uint64_t x) -{ - return hash_uint64_basis(x, 0); -} - -static inline uint32_t hash_2words(uint32_t x, uint32_t y) -{ - return hash_uint64((uint64_t)y << 32 | x); -} - -static inline uint32_t hash_pointer(const void *p, uint32_t basis) -{ - return hash_uint64_basis((uint64_t) (uintptr_t) p, basis); -} -#endif - -uint32_t hash_words__(const uint32_t *p, size_t n_words, uint32_t basis); -uint32_t hash_words64__(const uint64_t *p, size_t n_words, uint32_t basis); - -/* Inline the larger hash functions only when 'n_words' is known to be - * compile-time constant. */ -#if __GNUC__ >= 4 -static inline uint32_t -hash_words(const uint32_t *p, size_t n_words, uint32_t basis) -{ - if (__builtin_constant_p(n_words)) { - return hash_words_inline(p, n_words, basis); - } else { - return hash_words__(p, n_words, basis); - } -} - -static inline uint32_t -hash_words64(const uint64_t *p, size_t n_words, uint32_t basis) -{ - if (__builtin_constant_p(n_words)) { - return hash_words64_inline(p, n_words, basis); - } else { - return hash_words64__(p, n_words, basis); - } -} - -#else - -static inline uint32_t -hash_words(const uint32_t *p, size_t n_words, uint32_t basis) -{ - return hash_words__(p, n_words, basis); -} - -static inline uint32_t -hash_words64(const uint64_t *p, size_t n_words, uint32_t basis) -{ - return hash_words64__(p, n_words, basis); -} -#endif - -static inline uint32_t -hash_bytes32(const uint32_t *p, size_t n_bytes, uint32_t basis) -{ - return hash_words(p, n_bytes / 4, basis); -} - -static inline uint32_t -hash_bytes64(const uint64_t *p, size_t n_bytes, uint32_t basis) -{ - return hash_words64(p, n_bytes / 8, basis); -} - -static inline uint32_t hash_string(const char *s, uint32_t basis) -{ - return hash_bytes(s, strlen(s), basis); -} - -static inline uint32_t hash_int(uint32_t x, uint32_t basis) -{ - return hash_2words(x, basis); -} - -/* An attempt at a useful 1-bit hash function. Has not been analyzed for - * quality. */ -static inline uint32_t hash_boolean(bool x, uint32_t basis) -{ - const uint32_t P0 = 0xc2b73583; /* This is hash_int(1, 0). */ - const uint32_t P1 = 0xe90f1258; /* This is hash_int(2, 0). */ - return (x ? P0 : P1) ^ hash_rot(basis, 1); -} - -/* Helper functions for calling hash_add() for several 32- or 64-bit words in a - * buffer. These are not hash functions by themselves, since they need - * hash_finish() to be called, so if you are looking for a full hash function - * see hash_words(), etc. */ - -static inline uint32_t -hash_add_words(uint32_t hash, const uint32_t *p, size_t n_words) -{ - for (size_t i = 0; i < n_words; i++) { - hash = hash_add(hash, p[i]); - } - return hash; -} - -static inline uint32_t -hash_add_words64(uint32_t hash, const uint64_t *p, size_t n_words) -{ - for (size_t i = 0; i < n_words; i++) { - hash = hash_add64(hash, p[i]); - } - return hash; -} - -static inline uint32_t -hash_add_bytes32(uint32_t hash, const uint32_t *p, size_t n_bytes) -{ - return hash_add_words(hash, p, n_bytes / 4); -} - -static inline uint32_t -hash_add_bytes64(uint32_t hash, const uint64_t *p, size_t n_bytes) -{ - return hash_add_words64(hash, p, n_bytes / 8); -} - -#ifdef __cplusplus -} -#endif - -#endif /* hash.h */ Index: openvswitch-2.17.2/include/internal/hash.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/hash.h @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2012, 2013, 2014, 2016 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 HASH_H +#define HASH_H 1 + +#include +#include +#include +#include +#include "internal/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +static inline uint32_t +hash_rot(uint32_t x, int k) +{ + return (x << k) | (x >> (32 - k)); +} + +uint32_t hash_bytes(const void *, size_t n_bytes, uint32_t basis); +/* The hash input must be a word larger than 128 bits. */ +void hash_bytes128(const void *_, size_t n_bytes, uint32_t basis, + ovs_u128 *out); + +static inline uint32_t hash_int(uint32_t x, uint32_t basis); +static inline uint32_t hash_2words(uint32_t, uint32_t); +static inline uint32_t hash_uint64(const uint64_t); +static inline uint32_t hash_uint64_basis(const uint64_t x, + const uint32_t basis); +uint32_t hash_3words(uint32_t, uint32_t, uint32_t); + +static inline uint32_t hash_boolean(bool x, uint32_t basis); +uint32_t hash_double(double, uint32_t basis); + +static inline uint32_t hash_pointer(const void *, uint32_t basis); +static inline uint32_t hash_string(const char *, uint32_t basis); + +/* Murmurhash by Austin Appleby, + * from https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp + * + * The upstream license there says: + * + * MurmurHash3 was written by Austin Appleby, and is placed in the public + * domain. The author hereby disclaims copyright to this source code. + * + * See hash_words() for sample usage. */ + +static inline uint32_t mhash_add__(uint32_t hash, uint32_t data) +{ + /* zero-valued 'data' will not change the 'hash' value */ + if (!data) { + return hash; + } + + data *= 0xcc9e2d51; + data = hash_rot(data, 15); + data *= 0x1b873593; + return hash ^ data; +} + +static inline uint32_t mhash_add(uint32_t hash, uint32_t data) +{ + hash = mhash_add__(hash, data); + hash = hash_rot(hash, 13); + return hash * 5 + 0xe6546b64; +} + +static inline uint32_t mhash_finish(uint32_t hash) +{ + hash ^= hash >> 16; + hash *= 0x85ebca6b; + hash ^= hash >> 13; + hash *= 0xc2b2ae35; + hash ^= hash >> 16; + return hash; +} + +static inline uint32_t hash_add(uint32_t hash, uint32_t data); +static inline uint32_t hash_add64(uint32_t hash, uint64_t data); + +static inline uint32_t hash_add_words(uint32_t, const uint32_t *, size_t); +static inline uint32_t hash_add_words64(uint32_t, const uint64_t *, size_t); +static inline uint32_t hash_add_bytes32(uint32_t, const uint32_t *, size_t); +static inline uint32_t hash_add_bytes64(uint32_t, const uint64_t *, size_t); + +#if (defined(__ARM_FEATURE_CRC32) && defined(__aarch64__)) +#include "internal/hash-aarch64.h" + +#elif !(defined(__SSE4_2__) && defined(__x86_64__)) +/* Mhash-based implementation. */ + +static inline uint32_t hash_add(uint32_t hash, uint32_t data) +{ + return mhash_add(hash, data); +} + +static inline uint32_t hash_add64(uint32_t hash, uint64_t data) +{ + return hash_add(hash_add(hash, data), data >> 32); +} + +static inline uint32_t hash_finish(uint32_t hash, uint32_t final) +{ + return mhash_finish(hash ^ final); +} + +/* Returns the hash of the 'n' 32-bit words at 'p', starting from 'basis'. + * 'p' must be properly aligned. + * + * This is inlined for the compiler to have access to the 'n_words', which + * in many cases is a constant. */ +static inline uint32_t +hash_words_inline(const uint32_t *p, size_t n_words, uint32_t basis) +{ + return hash_finish(hash_add_words(basis, p, n_words), n_words * 4); +} + +static inline uint32_t +hash_words64_inline(const uint64_t *p, size_t n_words, uint32_t basis) +{ + return hash_finish(hash_add_words64(basis, p, n_words), n_words * 8); +} + +static inline uint32_t hash_pointer(const void *p, uint32_t basis) +{ + /* Often pointers are hashed simply by casting to integer type, but that + * has pitfalls since the lower bits of a pointer are often all 0 for + * alignment reasons. It's hard to guess where the entropy really is, so + * we give up here and just use a high-quality hash function. + * + * The double cast suppresses a warning on 64-bit systems about casting to + * an integer to different size. That's OK in this case, since most of the + * entropy in the pointer is almost certainly in the lower 32 bits. */ + return hash_int((uint32_t) (uintptr_t) p, basis); +} + +static inline uint32_t hash_2words(uint32_t x, uint32_t y) +{ + return hash_finish(hash_add(hash_add(x, 0), y), 8); +} + +static inline uint32_t hash_uint64_basis(const uint64_t x, + const uint32_t basis) +{ + return hash_finish(hash_add64(basis, x), 8); +} + +static inline uint32_t hash_uint64(const uint64_t x) +{ + return hash_uint64_basis(x, 0); +} + +#else /* __SSE4_2__ && __x86_64__ */ +#include + +static inline uint32_t hash_add(uint32_t hash, uint32_t data) +{ + return _mm_crc32_u32(hash, data); +} + +/* Add the halves of 'data' in the memory order. */ +static inline uint32_t hash_add64(uint32_t hash, uint64_t data) +{ + return _mm_crc32_u64(hash, data); +} + +static inline uint32_t hash_finish(uint64_t hash, uint64_t final) +{ + /* The finishing multiplier 0x805204f3 has been experimentally + * derived to pass the testsuite hash tests. */ + hash = _mm_crc32_u64(hash, final) * 0x805204f3; + return hash ^ (uint32_t)hash >> 16; /* Increase entropy in LSBs. */ +} + +/* Returns the hash of the 'n' 32-bit words at 'p_', starting from 'basis'. + * We access 'p_' as a uint64_t pointer, which is fine for __SSE_4_2__. + * + * This is inlined for the compiler to have access to the 'n_words', which + * in many cases is a constant. */ +static inline uint32_t +hash_words_inline(const uint32_t p_[], size_t n_words, uint32_t basis) +{ + const uint64_t *p = (const void *)p_; + uint64_t hash1 = basis; + uint64_t hash2 = 0; + uint64_t hash3 = n_words; + const uint32_t *endp = (const uint32_t *)p + n_words; + const uint64_t *limit = p + n_words / 2 - 3; + + while (p <= limit) { + hash1 = _mm_crc32_u64(hash1, p[0]); + hash2 = _mm_crc32_u64(hash2, p[1]); + hash3 = _mm_crc32_u64(hash3, p[2]); + p += 3; + } + switch (endp - (const uint32_t *)p) { + case 1: + hash1 = _mm_crc32_u32(hash1, *(const uint32_t *)&p[0]); + break; + case 2: + hash1 = _mm_crc32_u64(hash1, p[0]); + break; + case 3: + hash1 = _mm_crc32_u64(hash1, p[0]); + hash2 = _mm_crc32_u32(hash2, *(const uint32_t *)&p[1]); + break; + case 4: + hash1 = _mm_crc32_u64(hash1, p[0]); + hash2 = _mm_crc32_u64(hash2, p[1]); + break; + case 5: + hash1 = _mm_crc32_u64(hash1, p[0]); + hash2 = _mm_crc32_u64(hash2, p[1]); + hash3 = _mm_crc32_u32(hash3, *(const uint32_t *)&p[2]); + break; + } + return hash_finish(hash1, hash2 << 32 | hash3); +} + +/* A simpler version for 64-bit data. + * 'n_words' is the count of 64-bit words, basis is 64 bits. */ +static inline uint32_t +hash_words64_inline(const uint64_t *p, size_t n_words, uint32_t basis) +{ + uint64_t hash1 = basis; + uint64_t hash2 = 0; + uint64_t hash3 = n_words; + const uint64_t *endp = p + n_words; + const uint64_t *limit = endp - 3; + + while (p <= limit) { + hash1 = _mm_crc32_u64(hash1, p[0]); + hash2 = _mm_crc32_u64(hash2, p[1]); + hash3 = _mm_crc32_u64(hash3, p[2]); + p += 3; + } + switch (endp - p) { + case 1: + hash1 = _mm_crc32_u64(hash1, p[0]); + break; + case 2: + hash1 = _mm_crc32_u64(hash1, p[0]); + hash2 = _mm_crc32_u64(hash2, p[1]); + break; + } + return hash_finish(hash1, hash2 << 32 | hash3); +} + +static inline uint32_t hash_uint64_basis(const uint64_t x, + const uint32_t basis) +{ + /* '23' chosen to mix bits enough for the test-hash to pass. */ + return hash_finish(hash_add64(basis, x), 23); +} + +static inline uint32_t hash_uint64(const uint64_t x) +{ + return hash_uint64_basis(x, 0); +} + +static inline uint32_t hash_2words(uint32_t x, uint32_t y) +{ + return hash_uint64((uint64_t)y << 32 | x); +} + +static inline uint32_t hash_pointer(const void *p, uint32_t basis) +{ + return hash_uint64_basis((uint64_t) (uintptr_t) p, basis); +} +#endif + +uint32_t hash_words__(const uint32_t *p, size_t n_words, uint32_t basis); +uint32_t hash_words64__(const uint64_t *p, size_t n_words, uint32_t basis); + +/* Inline the larger hash functions only when 'n_words' is known to be + * compile-time constant. */ +#if __GNUC__ >= 4 +static inline uint32_t +hash_words(const uint32_t *p, size_t n_words, uint32_t basis) +{ + if (__builtin_constant_p(n_words)) { + return hash_words_inline(p, n_words, basis); + } else { + return hash_words__(p, n_words, basis); + } +} + +static inline uint32_t +hash_words64(const uint64_t *p, size_t n_words, uint32_t basis) +{ + if (__builtin_constant_p(n_words)) { + return hash_words64_inline(p, n_words, basis); + } else { + return hash_words64__(p, n_words, basis); + } +} + +#else + +static inline uint32_t +hash_words(const uint32_t *p, size_t n_words, uint32_t basis) +{ + return hash_words__(p, n_words, basis); +} + +static inline uint32_t +hash_words64(const uint64_t *p, size_t n_words, uint32_t basis) +{ + return hash_words64__(p, n_words, basis); +} +#endif + +static inline uint32_t +hash_bytes32(const uint32_t *p, size_t n_bytes, uint32_t basis) +{ + return hash_words(p, n_bytes / 4, basis); +} + +static inline uint32_t +hash_bytes64(const uint64_t *p, size_t n_bytes, uint32_t basis) +{ + return hash_words64(p, n_bytes / 8, basis); +} + +static inline uint32_t hash_string(const char *s, uint32_t basis) +{ + return hash_bytes(s, strlen(s), basis); +} + +static inline uint32_t hash_int(uint32_t x, uint32_t basis) +{ + return hash_2words(x, basis); +} + +/* An attempt at a useful 1-bit hash function. Has not been analyzed for + * quality. */ +static inline uint32_t hash_boolean(bool x, uint32_t basis) +{ + const uint32_t P0 = 0xc2b73583; /* This is hash_int(1, 0). */ + const uint32_t P1 = 0xe90f1258; /* This is hash_int(2, 0). */ + return (x ? P0 : P1) ^ hash_rot(basis, 1); +} + +/* Helper functions for calling hash_add() for several 32- or 64-bit words in a + * buffer. These are not hash functions by themselves, since they need + * hash_finish() to be called, so if you are looking for a full hash function + * see hash_words(), etc. */ + +static inline uint32_t +hash_add_words(uint32_t hash, const uint32_t *p, size_t n_words) +{ + for (size_t i = 0; i < n_words; i++) { + hash = hash_add(hash, p[i]); + } + return hash; +} + +static inline uint32_t +hash_add_words64(uint32_t hash, const uint64_t *p, size_t n_words) +{ + for (size_t i = 0; i < n_words; i++) { + hash = hash_add64(hash, p[i]); + } + return hash; +} + +static inline uint32_t +hash_add_bytes32(uint32_t hash, const uint32_t *p, size_t n_bytes) +{ + return hash_add_words(hash, p, n_bytes / 4); +} + +static inline uint32_t +hash_add_bytes64(uint32_t hash, const uint64_t *p, size_t n_bytes) +{ + return hash_add_words64(hash, p, n_bytes / 8); +} + +#ifdef __cplusplus +} +#endif + +#endif /* hash.h */ Index: openvswitch-2.17.2/lib/hindex.h =================================================================== --- openvswitch-2.17.2.orig/lib/hindex.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2013, 2016 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 HINDEX_H -#define HINDEX_H 1 - -/* Hashed multimap. - * - * hindex is a hash table data structure that gracefully handles duplicates. - * With a high-quality hash function, insertion, deletion, and search are O(1) - * expected time, regardless of the number of duplicates for a given key. */ - -#include -#include -#include "util.h" - -/* A hash index node, to embed inside the data structure being indexed. - * - * Nodes are linked together like this (the boxes are labeled with hash - * values): - * - * +--------+ d +--------+ d +--------+ d - * bucket---> | 6 |---->| 20 |---->| 15 |---->null - * +-|------+ +-|------+ +-|------+ - * | ^ | | ^ - * s| |d |s s| |d - * V | V V | - * +------|-+ null +------|-+ - * | 6 | | 15 | - * +-|------+ +-|------+ - * | ^ | - * s| |d s| - * V | V - * +------|-+ null - * | 6 | - * +-|------+ - * | - * s| - * V - * null - * - * The basic usage is: - * - * - To visit the unique hash values in the hindex, follow the 'd' - * ("different") pointers starting from each bucket. The nodes visited - * this way are called "head" nodes, because they are at the head of the - * vertical chains. - * - * - To visit the nodes with hash value H, follow the 'd' pointers in the - * appropriate bucket until you find one with hash H, then follow the 's' - * ("same") pointers until you hit a null pointer. The non-head nodes - * visited this way are called "body" nodes. - * - * - The 'd' pointers in body nodes point back to the previous body node - * or, for the first body node, to the head node. (This makes it - * possible to remove a body node without traversing all the way downward - * from the head). - */ -struct hindex_node { - /* Hash value. */ - size_t hash; - - /* In a head node, the next head node (with a hash different from this - * node), or NULL if this is the last node in this bucket. - * - * In a body node, the previous head or body node (with the same hash as - * this node). Never null. */ - struct hindex_node *d; - - /* In a head or a body node, the next body node with the same hash as this - * node. NULL if this is the last node with this hash. */ - struct hindex_node *s; -}; - -/* A hash index. */ -struct hindex { - struct hindex_node **buckets; /* Must point to 'one' iff 'mask' == 0. */ - struct hindex_node *one; - size_t mask; /* 0 or more lowest-order bits set, others cleared. */ - size_t n_unique; /* Number of unique hashes (the number of head nodes). */ -}; - -/* Initializer for an empty hash index. */ -#define HINDEX_INITIALIZER(HINDEX) \ - { (struct hindex_node **const) &(HINDEX)->one, NULL, 0, 0 } - -/* Initialization. */ -void hindex_init(struct hindex *); -void hindex_destroy(struct hindex *); -void hindex_clear(struct hindex *); -void hindex_swap(struct hindex *a, struct hindex *b); -void hindex_moved(struct hindex *hindex); -static inline bool hindex_is_empty(const struct hindex *); - -/* Adjusting capacity. */ -void hindex_expand(struct hindex *); -void hindex_shrink(struct hindex *); -void hindex_reserve(struct hindex *, size_t capacity); - -/* Insertion and deletion. */ -void hindex_insert_fast(struct hindex *, struct hindex_node *, size_t hash); -void hindex_insert(struct hindex *, struct hindex_node *, size_t hash); -void hindex_remove(struct hindex *, struct hindex_node *); - -/* Search. - * - * HINDEX_FOR_EACH_WITH_HASH iterates NODE over all of the nodes in HINDEX that - * have hash value equal to HASH. MEMBER must be the name of the 'struct - * hindex_node' member within NODE. - * - * The loop should not change NODE to point to a different node or insert or - * delete nodes in HINDEX (unless it "break"s out of the loop to terminate - * iteration). - * - * Evaluates HASH only once. - */ -#define HINDEX_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HINDEX) \ - for (INIT_MULTIVAR(NODE, MEMBER, hindex_node_with_hash(HINDEX, HASH), \ - struct hindex_node); \ - CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ - UPDATE_MULTIVAR(NODE, ITER_VAR(NODE)->s)) - -/* Safe when NODE may be freed (not needed when NODE may be removed from the - * hash map but its members remain accessible and intact). */ -#define HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG(NODE, NEXT, MEMBER, HASH, HINDEX) \ - for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \ - hindex_node_with_hash(HINDEX, HASH), \ - struct hindex_node); \ - CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \ - ITER_VAR(NODE) != NULL, \ - ITER_VAR(NEXT) = ITER_VAR(NODE)->s, \ - ITER_VAR(NEXT) != NULL); \ - UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT)) - -/* Short version of HINDEX_FOR_EACH_WITH_HASH_SAFE. */ -#define HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT(NODE, MEMBER, HASH, HINDEX) \ - for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER, \ - hindex_node_with_hash(HINDEX, HASH), \ - struct hindex_node); \ - CONDITION_MULTIVAR_SAFE_SHORT(NODE, MEMBER, \ - ITER_VAR(NODE) != NULL, \ - ITER_NEXT_VAR(NODE) = ITER_VAR(NODE)->s); \ - UPDATE_MULTIVAR_SAFE_SHORT(NODE)) - -#define HINDEX_FOR_EACH_WITH_HASH_SAFE(...) \ - OVERLOAD_SAFE_MACRO(HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG, \ - HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT, \ - 5, __VA_ARGS__) - - -/* Returns the head node in 'hindex' with the given 'hash', or a null pointer - * if no nodes have that hash value. */ -static inline struct hindex_node * -hindex_node_with_hash(const struct hindex *hindex, size_t hash) -{ - struct hindex_node *node = hindex->buckets[hash & hindex->mask]; - - while (node && node->hash != hash) { - node = node->d; - } - return node; -} - -/* Iteration. */ - -/* Iterates through every node in HINDEX. */ -#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX) \ - for (INIT_MULTIVAR(NODE, MEMBER, hindex_first(HINDEX), \ - struct hindex_node); \ - CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ - UPDATE_MULTIVAR(NODE, hindex_next(HINDEX, ITER_VAR(NODE)))) - -/* Safe when NODE may be freed (not needed when NODE may be removed from the - * hash index but its members remain accessible and intact). */ -#define HINDEX_FOR_EACH_SAFE_LONG(NODE, NEXT, MEMBER, HINDEX) \ - for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, hindex_first(HINDEX), \ - struct hindex_node); \ - CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \ - ITER_VAR(NODE) != NULL, \ - ITER_VAR(NEXT) = hindex_next(HINDEX, ITER_VAR(NODE)), \ - ITER_VAR(NEXT) != NULL); \ - UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT)) - -/* Short version of HINDEX_FOR_EACH_SAFE. */ -#define HINDEX_FOR_EACH_SAFE_SHORT(NODE, MEMBER, HINDEX) \ - for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER, hindex_first(HINDEX), \ - struct hindex_node); \ - CONDITION_MULTIVAR_SAFE_SHORT(NODE, MEMBER, \ - ITER_VAR(NODE) != NULL, \ - ITER_NEXT_VAR(NODE) = hindex_next(HINDEX, ITER_VAR(NODE))); \ - UPDATE_MULTIVAR_SAFE_SHORT(NODE)) - -#define HINDEX_FOR_EACH_SAFE(...) \ - OVERLOAD_SAFE_MACRO(HINDEX_FOR_EACH_SAFE_LONG, \ - HINDEX_FOR_EACH_SAFE_SHORT, \ - 4, __VA_ARGS__) - -struct hindex_node *hindex_first(const struct hindex *); -struct hindex_node *hindex_next(const struct hindex *, - const struct hindex_node *); - -/* Returns true if 'hindex' currently contains no nodes, false otherwise. */ -static inline bool -hindex_is_empty(const struct hindex *hindex) -{ - return hindex->n_unique == 0; -} - -#endif /* hindex.h */ Index: openvswitch-2.17.2/include/internal/hindex.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/hindex.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2013, 2016 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 HINDEX_H +#define HINDEX_H 1 + +/* Hashed multimap. + * + * hindex is a hash table data structure that gracefully handles duplicates. + * With a high-quality hash function, insertion, deletion, and search are O(1) + * expected time, regardless of the number of duplicates for a given key. */ + +#include +#include +#include "internal/util.h" + +/* A hash index node, to embed inside the data structure being indexed. + * + * Nodes are linked together like this (the boxes are labeled with hash + * values): + * + * +--------+ d +--------+ d +--------+ d + * bucket---> | 6 |---->| 20 |---->| 15 |---->null + * +-|------+ +-|------+ +-|------+ + * | ^ | | ^ + * s| |d |s s| |d + * V | V V | + * +------|-+ null +------|-+ + * | 6 | | 15 | + * +-|------+ +-|------+ + * | ^ | + * s| |d s| + * V | V + * +------|-+ null + * | 6 | + * +-|------+ + * | + * s| + * V + * null + * + * The basic usage is: + * + * - To visit the unique hash values in the hindex, follow the 'd' + * ("different") pointers starting from each bucket. The nodes visited + * this way are called "head" nodes, because they are at the head of the + * vertical chains. + * + * - To visit the nodes with hash value H, follow the 'd' pointers in the + * appropriate bucket until you find one with hash H, then follow the 's' + * ("same") pointers until you hit a null pointer. The non-head nodes + * visited this way are called "body" nodes. + * + * - The 'd' pointers in body nodes point back to the previous body node + * or, for the first body node, to the head node. (This makes it + * possible to remove a body node without traversing all the way downward + * from the head). + */ +struct hindex_node { + /* Hash value. */ + size_t hash; + + /* In a head node, the next head node (with a hash different from this + * node), or NULL if this is the last node in this bucket. + * + * In a body node, the previous head or body node (with the same hash as + * this node). Never null. */ + struct hindex_node *d; + + /* In a head or a body node, the next body node with the same hash as this + * node. NULL if this is the last node with this hash. */ + struct hindex_node *s; +}; + +/* A hash index. */ +struct hindex { + struct hindex_node **buckets; /* Must point to 'one' iff 'mask' == 0. */ + struct hindex_node *one; + size_t mask; /* 0 or more lowest-order bits set, others cleared. */ + size_t n_unique; /* Number of unique hashes (the number of head nodes). */ +}; + +/* Initializer for an empty hash index. */ +#define HINDEX_INITIALIZER(HINDEX) \ + { (struct hindex_node **const) &(HINDEX)->one, NULL, 0, 0 } + +/* Initialization. */ +void hindex_init(struct hindex *); +void hindex_destroy(struct hindex *); +void hindex_clear(struct hindex *); +void hindex_swap(struct hindex *a, struct hindex *b); +void hindex_moved(struct hindex *hindex); +static inline bool hindex_is_empty(const struct hindex *); + +/* Adjusting capacity. */ +void hindex_expand(struct hindex *); +void hindex_shrink(struct hindex *); +void hindex_reserve(struct hindex *, size_t capacity); + +/* Insertion and deletion. */ +void hindex_insert_fast(struct hindex *, struct hindex_node *, size_t hash); +void hindex_insert(struct hindex *, struct hindex_node *, size_t hash); +void hindex_remove(struct hindex *, struct hindex_node *); + +/* Search. + * + * HINDEX_FOR_EACH_WITH_HASH iterates NODE over all of the nodes in HINDEX that + * have hash value equal to HASH. MEMBER must be the name of the 'struct + * hindex_node' member within NODE. + * + * The loop should not change NODE to point to a different node or insert or + * delete nodes in HINDEX (unless it "break"s out of the loop to terminate + * iteration). + * + * Evaluates HASH only once. + */ +#define HINDEX_FOR_EACH_WITH_HASH(NODE, MEMBER, HASH, HINDEX) \ + for (INIT_MULTIVAR(NODE, MEMBER, hindex_node_with_hash(HINDEX, HASH), \ + struct hindex_node); \ + CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ + UPDATE_MULTIVAR(NODE, ITER_VAR(NODE)->s)) + +/* Safe when NODE may be freed (not needed when NODE may be removed from the + * hash map but its members remain accessible and intact). */ +#define HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG(NODE, NEXT, MEMBER, HASH, HINDEX) \ + for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \ + hindex_node_with_hash(HINDEX, HASH), \ + struct hindex_node); \ + CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \ + ITER_VAR(NODE) != NULL, \ + ITER_VAR(NEXT) = ITER_VAR(NODE)->s, \ + ITER_VAR(NEXT) != NULL); \ + UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT)) + +/* Short version of HINDEX_FOR_EACH_WITH_HASH_SAFE. */ +#define HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT(NODE, MEMBER, HASH, HINDEX) \ + for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER, \ + hindex_node_with_hash(HINDEX, HASH), \ + struct hindex_node); \ + CONDITION_MULTIVAR_SAFE_SHORT(NODE, MEMBER, \ + ITER_VAR(NODE) != NULL, \ + ITER_NEXT_VAR(NODE) = ITER_VAR(NODE)->s); \ + UPDATE_MULTIVAR_SAFE_SHORT(NODE)) + +#define HINDEX_FOR_EACH_WITH_HASH_SAFE(...) \ + OVERLOAD_SAFE_MACRO(HINDEX_FOR_EACH_WITH_HASH_SAFE_LONG, \ + HINDEX_FOR_EACH_WITH_HASH_SAFE_SHORT, \ + 5, __VA_ARGS__) + + +/* Returns the head node in 'hindex' with the given 'hash', or a null pointer + * if no nodes have that hash value. */ +static inline struct hindex_node * +hindex_node_with_hash(const struct hindex *hindex, size_t hash) +{ + struct hindex_node *node = hindex->buckets[hash & hindex->mask]; + + while (node && node->hash != hash) { + node = node->d; + } + return node; +} + +/* Iteration. */ + +/* Iterates through every node in HINDEX. */ +#define HINDEX_FOR_EACH(NODE, MEMBER, HINDEX) \ + for (INIT_MULTIVAR(NODE, MEMBER, hindex_first(HINDEX), \ + struct hindex_node); \ + CONDITION_MULTIVAR(NODE, MEMBER, ITER_VAR(NODE) != NULL); \ + UPDATE_MULTIVAR(NODE, hindex_next(HINDEX, ITER_VAR(NODE)))) + +/* Safe when NODE may be freed (not needed when NODE may be removed from the + * hash index but its members remain accessible and intact). */ +#define HINDEX_FOR_EACH_SAFE_LONG(NODE, NEXT, MEMBER, HINDEX) \ + for (INIT_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, hindex_first(HINDEX), \ + struct hindex_node); \ + CONDITION_MULTIVAR_SAFE_LONG(NODE, NEXT, MEMBER, \ + ITER_VAR(NODE) != NULL, \ + ITER_VAR(NEXT) = hindex_next(HINDEX, ITER_VAR(NODE)), \ + ITER_VAR(NEXT) != NULL); \ + UPDATE_MULTIVAR_SAFE_LONG(NODE, NEXT)) + +/* Short version of HINDEX_FOR_EACH_SAFE. */ +#define HINDEX_FOR_EACH_SAFE_SHORT(NODE, MEMBER, HINDEX) \ + for (INIT_MULTIVAR_SAFE_SHORT(NODE, MEMBER, hindex_first(HINDEX), \ + struct hindex_node); \ + CONDITION_MULTIVAR_SAFE_SHORT(NODE, MEMBER, \ + ITER_VAR(NODE) != NULL, \ + ITER_NEXT_VAR(NODE) = hindex_next(HINDEX, ITER_VAR(NODE))); \ + UPDATE_MULTIVAR_SAFE_SHORT(NODE)) + +#define HINDEX_FOR_EACH_SAFE(...) \ + OVERLOAD_SAFE_MACRO(HINDEX_FOR_EACH_SAFE_LONG, \ + HINDEX_FOR_EACH_SAFE_SHORT, \ + 4, __VA_ARGS__) + +struct hindex_node *hindex_first(const struct hindex *); +struct hindex_node *hindex_next(const struct hindex *, + const struct hindex_node *); + +/* Returns true if 'hindex' currently contains no nodes, false otherwise. */ +static inline bool +hindex_is_empty(const struct hindex *hindex) +{ + return hindex->n_unique == 0; +} + +#endif /* hindex.h */ Index: openvswitch-2.17.2/lib/latch.h =================================================================== --- openvswitch-2.17.2.orig/lib/latch.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2013 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef LATCH_H -#define LATCH_H 1 - -/* A thread-safe, signal-safe, pollable doorbell. - * - * This is a thin wrapper around a pipe that allows threads to notify each - * other that an event has occurred in a signal-safe way */ - -#include -#include "util.h" - -struct latch { -#ifndef _WIN32 - int fds[2]; -#else - HANDLE wevent; - bool is_set; -#endif -}; - -void latch_init(struct latch *); -void latch_destroy(struct latch *); - -bool latch_poll(struct latch *); -void latch_set(struct latch *); - -bool latch_is_set(const struct latch *); -void latch_wait_at(const struct latch *, const char *where); -#define latch_wait(latch) latch_wait_at(latch, OVS_SOURCE_LOCATOR) - -#endif /* latch.h */ Index: openvswitch-2.17.2/include/internal/latch.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/latch.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LATCH_H +#define LATCH_H 1 + +/* A thread-safe, signal-safe, pollable doorbell. + * + * This is a thin wrapper around a pipe that allows threads to notify each + * other that an event has occurred in a signal-safe way */ + +#include +#include "internal/util.h" + +struct latch { +#ifndef _WIN32 + int fds[2]; +#else + HANDLE wevent; + bool is_set; +#endif +}; + +void latch_init(struct latch *); +void latch_destroy(struct latch *); + +bool latch_poll(struct latch *); +void latch_set(struct latch *); + +bool latch_is_set(const struct latch *); +void latch_wait_at(const struct latch *, const char *where); +#define latch_wait(latch) latch_wait_at(latch, OVS_SOURCE_LOCATOR) + +#endif /* latch.h */ Index: openvswitch-2.17.2/lib/mcast-snooping.h =================================================================== --- openvswitch-2.17.2.orig/lib/mcast-snooping.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (c) 2014 Red Hat, Inc. - * - * Based on mac-learning implementation. - * - * 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 MCAST_SNOOPING_H -#define MCAST_SNOOPING_H 1 - -#include -#include "dp-packet.h" -#include "openvswitch/hmap.h" -#include "openvswitch/list.h" -#include "ovs-atomic.h" -#include "ovs-thread.h" -#include "packets.h" -#include "timeval.h" - -struct mcast_snooping; - -/* Default maximum size of a mcast snooping table, in entries. */ -#define MCAST_DEFAULT_MAX_ENTRIES 2048 - -/* Time, in seconds, before expiring a mcast_group due to inactivity. */ -#define MCAST_ENTRY_DEFAULT_IDLE_TIME 300 - -/* Time, in seconds, before expiring a mrouter_port due to inactivity. */ -#define MCAST_MROUTER_PORT_IDLE_TIME 180 - -/* Multicast group entry. - * Guarded by owning 'mcast_snooping''s rwlock. */ -struct mcast_group { - /* Node in parent struct mcast_snooping hmap. */ - struct hmap_node hmap_node; - - /* Multicast group IPv6/IPv4 address. */ - struct in6_addr addr; - - /* VLAN tag. */ - uint16_t vlan; - - /* Node in parent struct mcast_snooping group_lru. */ - struct ovs_list group_node OVS_GUARDED; - - /* Contains struct mcast_group_bundle (ports), least recently used - * at the front, most recently used at the back. */ - struct ovs_list bundle_lru OVS_GUARDED; -}; - -/* The bundle associated to the multicast group. - * Guarded by owning 'mcast_snooping''s rwlock. */ -struct mcast_group_bundle { - /* Node in parent struct mcast_group bundle_lru list. */ - struct ovs_list bundle_node OVS_GUARDED; - - /* When this node expires. */ - time_t expires; - - /* Learned port. */ - void *port OVS_GUARDED; -}; - -/* The bundle connected to a multicast router. - * Guarded by owning 'mcast_snooping''s rwlock. */ -struct mcast_mrouter_bundle { - /* Node in parent struct mcast_group mrouter_lru list. */ - struct ovs_list mrouter_node OVS_GUARDED; - - /* When this node expires. */ - time_t expires; - - /* VLAN tag. */ - uint16_t vlan; - - /* Learned port. */ - void *port OVS_GUARDED; -}; - -/* The bundle to send multicast traffic or Reports. - * Guarded by owning 'mcast_snooping''s rwlock */ -struct mcast_port_bundle { - /* Node in parent struct mcast_snooping. */ - struct ovs_list node; - - /* VLAN tag. */ - uint16_t vlan; - - /* Learned port. */ - void *port; -}; - -/* Multicast snooping table. */ -struct mcast_snooping { - /* Snooping/learning table. */ - struct hmap table; - - /* Contains struct mcast_group, least recently used at the front, - * most recently used at the back. */ - struct ovs_list group_lru OVS_GUARDED; - - /* Contains struct mcast_mrouter_bundle, least recently used at the - * front, most recently used at the back. */ - struct ovs_list mrouter_lru OVS_GUARDED; - - /* Contains struct mcast_port_bundle to be flooded with multicast - * packets in no special order. */ - struct ovs_list fport_list OVS_GUARDED; - - /* Contains struct mcast_port_bundle to forward Reports in - * no special order. */ - struct ovs_list rport_list OVS_GUARDED; - - /* Secret for randomizing hash table. */ - uint32_t secret; - - /* Maximum age before deleting an entry. */ - unsigned int idle_time; - - /* Maximum number of multicast groups learned. */ - size_t max_entries; - - /* True if flow revalidation is needed. */ - bool need_revalidate; - - /* True if unregistered multicast packets should be flooded to all - * ports, otherwise send them to ports connected to multicast routers. */ - bool flood_unreg; - - struct ovs_refcount ref_cnt; - struct ovs_rwlock rwlock; -}; - -/* Basics. */ -bool mcast_snooping_enabled(const struct mcast_snooping *ms); -bool mcast_snooping_flood_unreg(const struct mcast_snooping *ms); -int mcast_mrouter_age(const struct mcast_snooping *ms, - const struct mcast_mrouter_bundle *m); -int mcast_bundle_age(const struct mcast_snooping *ms, - const struct mcast_group_bundle *b); -struct mcast_snooping *mcast_snooping_create(void); -struct mcast_snooping *mcast_snooping_ref(const struct mcast_snooping *); -void mcast_snooping_unref(struct mcast_snooping *); -bool mcast_snooping_run(struct mcast_snooping *ms); -void mcast_snooping_wait(struct mcast_snooping *ms); - -/* Configuration. */ -void mcast_snooping_set_idle_time(struct mcast_snooping *ms, - unsigned int idle_time) - OVS_REQ_WRLOCK(ms->rwlock); -void mcast_snooping_set_max_entries(struct mcast_snooping *ms, - size_t max_entries) - OVS_REQ_WRLOCK(ms->rwlock); -bool -mcast_snooping_set_flood_unreg(struct mcast_snooping *ms, bool enable) - OVS_REQ_WRLOCK(ms->rwlock); -void mcast_snooping_set_port_flood(struct mcast_snooping *ms, void *port, - bool flood) - OVS_REQ_WRLOCK(ms->rwlock); -void mcast_snooping_set_port_flood_reports(struct mcast_snooping *ms, - void *port, bool flood) - OVS_REQ_WRLOCK(ms->rwlock); - -/* Lookup. */ -struct mcast_group * -mcast_snooping_lookup(const struct mcast_snooping *ms, - const struct in6_addr *dip, uint16_t vlan) - OVS_REQ_RDLOCK(ms->rwlock); -struct mcast_group * -mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan) - OVS_REQ_RDLOCK(ms->rwlock); - -/* Learning. */ -bool mcast_snooping_add_group(struct mcast_snooping *ms, - const struct in6_addr *addr, - uint16_t vlan, void *port) - OVS_REQ_WRLOCK(ms->rwlock); -bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) - OVS_REQ_WRLOCK(ms->rwlock); -int mcast_snooping_add_report(struct mcast_snooping *ms, - const struct dp_packet *p, - uint16_t vlan, void *port) - OVS_REQ_WRLOCK(ms->rwlock); -int mcast_snooping_add_mld(struct mcast_snooping *ms, - const struct dp_packet *p, - uint16_t vlan, void *port) - OVS_REQ_WRLOCK(ms->rwlock); -bool mcast_snooping_leave_group(struct mcast_snooping *ms, - const struct in6_addr *addr, - uint16_t vlan, void *port) - OVS_REQ_WRLOCK(ms->rwlock); -bool mcast_snooping_leave_group4(struct mcast_snooping *ms, ovs_be32 ip4, - uint16_t vlan, void *port) - OVS_REQ_WRLOCK(ms->rwlock); -bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan, - void *port) - OVS_REQ_WRLOCK(ms->rwlock); -bool mcast_snooping_is_query(ovs_be16 igmp_type); -bool mcast_snooping_is_membership(ovs_be16 igmp_type); - -/* Flush. */ -void mcast_snooping_mdb_flush(struct mcast_snooping *ms); -void mcast_snooping_flush(struct mcast_snooping *ms); -void mcast_snooping_flush_bundle(struct mcast_snooping *ms, void *port); - -#endif /* mcast-snooping.h */ Index: openvswitch-2.17.2/include/internal/mcast-snooping.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/mcast-snooping.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2014 Red Hat, Inc. + * + * Based on mac-learning implementation. + * + * 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 MCAST_SNOOPING_H +#define MCAST_SNOOPING_H 1 + +#include +#include "internal/dp-packet.h" +#include "openvswitch/hmap.h" +#include "openvswitch/list.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/timeval.h" + +struct mcast_snooping; + +/* Default maximum size of a mcast snooping table, in entries. */ +#define MCAST_DEFAULT_MAX_ENTRIES 2048 + +/* Time, in seconds, before expiring a mcast_group due to inactivity. */ +#define MCAST_ENTRY_DEFAULT_IDLE_TIME 300 + +/* Time, in seconds, before expiring a mrouter_port due to inactivity. */ +#define MCAST_MROUTER_PORT_IDLE_TIME 180 + +/* Multicast group entry. + * Guarded by owning 'mcast_snooping''s rwlock. */ +struct mcast_group { + /* Node in parent struct mcast_snooping hmap. */ + struct hmap_node hmap_node; + + /* Multicast group IPv6/IPv4 address. */ + struct in6_addr addr; + + /* VLAN tag. */ + uint16_t vlan; + + /* Node in parent struct mcast_snooping group_lru. */ + struct ovs_list group_node OVS_GUARDED; + + /* Contains struct mcast_group_bundle (ports), least recently used + * at the front, most recently used at the back. */ + struct ovs_list bundle_lru OVS_GUARDED; +}; + +/* The bundle associated to the multicast group. + * Guarded by owning 'mcast_snooping''s rwlock. */ +struct mcast_group_bundle { + /* Node in parent struct mcast_group bundle_lru list. */ + struct ovs_list bundle_node OVS_GUARDED; + + /* When this node expires. */ + time_t expires; + + /* Learned port. */ + void *port OVS_GUARDED; +}; + +/* The bundle connected to a multicast router. + * Guarded by owning 'mcast_snooping''s rwlock. */ +struct mcast_mrouter_bundle { + /* Node in parent struct mcast_group mrouter_lru list. */ + struct ovs_list mrouter_node OVS_GUARDED; + + /* When this node expires. */ + time_t expires; + + /* VLAN tag. */ + uint16_t vlan; + + /* Learned port. */ + void *port OVS_GUARDED; +}; + +/* The bundle to send multicast traffic or Reports. + * Guarded by owning 'mcast_snooping''s rwlock */ +struct mcast_port_bundle { + /* Node in parent struct mcast_snooping. */ + struct ovs_list node; + + /* VLAN tag. */ + uint16_t vlan; + + /* Learned port. */ + void *port; +}; + +/* Multicast snooping table. */ +struct mcast_snooping { + /* Snooping/learning table. */ + struct hmap table; + + /* Contains struct mcast_group, least recently used at the front, + * most recently used at the back. */ + struct ovs_list group_lru OVS_GUARDED; + + /* Contains struct mcast_mrouter_bundle, least recently used at the + * front, most recently used at the back. */ + struct ovs_list mrouter_lru OVS_GUARDED; + + /* Contains struct mcast_port_bundle to be flooded with multicast + * packets in no special order. */ + struct ovs_list fport_list OVS_GUARDED; + + /* Contains struct mcast_port_bundle to forward Reports in + * no special order. */ + struct ovs_list rport_list OVS_GUARDED; + + /* Secret for randomizing hash table. */ + uint32_t secret; + + /* Maximum age before deleting an entry. */ + unsigned int idle_time; + + /* Maximum number of multicast groups learned. */ + size_t max_entries; + + /* True if flow revalidation is needed. */ + bool need_revalidate; + + /* True if unregistered multicast packets should be flooded to all + * ports, otherwise send them to ports connected to multicast routers. */ + bool flood_unreg; + + struct ovs_refcount ref_cnt; + struct ovs_rwlock rwlock; +}; + +/* Basics. */ +bool mcast_snooping_enabled(const struct mcast_snooping *ms); +bool mcast_snooping_flood_unreg(const struct mcast_snooping *ms); +int mcast_mrouter_age(const struct mcast_snooping *ms, + const struct mcast_mrouter_bundle *m); +int mcast_bundle_age(const struct mcast_snooping *ms, + const struct mcast_group_bundle *b); +struct mcast_snooping *mcast_snooping_create(void); +struct mcast_snooping *mcast_snooping_ref(const struct mcast_snooping *); +void mcast_snooping_unref(struct mcast_snooping *); +bool mcast_snooping_run(struct mcast_snooping *ms); +void mcast_snooping_wait(struct mcast_snooping *ms); + +/* Configuration. */ +void mcast_snooping_set_idle_time(struct mcast_snooping *ms, + unsigned int idle_time) + OVS_REQ_WRLOCK(ms->rwlock); +void mcast_snooping_set_max_entries(struct mcast_snooping *ms, + size_t max_entries) + OVS_REQ_WRLOCK(ms->rwlock); +bool +mcast_snooping_set_flood_unreg(struct mcast_snooping *ms, bool enable) + OVS_REQ_WRLOCK(ms->rwlock); +void mcast_snooping_set_port_flood(struct mcast_snooping *ms, void *port, + bool flood) + OVS_REQ_WRLOCK(ms->rwlock); +void mcast_snooping_set_port_flood_reports(struct mcast_snooping *ms, + void *port, bool flood) + OVS_REQ_WRLOCK(ms->rwlock); + +/* Lookup. */ +struct mcast_group * +mcast_snooping_lookup(const struct mcast_snooping *ms, + const struct in6_addr *dip, uint16_t vlan) + OVS_REQ_RDLOCK(ms->rwlock); +struct mcast_group * +mcast_snooping_lookup4(const struct mcast_snooping *ms, ovs_be32 ip4, + uint16_t vlan) + OVS_REQ_RDLOCK(ms->rwlock); + +/* Learning. */ +bool mcast_snooping_add_group(struct mcast_snooping *ms, + const struct in6_addr *addr, + uint16_t vlan, void *port) + OVS_REQ_WRLOCK(ms->rwlock); +bool mcast_snooping_add_group4(struct mcast_snooping *ms, ovs_be32 ip4, + uint16_t vlan, void *port) + OVS_REQ_WRLOCK(ms->rwlock); +int mcast_snooping_add_report(struct mcast_snooping *ms, + const struct dp_packet *p, + uint16_t vlan, void *port) + OVS_REQ_WRLOCK(ms->rwlock); +int mcast_snooping_add_mld(struct mcast_snooping *ms, + const struct dp_packet *p, + uint16_t vlan, void *port) + OVS_REQ_WRLOCK(ms->rwlock); +bool mcast_snooping_leave_group(struct mcast_snooping *ms, + const struct in6_addr *addr, + uint16_t vlan, void *port) + OVS_REQ_WRLOCK(ms->rwlock); +bool mcast_snooping_leave_group4(struct mcast_snooping *ms, ovs_be32 ip4, + uint16_t vlan, void *port) + OVS_REQ_WRLOCK(ms->rwlock); +bool mcast_snooping_add_mrouter(struct mcast_snooping *ms, uint16_t vlan, + void *port) + OVS_REQ_WRLOCK(ms->rwlock); +bool mcast_snooping_is_query(ovs_be16 igmp_type); +bool mcast_snooping_is_membership(ovs_be16 igmp_type); + +/* Flush. */ +void mcast_snooping_mdb_flush(struct mcast_snooping *ms); +void mcast_snooping_flush(struct mcast_snooping *ms); +void mcast_snooping_flush_bundle(struct mcast_snooping *ms, void *port); + +#endif /* mcast-snooping.h */ Index: openvswitch-2.17.2/lib/netdev.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NETDEV_H -#define NETDEV_H 1 - -#include "openvswitch/netdev.h" -#include "openvswitch/types.h" -#include "packets.h" -#include "flow.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Generic interface to network devices ("netdev"s). - * - * Every port on a switch must have a corresponding netdev that must minimally - * support a few operations, such as the ability to read the netdev's MTU. - * The Porting section of the documentation has more information in the - * "Writing a netdev Provider" section. - * - * Thread-safety - * ============= - * - * Most of the netdev functions are fully thread-safe: they may be called from - * any number of threads on the same or different netdev objects. The - * exceptions are: - * - * netdev_rxq_recv() - * netdev_rxq_wait() - * netdev_rxq_drain() - * - * These functions are conditionally thread-safe: they may be called from - * different threads only on different netdev_rxq objects. (The client may - * create multiple netdev_rxq objects for a single netdev and access each - * of those from a different thread.) - * - * NETDEV_QUEUE_FOR_EACH - * netdev_queue_dump_next() - * netdev_queue_dump_done() - * - * These functions are conditionally thread-safe: they may be called from - * different threads only on different netdev_queue_dump objects. (The - * client may create multiple netdev_queue_dump objects for a single - * netdev and access each of those from a different thread.) - */ - -struct dp_packet_batch; -struct dp_packet; -struct netdev_class; -struct netdev_rxq; -struct netdev_saved_flags; -struct ofpbuf; -struct in_addr; -struct in6_addr; -struct smap; -struct sset; -struct ovs_action_push_tnl; - -enum netdev_pt_mode { - /* The netdev is packet type aware. It can potentially carry any kind of - * packet. This "modern" mode is appropriate for both netdevs that handle - * only a single kind of packet (such as a virtual or physical Ethernet - * interface) and for those that can handle multiple (such as VXLAN-GPE or - * Geneve). */ - NETDEV_PT_AWARE, - - /* The netdev sends and receives only Ethernet frames. The netdev cannot - * carry packets other than Ethernet frames. This is a legacy mode for - * backward compability with controllers that are not prepared to handle - * OpenFlow 1.5+ "packet_type". */ - NETDEV_PT_LEGACY_L2, - - /* The netdev sends and receives only IPv4 and IPv6 packets. The netdev - * cannot carry Ethernet frames or other kinds of packets. - * - * IPv4 and IPv6 packets carried over the netdev are treated as Ethernet: - * when they are received, they are converted to Ethernet by adding a dummy - * header with the proper Ethertype; on tranmission, the Ethernet header is - * stripped. This is a legacy mode for backward compability with - * controllers that are not prepared to handle OpenFlow 1.5+ - * "packet_type". */ - NETDEV_PT_LEGACY_L3, -}; - -/* Configuration specific to tunnels. */ -struct netdev_tunnel_config { - ovs_be64 in_key; - bool in_key_present; - bool in_key_flow; - - bool out_key_present; - bool out_key_flow; - ovs_be64 out_key; - - ovs_be16 payload_ethertype; - ovs_be16 dst_port; - - bool ip_src_flow; - bool ip_dst_flow; - struct in6_addr ipv6_src; - struct in6_addr ipv6_dst; - - uint32_t exts; - uint32_t egress_pkt_mark; - bool set_egress_pkt_mark; - - uint8_t ttl; - bool ttl_inherit; - - uint8_t tos; - bool tos_inherit; - - bool csum; - bool dont_fragment; - enum netdev_pt_mode pt_mode; - - bool set_seq; - uint32_t seqno; - uint32_t erspan_idx; - uint8_t erspan_ver; - uint8_t erspan_dir; - uint8_t erspan_hwid; - - bool erspan_ver_flow; - bool erspan_idx_flow; - bool erspan_dir_flow; - bool erspan_hwid_flow; -}; - -void netdev_run(void); -void netdev_wait(void); - -void netdev_enumerate_types(struct sset *types); -bool netdev_is_reserved_name(const char *name); - -int netdev_n_txq(const struct netdev *netdev); -int netdev_n_rxq(const struct netdev *netdev); -bool netdev_is_pmd(const struct netdev *netdev); -bool netdev_has_tunnel_push_pop(const struct netdev *netdev); - -/* Open and close. */ -int netdev_open(const char *name, const char *type, struct netdev **netdevp); - -struct netdev *netdev_ref(const struct netdev *); -void netdev_remove(struct netdev *); -void netdev_close(struct netdev *); - -void netdev_parse_name(const char *netdev_name, char **name, char **type); - -/* Options. */ -int netdev_set_config(struct netdev *, const struct smap *args, char **errp); -int netdev_get_config(const struct netdev *, struct smap *); -const struct netdev_tunnel_config * - netdev_get_tunnel_config(const struct netdev *); -int netdev_get_numa_id(const struct netdev *); - -/* Basic properties. */ -const char *netdev_get_name(const struct netdev *); -const char *netdev_get_type(const struct netdev *); -const char *netdev_get_type_from_name(const char *); -int netdev_get_mtu(const struct netdev *, int *mtup); -int netdev_set_mtu(struct netdev *, int mtu); -void netdev_mtu_user_config(struct netdev *, bool); -bool netdev_mtu_is_user_config(struct netdev *); -int netdev_get_ifindex(const struct netdev *); -int netdev_set_tx_multiq(struct netdev *, unsigned int n_txq); -enum netdev_pt_mode netdev_get_pt_mode(const struct netdev *); -void netdev_set_dpif_type(struct netdev *, const char *); -const char *netdev_get_dpif_type(const struct netdev *); - -/* Packet reception. */ -int netdev_rxq_open(struct netdev *, struct netdev_rxq **, int id); -void netdev_rxq_close(struct netdev_rxq *); -bool netdev_rxq_enabled(struct netdev_rxq *); - -const char *netdev_rxq_get_name(const struct netdev_rxq *); -int netdev_rxq_get_queue_id(const struct netdev_rxq *); - -int netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *, - int *qfill); -void netdev_rxq_wait(struct netdev_rxq *); -int netdev_rxq_drain(struct netdev_rxq *); - -/* Packet transmission. */ -int netdev_send(struct netdev *, int qid, struct dp_packet_batch *, - bool concurrent_txq); -void netdev_send_wait(struct netdev *, int qid); - -/* native tunnel APIs */ -/* Structure to pass parameters required to build a tunnel header. */ -struct netdev_tnl_build_header_params { - const struct flow *flow; - const struct in6_addr *s_ip; - struct eth_addr dmac; - struct eth_addr smac; - bool is_ipv6; -}; - -void -netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params, - const struct flow *tnl_flow, - const struct in6_addr *src, - struct eth_addr dmac, - struct eth_addr smac); - -int netdev_build_header(const struct netdev *, struct ovs_action_push_tnl *data, - const struct netdev_tnl_build_header_params *params); - -int netdev_push_header(const struct netdev *netdev, - struct dp_packet_batch *, - const struct ovs_action_push_tnl *data); -void netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *); - -/* Hardware address. */ -int netdev_set_etheraddr(struct netdev *, const struct eth_addr mac); -int netdev_get_etheraddr(const struct netdev *, struct eth_addr *mac); - -/* PHY interface. */ -bool netdev_get_carrier(const struct netdev *); -long long int netdev_get_carrier_resets(const struct netdev *); -int netdev_set_miimon_interval(struct netdev *, long long int interval); - -/* Flags. */ -enum netdev_flags { - NETDEV_UP = 0x0001, /* Device enabled? */ - NETDEV_PROMISC = 0x0002, /* Promiscuous mode? */ - NETDEV_LOOPBACK = 0x0004 /* This is a loopback device. */ -}; - -int netdev_get_flags(const struct netdev *, enum netdev_flags *); -int netdev_set_flags(struct netdev *, enum netdev_flags, - struct netdev_saved_flags **); -int netdev_turn_flags_on(struct netdev *, enum netdev_flags, - struct netdev_saved_flags **); -int netdev_turn_flags_off(struct netdev *, enum netdev_flags, - struct netdev_saved_flags **); - -void netdev_restore_flags(struct netdev_saved_flags *); - -/* TCP/IP stack interface. */ -int netdev_set_in4(struct netdev *, struct in_addr addr, struct in_addr mask); -int netdev_get_in4_by_name(const char *device_name, struct in_addr *in4); -int netdev_get_ip_by_name(const char *device_name, struct in6_addr *); -int netdev_get_addr_list(const struct netdev *netdev, struct in6_addr **addr, - struct in6_addr **mask, int *n_in6); - -int netdev_add_router(struct netdev *, struct in_addr router); -int netdev_get_next_hop(const struct netdev *, const struct in_addr *host, - struct in_addr *next_hop, char **); -int netdev_get_status(const struct netdev *, struct smap *); -int netdev_arp_lookup(const struct netdev *, ovs_be32 ip, - struct eth_addr *mac); - -struct netdev *netdev_find_dev_by_in4(const struct in_addr *); - -/* Statistics. */ -int netdev_get_stats(const struct netdev *, struct netdev_stats *); -int netdev_get_custom_stats(const struct netdev *, - struct netdev_custom_stats *); - -/* Quality of service. */ -struct netdev_qos_capabilities { - unsigned int n_queues; -}; - -struct netdev_queue_stats { - /* Values of unsupported statistics are set to all-1-bits (UINT64_MAX). */ - uint64_t tx_bytes; - uint64_t tx_packets; - uint64_t tx_errors; - - /* Time at which the queue was created, in msecs, LLONG_MIN if unknown. */ - long long int created; -}; - -int netdev_set_policing(struct netdev *, uint32_t kbits_rate, - uint32_t kbits_burst, uint32_t kpkts_rate, - uint32_t kpkts_burst); - -int netdev_get_qos_types(const struct netdev *, struct sset *types); -int netdev_get_qos_capabilities(const struct netdev *, - const char *type, - struct netdev_qos_capabilities *); -int netdev_get_n_queues(const struct netdev *, - const char *type, unsigned int *n_queuesp); - -int netdev_get_qos(const struct netdev *, - const char **typep, struct smap *details); -int netdev_set_qos(struct netdev *, - const char *type, const struct smap *details); - -int netdev_get_queue(const struct netdev *, - unsigned int queue_id, struct smap *details); -int netdev_set_queue(struct netdev *, - unsigned int queue_id, const struct smap *details); -int netdev_delete_queue(struct netdev *, unsigned int queue_id); -int netdev_get_queue_stats(const struct netdev *, unsigned int queue_id, - struct netdev_queue_stats *); -uint64_t netdev_get_change_seq(const struct netdev *); - -int netdev_reconfigure(struct netdev *netdev); -void netdev_wait_reconf_required(struct netdev *netdev); -bool netdev_is_reconf_required(struct netdev *netdev); - -struct netdev_queue_dump { - struct netdev *netdev; - int error; - void *state; -}; -void netdev_queue_dump_start(struct netdev_queue_dump *, - const struct netdev *); -bool netdev_queue_dump_next(struct netdev_queue_dump *, - unsigned int *queue_id, struct smap *details); -int netdev_queue_dump_done(struct netdev_queue_dump *); - -/* Iterates through each queue in NETDEV, using DUMP as state. Fills QUEUE_ID - * and DETAILS with information about queues. The client must initialize and - * destroy DETAILS. - * - * Arguments all have pointer type. - * - * If you break out of the loop, then you need to free the dump structure by - * hand using netdev_queue_dump_done(). */ -#define NETDEV_QUEUE_FOR_EACH(QUEUE_ID, DETAILS, DUMP, NETDEV) \ - for (netdev_queue_dump_start(DUMP, NETDEV); \ - (netdev_queue_dump_next(DUMP, QUEUE_ID, DETAILS) \ - ? true \ - : (netdev_queue_dump_done(DUMP), false)); \ - ) - -typedef void netdev_dump_queue_stats_cb(unsigned int queue_id, - struct netdev_queue_stats *, - void *aux); -int netdev_dump_queue_stats(const struct netdev *, - netdev_dump_queue_stats_cb *, void *aux); - -extern struct seq *tnl_conf_seq; - -#ifndef _WIN32 -void netdev_get_addrs_list_flush(void); -int netdev_get_addrs(const char dev[], struct in6_addr **paddr, - struct in6_addr **pmask, int *n_in6); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* netdev.h */ Index: openvswitch-2.17.2/include/internal/netdev.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/netdev.h @@ -0,0 +1,364 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETDEV_H +#define NETDEV_H 1 + +#include "openvswitch/netdev.h" +#include "openvswitch/types.h" +#include "internal/packets.h" +#include "internal/flow.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Generic interface to network devices ("netdev"s). + * + * Every port on a switch must have a corresponding netdev that must minimally + * support a few operations, such as the ability to read the netdev's MTU. + * The Porting section of the documentation has more information in the + * "Writing a netdev Provider" section. + * + * Thread-safety + * ============= + * + * Most of the netdev functions are fully thread-safe: they may be called from + * any number of threads on the same or different netdev objects. The + * exceptions are: + * + * netdev_rxq_recv() + * netdev_rxq_wait() + * netdev_rxq_drain() + * + * These functions are conditionally thread-safe: they may be called from + * different threads only on different netdev_rxq objects. (The client may + * create multiple netdev_rxq objects for a single netdev and access each + * of those from a different thread.) + * + * NETDEV_QUEUE_FOR_EACH + * netdev_queue_dump_next() + * netdev_queue_dump_done() + * + * These functions are conditionally thread-safe: they may be called from + * different threads only on different netdev_queue_dump objects. (The + * client may create multiple netdev_queue_dump objects for a single + * netdev and access each of those from a different thread.) + */ + +struct dp_packet_batch; +struct dp_packet; +struct netdev_class; +struct netdev_rxq; +struct netdev_saved_flags; +struct ofpbuf; +struct in_addr; +struct in6_addr; +struct smap; +struct sset; +struct ovs_action_push_tnl; + +enum netdev_pt_mode { + /* The netdev is packet type aware. It can potentially carry any kind of + * packet. This "modern" mode is appropriate for both netdevs that handle + * only a single kind of packet (such as a virtual or physical Ethernet + * interface) and for those that can handle multiple (such as VXLAN-GPE or + * Geneve). */ + NETDEV_PT_AWARE, + + /* The netdev sends and receives only Ethernet frames. The netdev cannot + * carry packets other than Ethernet frames. This is a legacy mode for + * backward compability with controllers that are not prepared to handle + * OpenFlow 1.5+ "packet_type". */ + NETDEV_PT_LEGACY_L2, + + /* The netdev sends and receives only IPv4 and IPv6 packets. The netdev + * cannot carry Ethernet frames or other kinds of packets. + * + * IPv4 and IPv6 packets carried over the netdev are treated as Ethernet: + * when they are received, they are converted to Ethernet by adding a dummy + * header with the proper Ethertype; on tranmission, the Ethernet header is + * stripped. This is a legacy mode for backward compability with + * controllers that are not prepared to handle OpenFlow 1.5+ + * "packet_type". */ + NETDEV_PT_LEGACY_L3, +}; + +/* Configuration specific to tunnels. */ +struct netdev_tunnel_config { + ovs_be64 in_key; + bool in_key_present; + bool in_key_flow; + + bool out_key_present; + bool out_key_flow; + ovs_be64 out_key; + + ovs_be16 payload_ethertype; + ovs_be16 dst_port; + + bool ip_src_flow; + bool ip_dst_flow; + struct in6_addr ipv6_src; + struct in6_addr ipv6_dst; + + uint32_t exts; + uint32_t egress_pkt_mark; + bool set_egress_pkt_mark; + + uint8_t ttl; + bool ttl_inherit; + + uint8_t tos; + bool tos_inherit; + + bool csum; + bool dont_fragment; + enum netdev_pt_mode pt_mode; + + bool set_seq; + uint32_t seqno; + uint32_t erspan_idx; + uint8_t erspan_ver; + uint8_t erspan_dir; + uint8_t erspan_hwid; + + bool erspan_ver_flow; + bool erspan_idx_flow; + bool erspan_dir_flow; + bool erspan_hwid_flow; +}; + +void netdev_run(void); +void netdev_wait(void); + +void netdev_enumerate_types(struct sset *types); +bool netdev_is_reserved_name(const char *name); + +int netdev_n_txq(const struct netdev *netdev); +int netdev_n_rxq(const struct netdev *netdev); +bool netdev_is_pmd(const struct netdev *netdev); +bool netdev_has_tunnel_push_pop(const struct netdev *netdev); + +/* Open and close. */ +int netdev_open(const char *name, const char *type, struct netdev **netdevp); + +struct netdev *netdev_ref(const struct netdev *); +void netdev_remove(struct netdev *); +void netdev_close(struct netdev *); + +void netdev_parse_name(const char *netdev_name, char **name, char **type); + +/* Options. */ +int netdev_set_config(struct netdev *, const struct smap *args, char **errp); +int netdev_get_config(const struct netdev *, struct smap *); +const struct netdev_tunnel_config * + netdev_get_tunnel_config(const struct netdev *); +int netdev_get_numa_id(const struct netdev *); + +/* Basic properties. */ +const char *netdev_get_name(const struct netdev *); +const char *netdev_get_type(const struct netdev *); +const char *netdev_get_type_from_name(const char *); +int netdev_get_mtu(const struct netdev *, int *mtup); +int netdev_set_mtu(struct netdev *, int mtu); +void netdev_mtu_user_config(struct netdev *, bool); +bool netdev_mtu_is_user_config(struct netdev *); +int netdev_get_ifindex(const struct netdev *); +int netdev_set_tx_multiq(struct netdev *, unsigned int n_txq); +enum netdev_pt_mode netdev_get_pt_mode(const struct netdev *); +void netdev_set_dpif_type(struct netdev *, const char *); +const char *netdev_get_dpif_type(const struct netdev *); + +/* Packet reception. */ +int netdev_rxq_open(struct netdev *, struct netdev_rxq **, int id); +void netdev_rxq_close(struct netdev_rxq *); +bool netdev_rxq_enabled(struct netdev_rxq *); + +const char *netdev_rxq_get_name(const struct netdev_rxq *); +int netdev_rxq_get_queue_id(const struct netdev_rxq *); + +int netdev_rxq_recv(struct netdev_rxq *rx, struct dp_packet_batch *, + int *qfill); +void netdev_rxq_wait(struct netdev_rxq *); +int netdev_rxq_drain(struct netdev_rxq *); + +/* Packet transmission. */ +int netdev_send(struct netdev *, int qid, struct dp_packet_batch *, + bool concurrent_txq); +void netdev_send_wait(struct netdev *, int qid); + +/* native tunnel APIs */ +/* Structure to pass parameters required to build a tunnel header. */ +struct netdev_tnl_build_header_params { + const struct flow *flow; + const struct in6_addr *s_ip; + struct eth_addr dmac; + struct eth_addr smac; + bool is_ipv6; +}; + +void +netdev_init_tnl_build_header_params(struct netdev_tnl_build_header_params *params, + const struct flow *tnl_flow, + const struct in6_addr *src, + struct eth_addr dmac, + struct eth_addr smac); + +int netdev_build_header(const struct netdev *, struct ovs_action_push_tnl *data, + const struct netdev_tnl_build_header_params *params); + +int netdev_push_header(const struct netdev *netdev, + struct dp_packet_batch *, + const struct ovs_action_push_tnl *data); +void netdev_pop_header(struct netdev *netdev, struct dp_packet_batch *); + +/* Hardware address. */ +int netdev_set_etheraddr(struct netdev *, const struct eth_addr mac); +int netdev_get_etheraddr(const struct netdev *, struct eth_addr *mac); + +/* PHY interface. */ +bool netdev_get_carrier(const struct netdev *); +long long int netdev_get_carrier_resets(const struct netdev *); +int netdev_set_miimon_interval(struct netdev *, long long int interval); + +/* Flags. */ +enum netdev_flags { + NETDEV_UP = 0x0001, /* Device enabled? */ + NETDEV_PROMISC = 0x0002, /* Promiscuous mode? */ + NETDEV_LOOPBACK = 0x0004 /* This is a loopback device. */ +}; + +int netdev_get_flags(const struct netdev *, enum netdev_flags *); +int netdev_set_flags(struct netdev *, enum netdev_flags, + struct netdev_saved_flags **); +int netdev_turn_flags_on(struct netdev *, enum netdev_flags, + struct netdev_saved_flags **); +int netdev_turn_flags_off(struct netdev *, enum netdev_flags, + struct netdev_saved_flags **); + +void netdev_restore_flags(struct netdev_saved_flags *); + +/* TCP/IP stack interface. */ +int netdev_set_in4(struct netdev *, struct in_addr addr, struct in_addr mask); +int netdev_get_in4_by_name(const char *device_name, struct in_addr *in4); +int netdev_get_ip_by_name(const char *device_name, struct in6_addr *); +int netdev_get_addr_list(const struct netdev *netdev, struct in6_addr **addr, + struct in6_addr **mask, int *n_in6); + +int netdev_add_router(struct netdev *, struct in_addr router); +int netdev_get_next_hop(const struct netdev *, const struct in_addr *host, + struct in_addr *next_hop, char **); +int netdev_get_status(const struct netdev *, struct smap *); +int netdev_arp_lookup(const struct netdev *, ovs_be32 ip, + struct eth_addr *mac); + +struct netdev *netdev_find_dev_by_in4(const struct in_addr *); + +/* Statistics. */ +int netdev_get_stats(const struct netdev *, struct netdev_stats *); +int netdev_get_custom_stats(const struct netdev *, + struct netdev_custom_stats *); + +/* Quality of service. */ +struct netdev_qos_capabilities { + unsigned int n_queues; +}; + +struct netdev_queue_stats { + /* Values of unsupported statistics are set to all-1-bits (UINT64_MAX). */ + uint64_t tx_bytes; + uint64_t tx_packets; + uint64_t tx_errors; + + /* Time at which the queue was created, in msecs, LLONG_MIN if unknown. */ + long long int created; +}; + +int netdev_set_policing(struct netdev *, uint32_t kbits_rate, + uint32_t kbits_burst, uint32_t kpkts_rate, + uint32_t kpkts_burst); + +int netdev_get_qos_types(const struct netdev *, struct sset *types); +int netdev_get_qos_capabilities(const struct netdev *, + const char *type, + struct netdev_qos_capabilities *); +int netdev_get_n_queues(const struct netdev *, + const char *type, unsigned int *n_queuesp); + +int netdev_get_qos(const struct netdev *, + const char **typep, struct smap *details); +int netdev_set_qos(struct netdev *, + const char *type, const struct smap *details); + +int netdev_get_queue(const struct netdev *, + unsigned int queue_id, struct smap *details); +int netdev_set_queue(struct netdev *, + unsigned int queue_id, const struct smap *details); +int netdev_delete_queue(struct netdev *, unsigned int queue_id); +int netdev_get_queue_stats(const struct netdev *, unsigned int queue_id, + struct netdev_queue_stats *); +uint64_t netdev_get_change_seq(const struct netdev *); + +int netdev_reconfigure(struct netdev *netdev); +void netdev_wait_reconf_required(struct netdev *netdev); +bool netdev_is_reconf_required(struct netdev *netdev); + +struct netdev_queue_dump { + struct netdev *netdev; + int error; + void *state; +}; +void netdev_queue_dump_start(struct netdev_queue_dump *, + const struct netdev *); +bool netdev_queue_dump_next(struct netdev_queue_dump *, + unsigned int *queue_id, struct smap *details); +int netdev_queue_dump_done(struct netdev_queue_dump *); + +/* Iterates through each queue in NETDEV, using DUMP as state. Fills QUEUE_ID + * and DETAILS with information about queues. The client must initialize and + * destroy DETAILS. + * + * Arguments all have pointer type. + * + * If you break out of the loop, then you need to free the dump structure by + * hand using netdev_queue_dump_done(). */ +#define NETDEV_QUEUE_FOR_EACH(QUEUE_ID, DETAILS, DUMP, NETDEV) \ + for (netdev_queue_dump_start(DUMP, NETDEV); \ + (netdev_queue_dump_next(DUMP, QUEUE_ID, DETAILS) \ + ? true \ + : (netdev_queue_dump_done(DUMP), false)); \ + ) + +typedef void netdev_dump_queue_stats_cb(unsigned int queue_id, + struct netdev_queue_stats *, + void *aux); +int netdev_dump_queue_stats(const struct netdev *, + netdev_dump_queue_stats_cb *, void *aux); + +extern struct seq *tnl_conf_seq; + +#ifndef _WIN32 +void netdev_get_addrs_list_flush(void); +int netdev_get_addrs(const char dev[], struct in6_addr **paddr, + struct in6_addr **pmask, int *n_in6); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* netdev.h */ Index: openvswitch-2.17.2/lib/netlink-protocol.h =================================================================== --- openvswitch-2.17.2.orig/lib/netlink-protocol.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2008, 2010, 2011, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NETLINK_PROTOCOL_H -#define NETLINK_PROTOCOL_H 1 - -/* Netlink protocol definitions. - * - * Netlink is a message framing format described in RFC 3549 and used heavily - * in Linux to access the network stack. Open vSwitch uses AF_NETLINK sockets - * for this purpose on Linux. But on all platforms, Open vSwitch uses Netlink - * message framing internally for certain purposes. - * - * This header provides access to the Netlink message framing definitions - * regardless of platform. On Linux, it includes the proper headers directly; - * on other platforms it directly defines the structures and macros itself. - */ - -#include -#include -#include "util.h" - -#ifdef HAVE_NETLINK -#include -#include - -#else -#define NETLINK_NETFILTER 12 -#define NETLINK_GENERIC 16 - -/* nlmsg_flags bits. */ -#define NLM_F_REQUEST 0x001 -#define NLM_F_MULTI 0x002 -#define NLM_F_ACK 0x004 -#define NLM_F_ECHO 0x008 - -/* GET request flag.*/ -#define NLM_F_ROOT 0x100 -#define NLM_F_MATCH 0x200 -#define NLM_F_ATOMIC 0x400 -#define NLM_F_DUMP (NLM_F_ROOT | NLM_F_MATCH) - -/* NEW request flags. */ -#define NLM_F_REPLACE 0x100 -#define NLM_F_EXCL 0x200 -#define NLM_F_CREATE 0x400 - -/* nlmsg_type values. */ -#define NLMSG_NOOP 1 -#define NLMSG_ERROR 2 -#define NLMSG_DONE 3 -#define NLMSG_OVERRUN 4 - -#define NLMSG_MIN_TYPE 0x10 - -#define MAX_LINKS 32 - -struct nlmsghdr { - uint32_t nlmsg_len; - uint16_t nlmsg_type; - uint16_t nlmsg_flags; - uint32_t nlmsg_seq; - uint32_t nlmsg_pid; -}; -BUILD_ASSERT_DECL(sizeof(struct nlmsghdr) == 16); - -#define NLMSG_ALIGNTO 4 -#define NLMSG_ALIGN(SIZE) ROUND_UP(SIZE, NLMSG_ALIGNTO) -#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) - -struct nlmsgerr -{ - int error; - struct nlmsghdr msg; -}; -BUILD_ASSERT_DECL(sizeof(struct nlmsgerr) == 20); - -struct genlmsghdr { - uint8_t cmd; - uint8_t version; - uint16_t reserved; -}; -BUILD_ASSERT_DECL(sizeof(struct genlmsghdr) == 4); - -#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) - -struct nlattr { - uint16_t nla_len; - uint16_t nla_type; -}; -BUILD_ASSERT_DECL(sizeof(struct nlattr) == 4); - -#define NLA_ALIGNTO 4 -#define NLA_ALIGN(SIZE) ROUND_UP(SIZE, NLA_ALIGNTO) -#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) - -#define GENL_MIN_ID NLMSG_MIN_TYPE -#define GENL_MAX_ID 1023 - -#define GENL_ID_CTRL NLMSG_MIN_TYPE - -enum { - CTRL_CMD_UNSPEC, - CTRL_CMD_NEWFAMILY, - CTRL_CMD_DELFAMILY, - CTRL_CMD_GETFAMILY, - CTRL_CMD_NEWOPS, - CTRL_CMD_DELOPS, - CTRL_CMD_GETOPS, - __CTRL_CMD_MAX, -}; - -#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1) - -enum { - CTRL_ATTR_UNSPEC, - CTRL_ATTR_FAMILY_ID, - CTRL_ATTR_FAMILY_NAME, - CTRL_ATTR_VERSION, - CTRL_ATTR_HDRSIZE, - CTRL_ATTR_MAXATTR, - CTRL_ATTR_OPS, - __CTRL_ATTR_MAX, -}; - -#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) - -enum { - CTRL_ATTR_OP_UNSPEC, - CTRL_ATTR_OP_ID, - CTRL_ATTR_OP_FLAGS, - __CTRL_ATTR_OP_MAX, -}; - -#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) -#endif /* !HAVE_NETLINK */ - -/* These were introduced all together in 2.6.24. */ -#ifndef NLA_TYPE_MASK -#define NLA_F_NESTED (1 << 15) -#define NLA_F_NET_BYTEORDER (1 << 14) -#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) -#endif - -/* These were introduced all together in 2.6.14. (We want our programs to - * support the newer kernel features even if compiled with older headers.) */ -#ifndef NETLINK_ADD_MEMBERSHIP -#define NETLINK_ADD_MEMBERSHIP 1 -#define NETLINK_DROP_MEMBERSHIP 2 -#endif - -/* This was introduced in v4.2. (We want our programs to support the newer - * kernel features even if compiled with older headers.) */ -#ifndef NETLINK_LISTEN_ALL_NSID -#define NETLINK_LISTEN_ALL_NSID 8 -#endif - -/* These were introduced all together in 2.6.23. (We want our programs to - * support the newer kernel features even if compiled with older headers.) */ -#ifndef CTRL_ATTR_MCAST_GRP_MAX - -#undef CTRL_ATTR_MAX -#define CTRL_ATTR_MAX 7 -#define CTRL_ATTR_MCAST_GROUPS 7 - -enum { - CTRL_ATTR_MCAST_GRP_UNSPEC, - CTRL_ATTR_MCAST_GRP_NAME, - CTRL_ATTR_MCAST_GRP_ID, - __CTRL_ATTR_MCAST_GRP_MAX, -}; - -#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) -#endif /* CTRL_ATTR_MCAST_GRP_MAX */ - -#ifndef NETLINK_EXT_ACK - -#define NETLINK_CAP_ACK 10 -#define NETLINK_EXT_ACK 11 - -/* ACK message flags. */ -#define NLM_F_CAPPED 0x100 -#define NLM_F_ACK_TLVS 0x200 - -enum { - NLMSGERR_ATTR_UNUSED, - NLMSGERR_ATTR_MSG, - NLMSGERR_ATTR_OFFS, - __NLMSGERR_ATTR_MAX, - NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 -}; - -#endif /* NLM_F_ACK_TLVS */ - -#endif /* netlink-protocol.h */ Index: openvswitch-2.17.2/include/internal/netlink-protocol.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/netlink-protocol.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2008, 2010, 2011, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETLINK_PROTOCOL_H +#define NETLINK_PROTOCOL_H 1 + +/* Netlink protocol definitions. + * + * Netlink is a message framing format described in RFC 3549 and used heavily + * in Linux to access the network stack. Open vSwitch uses AF_NETLINK sockets + * for this purpose on Linux. But on all platforms, Open vSwitch uses Netlink + * message framing internally for certain purposes. + * + * This header provides access to the Netlink message framing definitions + * regardless of platform. On Linux, it includes the proper headers directly; + * on other platforms it directly defines the structures and macros itself. + */ + +#include +#include +#include "internal/util.h" + +#ifdef HAVE_NETLINK +#include +#include + +#else +#define NETLINK_NETFILTER 12 +#define NETLINK_GENERIC 16 + +/* nlmsg_flags bits. */ +#define NLM_F_REQUEST 0x001 +#define NLM_F_MULTI 0x002 +#define NLM_F_ACK 0x004 +#define NLM_F_ECHO 0x008 + +/* GET request flag.*/ +#define NLM_F_ROOT 0x100 +#define NLM_F_MATCH 0x200 +#define NLM_F_ATOMIC 0x400 +#define NLM_F_DUMP (NLM_F_ROOT | NLM_F_MATCH) + +/* NEW request flags. */ +#define NLM_F_REPLACE 0x100 +#define NLM_F_EXCL 0x200 +#define NLM_F_CREATE 0x400 + +/* nlmsg_type values. */ +#define NLMSG_NOOP 1 +#define NLMSG_ERROR 2 +#define NLMSG_DONE 3 +#define NLMSG_OVERRUN 4 + +#define NLMSG_MIN_TYPE 0x10 + +#define MAX_LINKS 32 + +struct nlmsghdr { + uint32_t nlmsg_len; + uint16_t nlmsg_type; + uint16_t nlmsg_flags; + uint32_t nlmsg_seq; + uint32_t nlmsg_pid; +}; +BUILD_ASSERT_DECL(sizeof(struct nlmsghdr) == 16); + +#define NLMSG_ALIGNTO 4 +#define NLMSG_ALIGN(SIZE) ROUND_UP(SIZE, NLMSG_ALIGNTO) +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) + +struct nlmsgerr +{ + int error; + struct nlmsghdr msg; +}; +BUILD_ASSERT_DECL(sizeof(struct nlmsgerr) == 20); + +struct genlmsghdr { + uint8_t cmd; + uint8_t version; + uint16_t reserved; +}; +BUILD_ASSERT_DECL(sizeof(struct genlmsghdr) == 4); + +#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr)) + +struct nlattr { + uint16_t nla_len; + uint16_t nla_type; +}; +BUILD_ASSERT_DECL(sizeof(struct nlattr) == 4); + +#define NLA_ALIGNTO 4 +#define NLA_ALIGN(SIZE) ROUND_UP(SIZE, NLA_ALIGNTO) +#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr))) + +#define GENL_MIN_ID NLMSG_MIN_TYPE +#define GENL_MAX_ID 1023 + +#define GENL_ID_CTRL NLMSG_MIN_TYPE + +enum { + CTRL_CMD_UNSPEC, + CTRL_CMD_NEWFAMILY, + CTRL_CMD_DELFAMILY, + CTRL_CMD_GETFAMILY, + CTRL_CMD_NEWOPS, + CTRL_CMD_DELOPS, + CTRL_CMD_GETOPS, + __CTRL_CMD_MAX, +}; + +#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1) + +enum { + CTRL_ATTR_UNSPEC, + CTRL_ATTR_FAMILY_ID, + CTRL_ATTR_FAMILY_NAME, + CTRL_ATTR_VERSION, + CTRL_ATTR_HDRSIZE, + CTRL_ATTR_MAXATTR, + CTRL_ATTR_OPS, + __CTRL_ATTR_MAX, +}; + +#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1) + +enum { + CTRL_ATTR_OP_UNSPEC, + CTRL_ATTR_OP_ID, + CTRL_ATTR_OP_FLAGS, + __CTRL_ATTR_OP_MAX, +}; + +#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1) +#endif /* !HAVE_NETLINK */ + +/* These were introduced all together in 2.6.24. */ +#ifndef NLA_TYPE_MASK +#define NLA_F_NESTED (1 << 15) +#define NLA_F_NET_BYTEORDER (1 << 14) +#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER) +#endif + +/* These were introduced all together in 2.6.14. (We want our programs to + * support the newer kernel features even if compiled with older headers.) */ +#ifndef NETLINK_ADD_MEMBERSHIP +#define NETLINK_ADD_MEMBERSHIP 1 +#define NETLINK_DROP_MEMBERSHIP 2 +#endif + +/* This was introduced in v4.2. (We want our programs to support the newer + * kernel features even if compiled with older headers.) */ +#ifndef NETLINK_LISTEN_ALL_NSID +#define NETLINK_LISTEN_ALL_NSID 8 +#endif + +/* These were introduced all together in 2.6.23. (We want our programs to + * support the newer kernel features even if compiled with older headers.) */ +#ifndef CTRL_ATTR_MCAST_GRP_MAX + +#undef CTRL_ATTR_MAX +#define CTRL_ATTR_MAX 7 +#define CTRL_ATTR_MCAST_GROUPS 7 + +enum { + CTRL_ATTR_MCAST_GRP_UNSPEC, + CTRL_ATTR_MCAST_GRP_NAME, + CTRL_ATTR_MCAST_GRP_ID, + __CTRL_ATTR_MCAST_GRP_MAX, +}; + +#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1) +#endif /* CTRL_ATTR_MCAST_GRP_MAX */ + +#ifndef NETLINK_EXT_ACK + +#define NETLINK_CAP_ACK 10 +#define NETLINK_EXT_ACK 11 + +/* ACK message flags. */ +#define NLM_F_CAPPED 0x100 +#define NLM_F_ACK_TLVS 0x200 + +enum { + NLMSGERR_ATTR_UNUSED, + NLMSGERR_ATTR_MSG, + NLMSGERR_ATTR_OFFS, + __NLMSGERR_ATTR_MAX, + NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 +}; + +#endif /* NLM_F_ACK_TLVS */ + +#endif /* netlink-protocol.h */ Index: openvswitch-2.17.2/lib/netlink.h =================================================================== --- openvswitch-2.17.2.orig/lib/netlink.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2015 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef NETLINK_H -#define NETLINK_H 1 - -/* Netlink message helpers. - * - * Netlink is a datagram-based network protocol primarily for communication - * between user processes and the kernel, and mainly on Linux. Netlink is - * specified in RFC 3549, "Linux Netlink as an IP Services Protocol". - * - * Netlink is not suitable for use in physical networks of heterogeneous - * machines because host byte order is used throughout. - * - * This header file defines helper functions for working with Netlink messages. - * For Netlink protocol definitions, see netlink-protocol.h. For - * Linux-specific definitions for Netlink sockets, see netlink-socket.h. - */ - -#include -#include -#include -#include -#include -#include "netlink-protocol.h" -#include "openvswitch/types.h" - -struct ofpbuf; -struct nlattr; - -/* Accessing headers and data. */ -struct nlmsghdr *nl_msg_nlmsghdr(const struct ofpbuf *); -struct genlmsghdr *nl_msg_genlmsghdr(const struct ofpbuf *); -bool nl_msg_nlmsgerr(const struct ofpbuf *, int *error, const char **attr_msg); -void nl_msg_reserve(struct ofpbuf *, size_t); - -/* Appending and prepending headers and raw data. */ -void nl_msg_put_nlmsghdr(struct ofpbuf *, size_t expected_payload, - uint32_t type, uint32_t flags); -void nl_msg_put_genlmsghdr(struct ofpbuf *, size_t expected_payload, - int family, uint32_t flags, - uint8_t cmd, uint8_t version); -void nl_msg_put(struct ofpbuf *, const void *, size_t); -void *nl_msg_put_uninit(struct ofpbuf *, size_t); -void nl_msg_push(struct ofpbuf *, const void *, size_t); -void *nl_msg_push_uninit(struct ofpbuf *, size_t); - -/* Appending attributes. */ -void *nl_msg_put_unspec_uninit(struct ofpbuf *, uint16_t type, size_t); -void *nl_msg_put_unspec_zero(struct ofpbuf *, uint16_t type, size_t); -void nl_msg_put_unspec(struct ofpbuf *, uint16_t type, const void *, size_t); -void nl_msg_put_flag(struct ofpbuf *, uint16_t type); -void nl_msg_put_u8(struct ofpbuf *, uint16_t type, uint8_t value); -void nl_msg_put_u16(struct ofpbuf *, uint16_t type, uint16_t value); -void nl_msg_put_u32(struct ofpbuf *, uint16_t type, uint32_t value); -void nl_msg_put_u64(struct ofpbuf *, uint16_t type, uint64_t value); -void nl_msg_put_u128(struct ofpbuf *, uint16_t type, ovs_u128 value); -void nl_msg_put_be16(struct ofpbuf *, uint16_t type, ovs_be16 value); -void nl_msg_put_be32(struct ofpbuf *, uint16_t type, ovs_be32 value); -void nl_msg_put_be64(struct ofpbuf *, uint16_t type, ovs_be64 value); -void nl_msg_put_be128(struct ofpbuf *, uint16_t type, ovs_be128 value); -void nl_msg_put_in6_addr(struct ofpbuf *msg, uint16_t type, - const struct in6_addr *value); -void nl_msg_put_odp_port(struct ofpbuf *, uint16_t type, odp_port_t value); -void nl_msg_put_string__(struct ofpbuf *, uint16_t type, const char *value, - size_t len); -void nl_msg_put_string(struct ofpbuf *, uint16_t type, const char *value); - -size_t nl_msg_start_nested(struct ofpbuf *, uint16_t type); -void nl_msg_end_nested(struct ofpbuf *, size_t offset); -void nl_msg_cancel_nested(struct ofpbuf *, size_t offset); -bool nl_msg_end_non_empty_nested(struct ofpbuf *, size_t offset); -void nl_msg_put_nested(struct ofpbuf *, uint16_t type, - const void *data, size_t size); - -/* Prepending attributes. */ -void *nl_msg_push_unspec_uninit(struct ofpbuf *, uint16_t type, size_t); -void nl_msg_push_unspec(struct ofpbuf *, uint16_t type, const void *, size_t); -void nl_msg_push_flag(struct ofpbuf *, uint16_t type); -void nl_msg_push_u8(struct ofpbuf *, uint16_t type, uint8_t value); -void nl_msg_push_u16(struct ofpbuf *, uint16_t type, uint16_t value); -void nl_msg_push_u32(struct ofpbuf *, uint16_t type, uint32_t value); -void nl_msg_push_u64(struct ofpbuf *, uint16_t type, uint64_t value); -void nl_msg_push_u128(struct ofpbuf *, uint16_t type, ovs_u128 value); -void nl_msg_push_be16(struct ofpbuf *, uint16_t type, ovs_be16 value); -void nl_msg_push_be32(struct ofpbuf *, uint16_t type, ovs_be32 value); -void nl_msg_push_be64(struct ofpbuf *, uint16_t type, ovs_be64 value); -void nl_msg_push_be128(struct ofpbuf *, uint16_t type, ovs_be128 value); -void nl_msg_push_string(struct ofpbuf *, uint16_t type, const char *value); - -/* Separating buffers into individual messages. */ -struct nlmsghdr *nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg); - -/* Sizes of various attribute types, in bytes, including the attribute header - * and padding. - * - * A minimum-size attribute is 4 bytes long: 4 bytes of header, no bytes of - * payload, no padding. - * - * A maximum-size attribute is 65536 bytes long: 4 bytes of header, 65531 bytes - * of payload, 1 byte of padding. (Thus, NL_ATTR_SIZE() of a maximum length - * attribute payload does not fit in 16 bits.) */ -#define NL_ATTR_SIZE(PAYLOAD_SIZE) (NLA_HDRLEN + NLA_ALIGN(PAYLOAD_SIZE)) -#define NL_A_U8_SIZE NL_ATTR_SIZE(sizeof(uint8_t)) -#define NL_A_U16_SIZE NL_ATTR_SIZE(sizeof(uint16_t)) -#define NL_A_U32_SIZE NL_ATTR_SIZE(sizeof(uint32_t)) -#define NL_A_U64_SIZE NL_ATTR_SIZE(sizeof(uint64_t)) -#define NL_A_U128_SIZE NL_ATTR_SIZE(sizeof(ovs_u128)) -#define NL_A_BE16_SIZE NL_ATTR_SIZE(sizeof(ovs_be16)) -#define NL_A_BE32_SIZE NL_ATTR_SIZE(sizeof(ovs_be32)) -#define NL_A_BE64_SIZE NL_ATTR_SIZE(sizeof(ovs_be64)) -#define NL_A_BE128_SIZE NL_ATTR_SIZE(sizeof(ovs_be128)) -#define NL_A_FLAG_SIZE NL_ATTR_SIZE(0) -#define NL_A_IPV6_SIZE NL_ATTR_SIZE(sizeof(struct in6_addr)) -#define NL_A_LL_ADDR_ETH_SIZE NL_ATTR_SIZE(sizeof(struct eth_addr)) -#define NL_A_LL_ADDR_IB_SIZE NL_ATTR_SIZE(sizeof(struct ib_addr)) - -bool nl_attr_oversized(size_t payload_size); - -/* Netlink attribute types. */ -enum nl_attr_type -{ - NL_A_NO_ATTR = 0, - NL_A_UNSPEC, - NL_A_U8, - NL_A_U16, - NL_A_BE16 = NL_A_U16, - NL_A_U32, - NL_A_BE32 = NL_A_U32, - NL_A_U64, - NL_A_BE64 = NL_A_U64, - NL_A_U128, - NL_A_BE128 = NL_A_U128, - NL_A_STRING, - NL_A_FLAG, - NL_A_IPV6, - NL_A_NESTED, - NL_A_LL_ADDR, - N_NL_ATTR_TYPES -}; - -/* Netlink attribute iteration. */ -static inline struct nlattr * -nl_attr_next(const struct nlattr *nla) -{ - return ALIGNED_CAST(struct nlattr *, - ((uint8_t *) nla + NLA_ALIGN(nla->nla_len))); -} - -static inline bool -nl_attr_is_valid(const struct nlattr *nla, size_t maxlen) -{ - return (maxlen >= sizeof *nla - && nla->nla_len >= sizeof *nla - && nla->nla_len <= maxlen); -} - -static inline size_t -nl_attr_len_pad(const struct nlattr *nla, size_t maxlen) -{ - size_t len = NLA_ALIGN(nla->nla_len); - - return len <= maxlen ? len : nla->nla_len; -} - -/* This macro is careful to check for attributes with bad lengths. */ -#define NL_ATTR_FOR_EACH(ITER, LEFT, ATTRS, ATTRS_LEN) \ - for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ - nl_attr_is_valid(ITER, LEFT); \ - (LEFT) -= nl_attr_len_pad(ITER, LEFT), (ITER) = nl_attr_next(ITER)) - - -/* This macro does not check for attributes with bad lengths. It should only - * be used with messages from trusted sources or with messages that have - * already been validated (e.g. with NL_ATTR_FOR_EACH). */ -#define NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, ATTRS, ATTRS_LEN) \ - for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ - (LEFT) > 0; \ - (LEFT) -= nl_attr_len_pad(ITER, LEFT), (ITER) = nl_attr_next(ITER)) - -/* These variants are convenient for iterating nested attributes. */ -#define NL_NESTED_FOR_EACH(ITER, LEFT, A) \ - NL_ATTR_FOR_EACH(ITER, LEFT, nl_attr_get(A), nl_attr_get_size(A)) -#define NL_NESTED_FOR_EACH_UNSAFE(ITER, LEFT, A) \ - NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, nl_attr_get(A), nl_attr_get_size(A)) - -/* Netlink attribute parsing. */ -int nl_attr_type(const struct nlattr *); -const void *nl_attr_get(const struct nlattr *); -size_t nl_attr_get_size(const struct nlattr *); -const void *nl_attr_get_unspec(const struct nlattr *, size_t size); -bool nl_attr_get_flag(const struct nlattr *); -uint8_t nl_attr_get_u8(const struct nlattr *); -uint16_t nl_attr_get_u16(const struct nlattr *); -uint32_t nl_attr_get_u32(const struct nlattr *); -uint64_t nl_attr_get_u64(const struct nlattr *); -ovs_u128 nl_attr_get_u128(const struct nlattr *); -ovs_be16 nl_attr_get_be16(const struct nlattr *); -ovs_be32 nl_attr_get_be32(const struct nlattr *); -ovs_be64 nl_attr_get_be64(const struct nlattr *); -ovs_be128 nl_attr_get_be128(const struct nlattr *); -struct in6_addr nl_attr_get_in6_addr(const struct nlattr *nla); -odp_port_t nl_attr_get_odp_port(const struct nlattr *); -const char *nl_attr_get_string(const struct nlattr *); -void nl_attr_get_nested(const struct nlattr *, struct ofpbuf *); -struct eth_addr nl_attr_get_eth_addr(const struct nlattr *nla); -struct ib_addr nl_attr_get_ib_addr(const struct nlattr *nla); - -/* Netlink attribute policy. - * - * Specifies how to parse a single attribute from a Netlink message payload. - */ -struct nl_policy -{ - enum nl_attr_type type; - size_t min_len, max_len; - bool optional; -}; - -#define NL_POLICY_FOR(TYPE) \ - .type = NL_A_UNSPEC, .min_len = sizeof(TYPE), .max_len = sizeof(TYPE) - -bool nl_attr_validate(const struct nlattr *, const struct nl_policy *); - -bool nl_policy_parse(const struct ofpbuf *, size_t offset, - const struct nl_policy[], - struct nlattr *[], size_t n_attrs); -bool nl_parse_nested(const struct nlattr *, const struct nl_policy[], - struct nlattr *[], size_t n_attrs); - -const struct nlattr *nl_attr_find(const struct ofpbuf *, size_t hdr_len, - uint16_t type); -const struct nlattr *nl_attr_find_nested(const struct nlattr *, uint16_t type); -const struct nlattr *nl_attr_find__(const struct nlattr *attrs, size_t size, - uint16_t type); - -#endif /* netlink.h */ Index: openvswitch-2.17.2/include/internal/netlink.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/netlink.h @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2015 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef NETLINK_H +#define NETLINK_H 1 + +/* Netlink message helpers. + * + * Netlink is a datagram-based network protocol primarily for communication + * between user processes and the kernel, and mainly on Linux. Netlink is + * specified in RFC 3549, "Linux Netlink as an IP Services Protocol". + * + * Netlink is not suitable for use in physical networks of heterogeneous + * machines because host byte order is used throughout. + * + * This header file defines helper functions for working with Netlink messages. + * For Netlink protocol definitions, see netlink-protocol.h. For + * Linux-specific definitions for Netlink sockets, see netlink-socket.h. + */ + +#include +#include +#include +#include +#include +#include "internal/netlink-protocol.h" +#include "openvswitch/types.h" + +struct ofpbuf; +struct nlattr; + +/* Accessing headers and data. */ +struct nlmsghdr *nl_msg_nlmsghdr(const struct ofpbuf *); +struct genlmsghdr *nl_msg_genlmsghdr(const struct ofpbuf *); +bool nl_msg_nlmsgerr(const struct ofpbuf *, int *error, const char **attr_msg); +void nl_msg_reserve(struct ofpbuf *, size_t); + +/* Appending and prepending headers and raw data. */ +void nl_msg_put_nlmsghdr(struct ofpbuf *, size_t expected_payload, + uint32_t type, uint32_t flags); +void nl_msg_put_genlmsghdr(struct ofpbuf *, size_t expected_payload, + int family, uint32_t flags, + uint8_t cmd, uint8_t version); +void nl_msg_put(struct ofpbuf *, const void *, size_t); +void *nl_msg_put_uninit(struct ofpbuf *, size_t); +void nl_msg_push(struct ofpbuf *, const void *, size_t); +void *nl_msg_push_uninit(struct ofpbuf *, size_t); + +/* Appending attributes. */ +void *nl_msg_put_unspec_uninit(struct ofpbuf *, uint16_t type, size_t); +void *nl_msg_put_unspec_zero(struct ofpbuf *, uint16_t type, size_t); +void nl_msg_put_unspec(struct ofpbuf *, uint16_t type, const void *, size_t); +void nl_msg_put_flag(struct ofpbuf *, uint16_t type); +void nl_msg_put_u8(struct ofpbuf *, uint16_t type, uint8_t value); +void nl_msg_put_u16(struct ofpbuf *, uint16_t type, uint16_t value); +void nl_msg_put_u32(struct ofpbuf *, uint16_t type, uint32_t value); +void nl_msg_put_u64(struct ofpbuf *, uint16_t type, uint64_t value); +void nl_msg_put_u128(struct ofpbuf *, uint16_t type, ovs_u128 value); +void nl_msg_put_be16(struct ofpbuf *, uint16_t type, ovs_be16 value); +void nl_msg_put_be32(struct ofpbuf *, uint16_t type, ovs_be32 value); +void nl_msg_put_be64(struct ofpbuf *, uint16_t type, ovs_be64 value); +void nl_msg_put_be128(struct ofpbuf *, uint16_t type, ovs_be128 value); +void nl_msg_put_in6_addr(struct ofpbuf *msg, uint16_t type, + const struct in6_addr *value); +void nl_msg_put_odp_port(struct ofpbuf *, uint16_t type, odp_port_t value); +void nl_msg_put_string__(struct ofpbuf *, uint16_t type, const char *value, + size_t len); +void nl_msg_put_string(struct ofpbuf *, uint16_t type, const char *value); + +size_t nl_msg_start_nested(struct ofpbuf *, uint16_t type); +void nl_msg_end_nested(struct ofpbuf *, size_t offset); +void nl_msg_cancel_nested(struct ofpbuf *, size_t offset); +bool nl_msg_end_non_empty_nested(struct ofpbuf *, size_t offset); +void nl_msg_put_nested(struct ofpbuf *, uint16_t type, + const void *data, size_t size); + +/* Prepending attributes. */ +void *nl_msg_push_unspec_uninit(struct ofpbuf *, uint16_t type, size_t); +void nl_msg_push_unspec(struct ofpbuf *, uint16_t type, const void *, size_t); +void nl_msg_push_flag(struct ofpbuf *, uint16_t type); +void nl_msg_push_u8(struct ofpbuf *, uint16_t type, uint8_t value); +void nl_msg_push_u16(struct ofpbuf *, uint16_t type, uint16_t value); +void nl_msg_push_u32(struct ofpbuf *, uint16_t type, uint32_t value); +void nl_msg_push_u64(struct ofpbuf *, uint16_t type, uint64_t value); +void nl_msg_push_u128(struct ofpbuf *, uint16_t type, ovs_u128 value); +void nl_msg_push_be16(struct ofpbuf *, uint16_t type, ovs_be16 value); +void nl_msg_push_be32(struct ofpbuf *, uint16_t type, ovs_be32 value); +void nl_msg_push_be64(struct ofpbuf *, uint16_t type, ovs_be64 value); +void nl_msg_push_be128(struct ofpbuf *, uint16_t type, ovs_be128 value); +void nl_msg_push_string(struct ofpbuf *, uint16_t type, const char *value); + +/* Separating buffers into individual messages. */ +struct nlmsghdr *nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg); + +/* Sizes of various attribute types, in bytes, including the attribute header + * and padding. + * + * A minimum-size attribute is 4 bytes long: 4 bytes of header, no bytes of + * payload, no padding. + * + * A maximum-size attribute is 65536 bytes long: 4 bytes of header, 65531 bytes + * of payload, 1 byte of padding. (Thus, NL_ATTR_SIZE() of a maximum length + * attribute payload does not fit in 16 bits.) */ +#define NL_ATTR_SIZE(PAYLOAD_SIZE) (NLA_HDRLEN + NLA_ALIGN(PAYLOAD_SIZE)) +#define NL_A_U8_SIZE NL_ATTR_SIZE(sizeof(uint8_t)) +#define NL_A_U16_SIZE NL_ATTR_SIZE(sizeof(uint16_t)) +#define NL_A_U32_SIZE NL_ATTR_SIZE(sizeof(uint32_t)) +#define NL_A_U64_SIZE NL_ATTR_SIZE(sizeof(uint64_t)) +#define NL_A_U128_SIZE NL_ATTR_SIZE(sizeof(ovs_u128)) +#define NL_A_BE16_SIZE NL_ATTR_SIZE(sizeof(ovs_be16)) +#define NL_A_BE32_SIZE NL_ATTR_SIZE(sizeof(ovs_be32)) +#define NL_A_BE64_SIZE NL_ATTR_SIZE(sizeof(ovs_be64)) +#define NL_A_BE128_SIZE NL_ATTR_SIZE(sizeof(ovs_be128)) +#define NL_A_FLAG_SIZE NL_ATTR_SIZE(0) +#define NL_A_IPV6_SIZE NL_ATTR_SIZE(sizeof(struct in6_addr)) +#define NL_A_LL_ADDR_ETH_SIZE NL_ATTR_SIZE(sizeof(struct eth_addr)) +#define NL_A_LL_ADDR_IB_SIZE NL_ATTR_SIZE(sizeof(struct ib_addr)) + +bool nl_attr_oversized(size_t payload_size); + +/* Netlink attribute types. */ +enum nl_attr_type +{ + NL_A_NO_ATTR = 0, + NL_A_UNSPEC, + NL_A_U8, + NL_A_U16, + NL_A_BE16 = NL_A_U16, + NL_A_U32, + NL_A_BE32 = NL_A_U32, + NL_A_U64, + NL_A_BE64 = NL_A_U64, + NL_A_U128, + NL_A_BE128 = NL_A_U128, + NL_A_STRING, + NL_A_FLAG, + NL_A_IPV6, + NL_A_NESTED, + NL_A_LL_ADDR, + N_NL_ATTR_TYPES +}; + +/* Netlink attribute iteration. */ +static inline struct nlattr * +nl_attr_next(const struct nlattr *nla) +{ + return ALIGNED_CAST(struct nlattr *, + ((uint8_t *) nla + NLA_ALIGN(nla->nla_len))); +} + +static inline bool +nl_attr_is_valid(const struct nlattr *nla, size_t maxlen) +{ + return (maxlen >= sizeof *nla + && nla->nla_len >= sizeof *nla + && nla->nla_len <= maxlen); +} + +static inline size_t +nl_attr_len_pad(const struct nlattr *nla, size_t maxlen) +{ + size_t len = NLA_ALIGN(nla->nla_len); + + return len <= maxlen ? len : nla->nla_len; +} + +/* This macro is careful to check for attributes with bad lengths. */ +#define NL_ATTR_FOR_EACH(ITER, LEFT, ATTRS, ATTRS_LEN) \ + for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ + nl_attr_is_valid(ITER, LEFT); \ + (LEFT) -= nl_attr_len_pad(ITER, LEFT), (ITER) = nl_attr_next(ITER)) + + +/* This macro does not check for attributes with bad lengths. It should only + * be used with messages from trusted sources or with messages that have + * already been validated (e.g. with NL_ATTR_FOR_EACH). */ +#define NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, ATTRS, ATTRS_LEN) \ + for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ + (LEFT) > 0; \ + (LEFT) -= nl_attr_len_pad(ITER, LEFT), (ITER) = nl_attr_next(ITER)) + +/* These variants are convenient for iterating nested attributes. */ +#define NL_NESTED_FOR_EACH(ITER, LEFT, A) \ + NL_ATTR_FOR_EACH(ITER, LEFT, nl_attr_get(A), nl_attr_get_size(A)) +#define NL_NESTED_FOR_EACH_UNSAFE(ITER, LEFT, A) \ + NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, nl_attr_get(A), nl_attr_get_size(A)) + +/* Netlink attribute parsing. */ +int nl_attr_type(const struct nlattr *); +const void *nl_attr_get(const struct nlattr *); +size_t nl_attr_get_size(const struct nlattr *); +const void *nl_attr_get_unspec(const struct nlattr *, size_t size); +bool nl_attr_get_flag(const struct nlattr *); +uint8_t nl_attr_get_u8(const struct nlattr *); +uint16_t nl_attr_get_u16(const struct nlattr *); +uint32_t nl_attr_get_u32(const struct nlattr *); +uint64_t nl_attr_get_u64(const struct nlattr *); +ovs_u128 nl_attr_get_u128(const struct nlattr *); +ovs_be16 nl_attr_get_be16(const struct nlattr *); +ovs_be32 nl_attr_get_be32(const struct nlattr *); +ovs_be64 nl_attr_get_be64(const struct nlattr *); +ovs_be128 nl_attr_get_be128(const struct nlattr *); +struct in6_addr nl_attr_get_in6_addr(const struct nlattr *nla); +odp_port_t nl_attr_get_odp_port(const struct nlattr *); +const char *nl_attr_get_string(const struct nlattr *); +void nl_attr_get_nested(const struct nlattr *, struct ofpbuf *); +struct eth_addr nl_attr_get_eth_addr(const struct nlattr *nla); +struct ib_addr nl_attr_get_ib_addr(const struct nlattr *nla); + +/* Netlink attribute policy. + * + * Specifies how to parse a single attribute from a Netlink message payload. + */ +struct nl_policy +{ + enum nl_attr_type type; + size_t min_len, max_len; + bool optional; +}; + +#define NL_POLICY_FOR(TYPE) \ + .type = NL_A_UNSPEC, .min_len = sizeof(TYPE), .max_len = sizeof(TYPE) + +bool nl_attr_validate(const struct nlattr *, const struct nl_policy *); + +bool nl_policy_parse(const struct ofpbuf *, size_t offset, + const struct nl_policy[], + struct nlattr *[], size_t n_attrs); +bool nl_parse_nested(const struct nlattr *, const struct nl_policy[], + struct nlattr *[], size_t n_attrs); + +const struct nlattr *nl_attr_find(const struct ofpbuf *, size_t hdr_len, + uint16_t type); +const struct nlattr *nl_attr_find_nested(const struct nlattr *, uint16_t type); +const struct nlattr *nl_attr_find__(const struct nlattr *attrs, size_t size, + uint16_t type); + +#endif /* netlink.h */ Index: openvswitch-2.17.2/lib/nx-match.h =================================================================== --- openvswitch-2.17.2.orig/lib/nx-match.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2010-2017, 2020 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 NX_MATCH_H -#define NX_MATCH_H 1 - -#include -#include -#include -#include "openvswitch/compiler.h" -#include "flow.h" -#include "openvswitch/meta-flow.h" -#include "openvswitch/ofp-errors.h" -#include "openvswitch/types.h" - -struct ds; -struct match; -struct ofpact_reg_move; -struct ofpact_reg_load; -struct ofpact_stack; -struct ofpbuf; -struct nx_action_reg_load; -struct nx_action_reg_move; -struct vl_mff_map; - - -/* Nicira Extended Match (NXM) flexible flow match helper functions. - * - * See include/openflow/nicira-ext.h for NXM specification. - */ - -char * mf_parse_field(const struct mf_field **field, const char *s) - OVS_WARN_UNUSED_RESULT; -void mf_format_subfield(const struct mf_subfield *, struct ds *); -char *mf_parse_subfield__(struct mf_subfield *sf, const char **s) - OVS_WARN_UNUSED_RESULT; -char *mf_parse_subfield(struct mf_subfield *, const char *s) - OVS_WARN_UNUSED_RESULT; - -/* Decoding matches. */ -enum ofperr nx_pull_match(struct ofpbuf *, unsigned int match_len, - struct match *, ovs_be64 *cookie, - ovs_be64 *cookie_mask, bool pipeline_fields_only, - const struct tun_table *, const struct vl_mff_map *); -enum ofperr nx_pull_match_loose(struct ofpbuf *, unsigned int match_len, - struct match *, ovs_be64 *cookie, - ovs_be64 *cookie_mask, - bool pipeline_fields_only, - const struct tun_table *); -enum ofperr oxm_pull_match(struct ofpbuf *, bool pipeline_fields_only, - const struct tun_table *, const struct vl_mff_map *, - struct match *); -enum ofperr oxm_pull_match_loose(struct ofpbuf *, bool pipeline_fields_only, - const struct tun_table *, struct match *); -enum ofperr oxm_decode_match(const void *, size_t, bool, - const struct tun_table *, - const struct vl_mff_map *, struct match *); -enum ofperr oxm_pull_field_array(const void *, size_t fields_len, - struct field_array *); - -/* Encoding matches. */ -int nx_put_match(struct ofpbuf *, const struct match *, - ovs_be64 cookie, ovs_be64 cookie_mask); -int oxm_put_match(struct ofpbuf *, const struct match *, enum ofp_version); -void oxm_put_raw(struct ofpbuf *, const struct match *, enum ofp_version); -void oxm_format_field_array(struct ds *, const struct field_array *); -int oxm_put_field_array(struct ofpbuf *, const struct field_array *, - enum ofp_version version); - -/* Decoding and encoding OXM/NXM headers (just a field ID) or entries (a field - * ID followed by a value and possibly a mask). */ -enum ofperr nx_pull_entry(struct ofpbuf *, const struct vl_mff_map *, - const struct mf_field **, union mf_value *value, - union mf_value *mask, bool is_action); -enum ofperr nx_pull_header(struct ofpbuf *, const struct vl_mff_map *, - const struct mf_field **, bool *masked); -void nxm_put_entry_raw(struct ofpbuf *, enum mf_field_id field, - enum ofp_version version, const void *value, - const void *mask, size_t n_bytes); -void nx_put_entry(struct ofpbuf *, const struct mf_field *, enum ofp_version, - const union mf_value *value, const union mf_value *mask); -void nx_put_header(struct ofpbuf *, enum mf_field_id, enum ofp_version, - bool masked); -void nx_put_mff_header(struct ofpbuf *, const struct mf_field *, - enum ofp_version, bool); - -/* NXM and OXM protocol headers values. - * - * These are often alternatives to nx_pull_entry/header() and - * nx_put_entry/header() for decoding and encoding OXM/NXM. In those cases, - * the nx_*() functions should be preferred because they can support the 64-bit - * "experimenter" OXM format (even though it is not yet implemented). */ -uint32_t mf_nxm_header(enum mf_field_id); -uint32_t nxm_header_from_mff(const struct mf_field *); -const struct mf_field *mf_from_nxm_header(uint32_t nxm_header, - const struct vl_mff_map *); - -char *nx_match_to_string(const uint8_t *, unsigned int match_len); -char *oxm_match_to_string(const struct ofpbuf *, unsigned int match_len); -int nx_match_from_string(const char *, struct ofpbuf *); -int oxm_match_from_string(const char *, struct ofpbuf *); - -void nx_format_field_name(enum mf_field_id, enum ofp_version, struct ds *); - -char *nxm_parse_reg_move(struct ofpact_reg_move *, const char *) - OVS_WARN_UNUSED_RESULT; - -void nxm_format_reg_move(const struct ofpact_reg_move *, struct ds *); - -enum ofperr nxm_reg_move_check(const struct ofpact_reg_move *, - const struct match *); - -void nxm_reg_load(const struct mf_subfield *, uint64_t src_data, - struct flow *, struct flow_wildcards *); - -char *nxm_parse_stack_action(struct ofpact_stack *, const char *) - OVS_WARN_UNUSED_RESULT; - -void nxm_format_stack_push(const struct ofpact_stack *, struct ds *); -void nxm_format_stack_pop(const struct ofpact_stack *, struct ds *); - -enum ofperr nxm_stack_push_check(const struct ofpact_stack *, - const struct match *); -enum ofperr nxm_stack_pop_check(const struct ofpact_stack *, - const struct match *); -void nx_stack_push(struct ofpbuf *stack, const void *v, uint8_t bytes); -void nx_stack_push_bottom(struct ofpbuf *stack, const void *v, uint8_t bytes); -void *nx_stack_pop(struct ofpbuf *stack, uint8_t *bytes); - -void nxm_execute_stack_push(const struct ofpact_stack *, - const struct flow *, struct flow_wildcards *, - struct ofpbuf *); -bool nxm_execute_stack_pop(const struct ofpact_stack *, - struct flow *, struct flow_wildcards *, - struct ofpbuf *); - -ovs_be64 oxm_bitmap_from_mf_bitmap(const struct mf_bitmap *, enum ofp_version); -struct mf_bitmap oxm_bitmap_to_mf_bitmap(ovs_be64 oxm_bitmap, - enum ofp_version); -struct mf_bitmap oxm_writable_fields(void); -struct mf_bitmap oxm_matchable_fields(void); -struct mf_bitmap oxm_maskable_fields(void); - -/* Dealing with the 'ofs_nbits' members in several Nicira extensions. */ - -static inline ovs_be16 -nxm_encode_ofs_nbits(int ofs, int n_bits) -{ - return htons((ofs << 6) | (n_bits - 1)); -} - -static inline int -nxm_decode_ofs(ovs_be16 ofs_nbits) -{ - return ntohs(ofs_nbits) >> 6; -} - -static inline int -nxm_decode_n_bits(ovs_be16 ofs_nbits) -{ - return (ntohs(ofs_nbits) & 0x3f) + 1; -} - -/* This is my guess at the length of a "typical" nx_match, for use in - * predicting space requirements. */ -#define NXM_TYPICAL_LEN 64 - -#endif /* nx-match.h */ Index: openvswitch-2.17.2/include/internal/nx-match.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/nx-match.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2010-2017, 2020 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 NX_MATCH_H +#define NX_MATCH_H 1 + +#include +#include +#include +#include "openvswitch/compiler.h" +#include "internal/flow.h" +#include "openvswitch/meta-flow.h" +#include "openvswitch/ofp-errors.h" +#include "openvswitch/types.h" + +struct ds; +struct match; +struct ofpact_reg_move; +struct ofpact_reg_load; +struct ofpact_stack; +struct ofpbuf; +struct nx_action_reg_load; +struct nx_action_reg_move; +struct vl_mff_map; + + +/* Nicira Extended Match (NXM) flexible flow match helper functions. + * + * See include/openflow/nicira-ext.h for NXM specification. + */ + +char * mf_parse_field(const struct mf_field **field, const char *s) + OVS_WARN_UNUSED_RESULT; +void mf_format_subfield(const struct mf_subfield *, struct ds *); +char *mf_parse_subfield__(struct mf_subfield *sf, const char **s) + OVS_WARN_UNUSED_RESULT; +char *mf_parse_subfield(struct mf_subfield *, const char *s) + OVS_WARN_UNUSED_RESULT; + +/* Decoding matches. */ +enum ofperr nx_pull_match(struct ofpbuf *, unsigned int match_len, + struct match *, ovs_be64 *cookie, + ovs_be64 *cookie_mask, bool pipeline_fields_only, + const struct tun_table *, const struct vl_mff_map *); +enum ofperr nx_pull_match_loose(struct ofpbuf *, unsigned int match_len, + struct match *, ovs_be64 *cookie, + ovs_be64 *cookie_mask, + bool pipeline_fields_only, + const struct tun_table *); +enum ofperr oxm_pull_match(struct ofpbuf *, bool pipeline_fields_only, + const struct tun_table *, const struct vl_mff_map *, + struct match *); +enum ofperr oxm_pull_match_loose(struct ofpbuf *, bool pipeline_fields_only, + const struct tun_table *, struct match *); +enum ofperr oxm_decode_match(const void *, size_t, bool, + const struct tun_table *, + const struct vl_mff_map *, struct match *); +enum ofperr oxm_pull_field_array(const void *, size_t fields_len, + struct field_array *); + +/* Encoding matches. */ +int nx_put_match(struct ofpbuf *, const struct match *, + ovs_be64 cookie, ovs_be64 cookie_mask); +int oxm_put_match(struct ofpbuf *, const struct match *, enum ofp_version); +void oxm_put_raw(struct ofpbuf *, const struct match *, enum ofp_version); +void oxm_format_field_array(struct ds *, const struct field_array *); +int oxm_put_field_array(struct ofpbuf *, const struct field_array *, + enum ofp_version version); + +/* Decoding and encoding OXM/NXM headers (just a field ID) or entries (a field + * ID followed by a value and possibly a mask). */ +enum ofperr nx_pull_entry(struct ofpbuf *, const struct vl_mff_map *, + const struct mf_field **, union mf_value *value, + union mf_value *mask, bool is_action); +enum ofperr nx_pull_header(struct ofpbuf *, const struct vl_mff_map *, + const struct mf_field **, bool *masked); +void nxm_put_entry_raw(struct ofpbuf *, enum mf_field_id field, + enum ofp_version version, const void *value, + const void *mask, size_t n_bytes); +void nx_put_entry(struct ofpbuf *, const struct mf_field *, enum ofp_version, + const union mf_value *value, const union mf_value *mask); +void nx_put_header(struct ofpbuf *, enum mf_field_id, enum ofp_version, + bool masked); +void nx_put_mff_header(struct ofpbuf *, const struct mf_field *, + enum ofp_version, bool); + +/* NXM and OXM protocol headers values. + * + * These are often alternatives to nx_pull_entry/header() and + * nx_put_entry/header() for decoding and encoding OXM/NXM. In those cases, + * the nx_*() functions should be preferred because they can support the 64-bit + * "experimenter" OXM format (even though it is not yet implemented). */ +uint32_t mf_nxm_header(enum mf_field_id); +uint32_t nxm_header_from_mff(const struct mf_field *); +const struct mf_field *mf_from_nxm_header(uint32_t nxm_header, + const struct vl_mff_map *); + +char *nx_match_to_string(const uint8_t *, unsigned int match_len); +char *oxm_match_to_string(const struct ofpbuf *, unsigned int match_len); +int nx_match_from_string(const char *, struct ofpbuf *); +int oxm_match_from_string(const char *, struct ofpbuf *); + +void nx_format_field_name(enum mf_field_id, enum ofp_version, struct ds *); + +char *nxm_parse_reg_move(struct ofpact_reg_move *, const char *) + OVS_WARN_UNUSED_RESULT; + +void nxm_format_reg_move(const struct ofpact_reg_move *, struct ds *); + +enum ofperr nxm_reg_move_check(const struct ofpact_reg_move *, + const struct match *); + +void nxm_reg_load(const struct mf_subfield *, uint64_t src_data, + struct flow *, struct flow_wildcards *); + +char *nxm_parse_stack_action(struct ofpact_stack *, const char *) + OVS_WARN_UNUSED_RESULT; + +void nxm_format_stack_push(const struct ofpact_stack *, struct ds *); +void nxm_format_stack_pop(const struct ofpact_stack *, struct ds *); + +enum ofperr nxm_stack_push_check(const struct ofpact_stack *, + const struct match *); +enum ofperr nxm_stack_pop_check(const struct ofpact_stack *, + const struct match *); +void nx_stack_push(struct ofpbuf *stack, const void *v, uint8_t bytes); +void nx_stack_push_bottom(struct ofpbuf *stack, const void *v, uint8_t bytes); +void *nx_stack_pop(struct ofpbuf *stack, uint8_t *bytes); + +void nxm_execute_stack_push(const struct ofpact_stack *, + const struct flow *, struct flow_wildcards *, + struct ofpbuf *); +bool nxm_execute_stack_pop(const struct ofpact_stack *, + struct flow *, struct flow_wildcards *, + struct ofpbuf *); + +ovs_be64 oxm_bitmap_from_mf_bitmap(const struct mf_bitmap *, enum ofp_version); +struct mf_bitmap oxm_bitmap_to_mf_bitmap(ovs_be64 oxm_bitmap, + enum ofp_version); +struct mf_bitmap oxm_writable_fields(void); +struct mf_bitmap oxm_matchable_fields(void); +struct mf_bitmap oxm_maskable_fields(void); + +/* Dealing with the 'ofs_nbits' members in several Nicira extensions. */ + +static inline ovs_be16 +nxm_encode_ofs_nbits(int ofs, int n_bits) +{ + return htons((ofs << 6) | (n_bits - 1)); +} + +static inline int +nxm_decode_ofs(ovs_be16 ofs_nbits) +{ + return ntohs(ofs_nbits) >> 6; +} + +static inline int +nxm_decode_n_bits(ovs_be16 ofs_nbits) +{ + return (ntohs(ofs_nbits) & 0x3f) + 1; +} + +/* This is my guess at the length of a "typical" nx_match, for use in + * predicting space requirements. */ +#define NXM_TYPICAL_LEN 64 + +#endif /* nx-match.h */ Index: openvswitch-2.17.2/lib/ovs-atomic-clang.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-clang.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This header implements atomic operation primitives on Clang. */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#define OVS_ATOMIC_CLANG_IMPL 1 - -#define ATOMIC(TYPE) _Atomic(TYPE) - -#define ATOMIC_VAR_INIT(VALUE) (VALUE) - -#define atomic_init(OBJECT, VALUE) __c11_atomic_init(OBJECT, VALUE) - -/* Clang hard-codes these exact values internally but does not appear to - * export any names for them. */ -typedef enum { - memory_order_relaxed = 0, - memory_order_consume = 1, - memory_order_acquire = 2, - memory_order_release = 3, - memory_order_acq_rel = 4, - memory_order_seq_cst = 5 -} memory_order; - -#define atomic_thread_fence(ORDER) __c11_atomic_thread_fence(ORDER) -#define atomic_signal_fence(ORDER) __c11_atomic_signal_fence(ORDER) - -#define atomic_store(DST, SRC) \ - atomic_store_explicit(DST, SRC, memory_order_seq_cst) -#define atomic_store_explicit(DST, SRC, ORDER) \ - __c11_atomic_store(DST, SRC, ORDER) - - -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) -#define atomic_read_explicit(SRC, DST, ORDER) \ - (*(DST) = __c11_atomic_load(SRC, ORDER), \ - (void) 0) - -#define atomic_compare_exchange_strong(DST, EXP, SRC) \ - atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ - __c11_atomic_compare_exchange_strong(DST, EXP, SRC, ORD1, ORD2) - -#define atomic_compare_exchange_weak(DST, EXP, SRC) \ - atomic_compare_exchange_weak_explicit(DST, EXP, SRC, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -#define atomic_compare_exchange_weak_explicit(DST, EXP, SRC, ORD1, ORD2) \ - __c11_atomic_compare_exchange_weak(DST, EXP, SRC, ORD1, ORD2) - -#define atomic_exchange(RMW, ARG) \ - atomic_exchange_explicit(RMW, ARG, memory_order_seq_cst) -#define atomic_exchange_explicit(RMW, ARG, ORDER) \ - __c11_atomic_exchange(RMW, ARG, ORDER) - -#define atomic_add(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_sub(RMW, ARG, ORIG) \ - atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_or(RMW, ARG, ORIG) \ - atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_xor(RMW, ARG, ORIG) \ - atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_and(RMW, ARG, ORIG) \ - atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = __c11_atomic_fetch_add(RMW, ARG, ORDER), (void) 0) -#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = __c11_atomic_fetch_sub(RMW, ARG, ORDER), (void) 0) -#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = __c11_atomic_fetch_or(RMW, ARG, ORDER), (void) 0) -#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = __c11_atomic_fetch_xor(RMW, ARG, ORDER), (void) 0) -#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = __c11_atomic_fetch_and(RMW, ARG, ORDER), (void) 0) - -#include "ovs-atomic-flag-gcc4.7+.h" Index: openvswitch-2.17.2/include/internal/ovs-atomic-clang.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-clang.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header implements atomic operation primitives on Clang. */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#define OVS_ATOMIC_CLANG_IMPL 1 + +#define ATOMIC(TYPE) _Atomic(TYPE) + +#define ATOMIC_VAR_INIT(VALUE) (VALUE) + +#define atomic_init(OBJECT, VALUE) __c11_atomic_init(OBJECT, VALUE) + +/* Clang hard-codes these exact values internally but does not appear to + * export any names for them. */ +typedef enum { + memory_order_relaxed = 0, + memory_order_consume = 1, + memory_order_acquire = 2, + memory_order_release = 3, + memory_order_acq_rel = 4, + memory_order_seq_cst = 5 +} memory_order; + +#define atomic_thread_fence(ORDER) __c11_atomic_thread_fence(ORDER) +#define atomic_signal_fence(ORDER) __c11_atomic_signal_fence(ORDER) + +#define atomic_store(DST, SRC) \ + atomic_store_explicit(DST, SRC, memory_order_seq_cst) +#define atomic_store_explicit(DST, SRC, ORDER) \ + __c11_atomic_store(DST, SRC, ORDER) + + +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) +#define atomic_read_explicit(SRC, DST, ORDER) \ + (*(DST) = __c11_atomic_load(SRC, ORDER), \ + (void) 0) + +#define atomic_compare_exchange_strong(DST, EXP, SRC) \ + atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ + memory_order_seq_cst, \ + memory_order_seq_cst) +#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ + __c11_atomic_compare_exchange_strong(DST, EXP, SRC, ORD1, ORD2) + +#define atomic_compare_exchange_weak(DST, EXP, SRC) \ + atomic_compare_exchange_weak_explicit(DST, EXP, SRC, \ + memory_order_seq_cst, \ + memory_order_seq_cst) +#define atomic_compare_exchange_weak_explicit(DST, EXP, SRC, ORD1, ORD2) \ + __c11_atomic_compare_exchange_weak(DST, EXP, SRC, ORD1, ORD2) + +#define atomic_exchange(RMW, ARG) \ + atomic_exchange_explicit(RMW, ARG, memory_order_seq_cst) +#define atomic_exchange_explicit(RMW, ARG, ORDER) \ + __c11_atomic_exchange(RMW, ARG, ORDER) + +#define atomic_add(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_sub(RMW, ARG, ORIG) \ + atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_or(RMW, ARG, ORIG) \ + atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_xor(RMW, ARG, ORIG) \ + atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_and(RMW, ARG, ORIG) \ + atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = __c11_atomic_fetch_add(RMW, ARG, ORDER), (void) 0) +#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = __c11_atomic_fetch_sub(RMW, ARG, ORDER), (void) 0) +#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = __c11_atomic_fetch_or(RMW, ARG, ORDER), (void) 0) +#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = __c11_atomic_fetch_xor(RMW, ARG, ORDER), (void) 0) +#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = __c11_atomic_fetch_and(RMW, ARG, ORDER), (void) 0) + +#include "internal/ovs-atomic-flag-gcc4.7+.h" Index: openvswitch-2.17.2/lib/ovs-atomic-gcc4+.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-gcc4+.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This header implements atomic operation primitives on GCC 4.x. */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#include "ovs-atomic-locked.h" -#define OVS_ATOMIC_GCC4P_IMPL 1 - -#define ATOMIC(TYPE) TYPE - -#define ATOMIC_BOOL_LOCK_FREE 2 -#define ATOMIC_CHAR_LOCK_FREE 2 -#define ATOMIC_SHORT_LOCK_FREE 2 -#define ATOMIC_INT_LOCK_FREE 2 -#define ATOMIC_LONG_LOCK_FREE (ULONG_MAX <= UINTPTR_MAX ? 2 : 0) -#define ATOMIC_LLONG_LOCK_FREE (ULLONG_MAX <= UINTPTR_MAX ? 2 : 0) -#define ATOMIC_POINTER_LOCK_FREE 2 - -typedef enum { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -} memory_order; - -#define IS_LOCKLESS_ATOMIC(OBJECT) (sizeof(OBJECT) <= sizeof(void *)) - -#define ATOMIC_VAR_INIT(VALUE) VALUE -#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) - -static inline void -atomic_thread_fence(memory_order order) -{ - if (order != memory_order_relaxed) { - __sync_synchronize(); - } -} - -static inline void -atomic_thread_fence_if_seq_cst(memory_order order) -{ - if (order == memory_order_seq_cst) { - __sync_synchronize(); - } -} - -static inline void -atomic_signal_fence(memory_order order) -{ - if (order != memory_order_relaxed) { - asm volatile("" : : : "memory"); - } -} - -#define atomic_is_lock_free(OBJ) \ - ((void) *(OBJ), \ - IS_LOCKLESS_ATOMIC(*(OBJ)) ? 2 : 0) - -#define atomic_store(DST, SRC) \ - atomic_store_explicit(DST, SRC, memory_order_seq_cst) -#define atomic_store_explicit(DST, SRC, ORDER) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(SRC) src__ = (SRC); \ - \ - if (IS_LOCKLESS_ATOMIC(*dst__)) { \ - atomic_thread_fence(ORDER); \ - *(typeof(*(DST)) volatile *)dst__ = src__; \ - atomic_thread_fence_if_seq_cst(ORDER); \ - } else { \ - atomic_store_locked(dst__, src__); \ - } \ - (void) 0; \ - }) -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) -#define atomic_read_explicit(SRC, DST, ORDER) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(SRC) src__ = (SRC); \ - \ - if (IS_LOCKLESS_ATOMIC(*src__)) { \ - atomic_thread_fence_if_seq_cst(ORDER); \ - *dst__ = *(typeof(*(SRC)) volatile *)src__; \ - } else { \ - atomic_read_locked(src__, dst__); \ - } \ - (void) 0; \ - }) - -#define atomic_compare_exchange_strong(DST, EXP, SRC) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(EXP) expp__ = (EXP); \ - typeof(SRC) src__ = (SRC); \ - typeof(SRC) exp__ = *expp__; \ - typeof(SRC) ret__; \ - \ - ret__ = __sync_val_compare_and_swap(dst__, exp__, src__); \ - if (ret__ != exp__) { \ - *expp__ = ret__; \ - } \ - ret__ == exp__; \ - }) -#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ - ((void) (ORD1), (void) (ORD2), \ - atomic_compare_exchange_strong(DST, EXP, SRC)) -#define atomic_compare_exchange_weak \ - atomic_compare_exchange_strong -#define atomic_compare_exchange_weak_explicit \ - atomic_compare_exchange_strong_explicit - -#define atomic_exchange_explicit(DST, SRC, ORDER) \ - __sync_lock_test_and_set(DST, SRC) -#define atomic_exchange(DST, SRC) \ - atomic_exchange_explicit(DST, SRC, memory_order_seq_cst) - -#define atomic_op__(RMW, OP, ARG, ORIG) \ - ({ \ - typeof(RMW) rmw__ = (RMW); \ - typeof(ARG) arg__ = (ARG); \ - typeof(ORIG) orig__ = (ORIG); \ - \ - if (IS_LOCKLESS_ATOMIC(*rmw__)) { \ - *orig__ = __sync_fetch_and_##OP(rmw__, arg__); \ - } else { \ - atomic_op_locked(rmw__, OP, arg__, orig__); \ - } \ - (void) 0; \ - }) - -#define atomic_add(RMW, ARG, ORIG) atomic_op__(RMW, add, ARG, ORIG) -#define atomic_sub(RMW, ARG, ORIG) atomic_op__(RMW, sub, ARG, ORIG) -#define atomic_or(RMW, ARG, ORIG) atomic_op__(RMW, or, ARG, ORIG) -#define atomic_xor(RMW, ARG, ORIG) atomic_op__(RMW, xor, ARG, ORIG) -#define atomic_and(RMW, ARG, ORIG) atomic_op__(RMW, and, ARG, ORIG) - -#define atomic_add_explicit(RMW, OPERAND, ORIG, ORDER) \ - ((void) (ORDER), atomic_add(RMW, OPERAND, ORIG)) -#define atomic_sub_explicit(RMW, OPERAND, ORIG, ORDER) \ - ((void) (ORDER), atomic_sub(RMW, OPERAND, ORIG)) -#define atomic_or_explicit(RMW, OPERAND, ORIG, ORDER) \ - ((void) (ORDER), atomic_or(RMW, OPERAND, ORIG)) -#define atomic_xor_explicit(RMW, OPERAND, ORIG, ORDER) \ - ((void) (ORDER), atomic_xor(RMW, OPERAND, ORIG)) -#define atomic_and_explicit(RMW, OPERAND, ORIG, ORDER) \ - ((void) (ORDER), atomic_and(RMW, OPERAND, ORIG)) - -/* atomic_flag */ - -typedef struct { - int b; -} atomic_flag; -#define ATOMIC_FLAG_INIT { false } - -static inline bool -atomic_flag_test_and_set_explicit(volatile atomic_flag *object, - memory_order order) -{ - bool old; - - /* __sync_lock_test_and_set() by itself is an acquire barrier. - * For anything higher additional barriers are needed. */ - if (order > memory_order_acquire) { - atomic_thread_fence(order); - } - old = __sync_lock_test_and_set(&object->b, 1); - atomic_thread_fence_if_seq_cst(order); - - return old; -} - -#define atomic_flag_test_and_set(FLAG) \ - atomic_flag_test_and_set_explicit(FLAG, memory_order_seq_cst) - -static inline void -atomic_flag_clear_explicit(volatile atomic_flag *object, - memory_order order) -{ - /* __sync_lock_release() by itself is a release barrier. For - * anything else additional barrier may be needed. */ - if (order != memory_order_release) { - atomic_thread_fence(order); - } - __sync_lock_release(&object->b); - atomic_thread_fence_if_seq_cst(order); -} - -#define atomic_flag_clear(FLAG) \ - atomic_flag_clear_explicit(FLAG, memory_order_seq_cst) Index: openvswitch-2.17.2/include/internal/ovs-atomic-gcc4+.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-gcc4+.h @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header implements atomic operation primitives on GCC 4.x. */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#include "internal/ovs-atomic-locked.h" +#define OVS_ATOMIC_GCC4P_IMPL 1 + +#define ATOMIC(TYPE) TYPE + +#define ATOMIC_BOOL_LOCK_FREE 2 +#define ATOMIC_CHAR_LOCK_FREE 2 +#define ATOMIC_SHORT_LOCK_FREE 2 +#define ATOMIC_INT_LOCK_FREE 2 +#define ATOMIC_LONG_LOCK_FREE (ULONG_MAX <= UINTPTR_MAX ? 2 : 0) +#define ATOMIC_LLONG_LOCK_FREE (ULLONG_MAX <= UINTPTR_MAX ? 2 : 0) +#define ATOMIC_POINTER_LOCK_FREE 2 + +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +} memory_order; + +#define IS_LOCKLESS_ATOMIC(OBJECT) (sizeof(OBJECT) <= sizeof(void *)) + +#define ATOMIC_VAR_INIT(VALUE) VALUE +#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) + +static inline void +atomic_thread_fence(memory_order order) +{ + if (order != memory_order_relaxed) { + __sync_synchronize(); + } +} + +static inline void +atomic_thread_fence_if_seq_cst(memory_order order) +{ + if (order == memory_order_seq_cst) { + __sync_synchronize(); + } +} + +static inline void +atomic_signal_fence(memory_order order) +{ + if (order != memory_order_relaxed) { + asm volatile("" : : : "memory"); + } +} + +#define atomic_is_lock_free(OBJ) \ + ((void) *(OBJ), \ + IS_LOCKLESS_ATOMIC(*(OBJ)) ? 2 : 0) + +#define atomic_store(DST, SRC) \ + atomic_store_explicit(DST, SRC, memory_order_seq_cst) +#define atomic_store_explicit(DST, SRC, ORDER) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(SRC) src__ = (SRC); \ + \ + if (IS_LOCKLESS_ATOMIC(*dst__)) { \ + atomic_thread_fence(ORDER); \ + *(typeof(*(DST)) volatile *)dst__ = src__; \ + atomic_thread_fence_if_seq_cst(ORDER); \ + } else { \ + atomic_store_locked(dst__, src__); \ + } \ + (void) 0; \ + }) +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) +#define atomic_read_explicit(SRC, DST, ORDER) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(SRC) src__ = (SRC); \ + \ + if (IS_LOCKLESS_ATOMIC(*src__)) { \ + atomic_thread_fence_if_seq_cst(ORDER); \ + *dst__ = *(typeof(*(SRC)) volatile *)src__; \ + } else { \ + atomic_read_locked(src__, dst__); \ + } \ + (void) 0; \ + }) + +#define atomic_compare_exchange_strong(DST, EXP, SRC) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(EXP) expp__ = (EXP); \ + typeof(SRC) src__ = (SRC); \ + typeof(SRC) exp__ = *expp__; \ + typeof(SRC) ret__; \ + \ + ret__ = __sync_val_compare_and_swap(dst__, exp__, src__); \ + if (ret__ != exp__) { \ + *expp__ = ret__; \ + } \ + ret__ == exp__; \ + }) +#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ + ((void) (ORD1), (void) (ORD2), \ + atomic_compare_exchange_strong(DST, EXP, SRC)) +#define atomic_compare_exchange_weak \ + atomic_compare_exchange_strong +#define atomic_compare_exchange_weak_explicit \ + atomic_compare_exchange_strong_explicit + +#define atomic_exchange_explicit(DST, SRC, ORDER) \ + __sync_lock_test_and_set(DST, SRC) +#define atomic_exchange(DST, SRC) \ + atomic_exchange_explicit(DST, SRC, memory_order_seq_cst) + +#define atomic_op__(RMW, OP, ARG, ORIG) \ + ({ \ + typeof(RMW) rmw__ = (RMW); \ + typeof(ARG) arg__ = (ARG); \ + typeof(ORIG) orig__ = (ORIG); \ + \ + if (IS_LOCKLESS_ATOMIC(*rmw__)) { \ + *orig__ = __sync_fetch_and_##OP(rmw__, arg__); \ + } else { \ + atomic_op_locked(rmw__, OP, arg__, orig__); \ + } \ + (void) 0; \ + }) + +#define atomic_add(RMW, ARG, ORIG) atomic_op__(RMW, add, ARG, ORIG) +#define atomic_sub(RMW, ARG, ORIG) atomic_op__(RMW, sub, ARG, ORIG) +#define atomic_or(RMW, ARG, ORIG) atomic_op__(RMW, or, ARG, ORIG) +#define atomic_xor(RMW, ARG, ORIG) atomic_op__(RMW, xor, ARG, ORIG) +#define atomic_and(RMW, ARG, ORIG) atomic_op__(RMW, and, ARG, ORIG) + +#define atomic_add_explicit(RMW, OPERAND, ORIG, ORDER) \ + ((void) (ORDER), atomic_add(RMW, OPERAND, ORIG)) +#define atomic_sub_explicit(RMW, OPERAND, ORIG, ORDER) \ + ((void) (ORDER), atomic_sub(RMW, OPERAND, ORIG)) +#define atomic_or_explicit(RMW, OPERAND, ORIG, ORDER) \ + ((void) (ORDER), atomic_or(RMW, OPERAND, ORIG)) +#define atomic_xor_explicit(RMW, OPERAND, ORIG, ORDER) \ + ((void) (ORDER), atomic_xor(RMW, OPERAND, ORIG)) +#define atomic_and_explicit(RMW, OPERAND, ORIG, ORDER) \ + ((void) (ORDER), atomic_and(RMW, OPERAND, ORIG)) + +/* atomic_flag */ + +typedef struct { + int b; +} atomic_flag; +#define ATOMIC_FLAG_INIT { false } + +static inline bool +atomic_flag_test_and_set_explicit(volatile atomic_flag *object, + memory_order order) +{ + bool old; + + /* __sync_lock_test_and_set() by itself is an acquire barrier. + * For anything higher additional barriers are needed. */ + if (order > memory_order_acquire) { + atomic_thread_fence(order); + } + old = __sync_lock_test_and_set(&object->b, 1); + atomic_thread_fence_if_seq_cst(order); + + return old; +} + +#define atomic_flag_test_and_set(FLAG) \ + atomic_flag_test_and_set_explicit(FLAG, memory_order_seq_cst) + +static inline void +atomic_flag_clear_explicit(volatile atomic_flag *object, + memory_order order) +{ + /* __sync_lock_release() by itself is a release barrier. For + * anything else additional barrier may be needed. */ + if (order != memory_order_release) { + atomic_thread_fence(order); + } + __sync_lock_release(&object->b); + atomic_thread_fence_if_seq_cst(order); +} + +#define atomic_flag_clear(FLAG) \ + atomic_flag_clear_explicit(FLAG, memory_order_seq_cst) Index: openvswitch-2.17.2/lib/ovs-atomic-gcc4.7+.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-gcc4.7+.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This header implements atomic operation primitives on GCC 4.7 and later. */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#define ATOMIC(TYPE) TYPE - -typedef enum { - memory_order_relaxed = __ATOMIC_RELAXED, - memory_order_consume = __ATOMIC_CONSUME, - memory_order_acquire = __ATOMIC_ACQUIRE, - memory_order_release = __ATOMIC_RELEASE, - memory_order_acq_rel = __ATOMIC_ACQ_REL, - memory_order_seq_cst = __ATOMIC_SEQ_CST -} memory_order; - -#define ATOMIC_VAR_INIT(VALUE) (VALUE) -#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) - -#define atomic_thread_fence __atomic_thread_fence -#define atomic_signal_fence __atomic_signal_fence -#define atomic_is_lock_free __atomic_is_lock_free - -#define atomic_store(DST, SRC) \ - atomic_store_explicit(DST, SRC, memory_order_seq_cst) -#define atomic_store_explicit __atomic_store_n - -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) -#define atomic_read_explicit(SRC, DST, ORDER) \ - (*(DST) = __atomic_load_n(SRC, ORDER), \ - (void) 0) - -#define atomic_compare_exchange_strong(DST, EXP, SRC) \ - atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ - __atomic_compare_exchange_n(DST, EXP, SRC, false, ORD1, ORD2) - -#define atomic_compare_exchange_weak(DST, EXP, SRC) \ - atomic_compare_exchange_weak_explicit(DST, EXP, SRC, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -#define atomic_compare_exchange_weak_explicit(DST, EXP, SRC, ORD1, ORD2) \ - __atomic_compare_exchange_n(DST, EXP, SRC, true, ORD1, ORD2) - -#define atomic_exchange_explicit(DST, SRC, ORDER) \ - __atomic_exchange_n(DST, SRC, ORDER) -#define atomic_exchange(DST, SRC) \ - atomic_exchange_explicit(DST, SRC, memory_order_seq_cst) - -#define atomic_add(RMW, OPERAND, ORIG) \ - atomic_add_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) -#define atomic_sub(RMW, OPERAND, ORIG) \ - atomic_sub_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) -#define atomic_or(RMW, OPERAND, ORIG) \ - atomic_or_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) -#define atomic_xor(RMW, OPERAND, ORIG) \ - atomic_xor_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) -#define atomic_and(RMW, OPERAND, ORIG) \ - atomic_and_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) - -#define atomic_add_explicit(RMW, OPERAND, ORIG, ORDER) \ - (*(ORIG) = __atomic_fetch_add(RMW, OPERAND, ORDER), (void) 0) -#define atomic_sub_explicit(RMW, OPERAND, ORIG, ORDER) \ - (*(ORIG) = __atomic_fetch_sub(RMW, OPERAND, ORDER), (void) 0) -#define atomic_or_explicit(RMW, OPERAND, ORIG, ORDER) \ - (*(ORIG) = __atomic_fetch_or(RMW, OPERAND, ORDER), (void) 0) -#define atomic_xor_explicit(RMW, OPERAND, ORIG, ORDER) \ - (*(ORIG) = __atomic_fetch_xor(RMW, OPERAND, ORDER), (void) 0) -#define atomic_and_explicit(RMW, OPERAND, ORIG, ORDER) \ - (*(ORIG) = __atomic_fetch_and(RMW, OPERAND, ORDER), (void) 0) - -#include "ovs-atomic-flag-gcc4.7+.h" Index: openvswitch-2.17.2/include/internal/ovs-atomic-gcc4.7+.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-gcc4.7+.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header implements atomic operation primitives on GCC 4.7 and later. */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#define ATOMIC(TYPE) TYPE + +typedef enum { + memory_order_relaxed = __ATOMIC_RELAXED, + memory_order_consume = __ATOMIC_CONSUME, + memory_order_acquire = __ATOMIC_ACQUIRE, + memory_order_release = __ATOMIC_RELEASE, + memory_order_acq_rel = __ATOMIC_ACQ_REL, + memory_order_seq_cst = __ATOMIC_SEQ_CST +} memory_order; + +#define ATOMIC_VAR_INIT(VALUE) (VALUE) +#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) + +#define atomic_thread_fence __atomic_thread_fence +#define atomic_signal_fence __atomic_signal_fence +#define atomic_is_lock_free __atomic_is_lock_free + +#define atomic_store(DST, SRC) \ + atomic_store_explicit(DST, SRC, memory_order_seq_cst) +#define atomic_store_explicit __atomic_store_n + +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) +#define atomic_read_explicit(SRC, DST, ORDER) \ + (*(DST) = __atomic_load_n(SRC, ORDER), \ + (void) 0) + +#define atomic_compare_exchange_strong(DST, EXP, SRC) \ + atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ + memory_order_seq_cst, \ + memory_order_seq_cst) +#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ + __atomic_compare_exchange_n(DST, EXP, SRC, false, ORD1, ORD2) + +#define atomic_compare_exchange_weak(DST, EXP, SRC) \ + atomic_compare_exchange_weak_explicit(DST, EXP, SRC, \ + memory_order_seq_cst, \ + memory_order_seq_cst) +#define atomic_compare_exchange_weak_explicit(DST, EXP, SRC, ORD1, ORD2) \ + __atomic_compare_exchange_n(DST, EXP, SRC, true, ORD1, ORD2) + +#define atomic_exchange_explicit(DST, SRC, ORDER) \ + __atomic_exchange_n(DST, SRC, ORDER) +#define atomic_exchange(DST, SRC) \ + atomic_exchange_explicit(DST, SRC, memory_order_seq_cst) + +#define atomic_add(RMW, OPERAND, ORIG) \ + atomic_add_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) +#define atomic_sub(RMW, OPERAND, ORIG) \ + atomic_sub_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) +#define atomic_or(RMW, OPERAND, ORIG) \ + atomic_or_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) +#define atomic_xor(RMW, OPERAND, ORIG) \ + atomic_xor_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) +#define atomic_and(RMW, OPERAND, ORIG) \ + atomic_and_explicit(RMW, OPERAND, ORIG, memory_order_seq_cst) + +#define atomic_add_explicit(RMW, OPERAND, ORIG, ORDER) \ + (*(ORIG) = __atomic_fetch_add(RMW, OPERAND, ORDER), (void) 0) +#define atomic_sub_explicit(RMW, OPERAND, ORIG, ORDER) \ + (*(ORIG) = __atomic_fetch_sub(RMW, OPERAND, ORDER), (void) 0) +#define atomic_or_explicit(RMW, OPERAND, ORIG, ORDER) \ + (*(ORIG) = __atomic_fetch_or(RMW, OPERAND, ORDER), (void) 0) +#define atomic_xor_explicit(RMW, OPERAND, ORIG, ORDER) \ + (*(ORIG) = __atomic_fetch_xor(RMW, OPERAND, ORDER), (void) 0) +#define atomic_and_explicit(RMW, OPERAND, ORIG, ORDER) \ + (*(ORIG) = __atomic_fetch_and(RMW, OPERAND, ORDER), (void) 0) + +#include "internal/ovs-atomic-flag-gcc4.7+.h" Index: openvswitch-2.17.2/lib/ovs-atomic-locked.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-locked.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include - -#include "ovs-atomic.h" -#include "hash.h" -#include "ovs-thread.h" - -#ifdef OVS_ATOMIC_LOCKED_IMPL -static struct ovs_mutex * -mutex_for_pointer(void *p) -{ - OVS_ALIGNED_STRUCT(CACHE_LINE_SIZE, aligned_mutex) { - struct ovs_mutex mutex; - char pad[PAD_SIZE(sizeof(struct ovs_mutex), CACHE_LINE_SIZE)]; - }; - - static struct aligned_mutex atomic_mutexes[] = { -#define MUTEX_INIT { .mutex = OVS_MUTEX_INITIALIZER } -#define MUTEX_INIT4 MUTEX_INIT, MUTEX_INIT, MUTEX_INIT, MUTEX_INIT -#define MUTEX_INIT16 MUTEX_INIT4, MUTEX_INIT4, MUTEX_INIT4, MUTEX_INIT4 - MUTEX_INIT16, MUTEX_INIT16, - }; - BUILD_ASSERT_DECL(IS_POW2(ARRAY_SIZE(atomic_mutexes))); - - uint32_t hash = hash_pointer(p, 0); - uint32_t indx = hash & (ARRAY_SIZE(atomic_mutexes) - 1); - return &atomic_mutexes[indx].mutex; -} - -void -atomic_lock__(void *p) - OVS_ACQUIRES(mutex_for_pointer(p)) -{ - ovs_mutex_lock(mutex_for_pointer(p)); -} - -void -atomic_unlock__(void *p) - OVS_RELEASES(mutex_for_pointer(p)) -{ - ovs_mutex_unlock(mutex_for_pointer(p)); -} -#endif /* OVS_ATOMIC_LOCKED_IMPL */ Index: openvswitch-2.17.2/include/internal/ovs-atomic-locked.c =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-locked.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "openvswitch/ovs-atomic.h" +#include "internal/hash.h" +#include "openvswitch/ovs-thread.h" + +#ifdef OVS_ATOMIC_LOCKED_IMPL +static struct ovs_mutex * +mutex_for_pointer(void *p) +{ + OVS_ALIGNED_STRUCT(CACHE_LINE_SIZE, aligned_mutex) { + struct ovs_mutex mutex; + char pad[PAD_SIZE(sizeof(struct ovs_mutex), CACHE_LINE_SIZE)]; + }; + + static struct aligned_mutex atomic_mutexes[] = { +#define MUTEX_INIT { .mutex = OVS_MUTEX_INITIALIZER } +#define MUTEX_INIT4 MUTEX_INIT, MUTEX_INIT, MUTEX_INIT, MUTEX_INIT +#define MUTEX_INIT16 MUTEX_INIT4, MUTEX_INIT4, MUTEX_INIT4, MUTEX_INIT4 + MUTEX_INIT16, MUTEX_INIT16, + }; + BUILD_ASSERT_DECL(IS_POW2(ARRAY_SIZE(atomic_mutexes))); + + uint32_t hash = hash_pointer(p, 0); + uint32_t indx = hash & (ARRAY_SIZE(atomic_mutexes) - 1); + return &atomic_mutexes[indx].mutex; +} + +void +atomic_lock__(void *p) + OVS_ACQUIRES(mutex_for_pointer(p)) +{ + ovs_mutex_lock(mutex_for_pointer(p)); +} + +void +atomic_unlock__(void *p) + OVS_RELEASES(mutex_for_pointer(p)) +{ + ovs_mutex_unlock(mutex_for_pointer(p)); +} +#endif /* OVS_ATOMIC_LOCKED_IMPL */ Index: openvswitch-2.17.2/lib/ovs-atomic-pthreads.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-pthreads.h +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This header implements atomic operation primitives using pthreads. */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#include "ovs-atomic-locked.h" - -#define OVS_ATOMIC_PTHREADS_IMPL 1 - -#define ATOMIC(TYPE) TYPE - -#define ATOMIC_BOOL_LOCK_FREE 0 -#define ATOMIC_CHAR_LOCK_FREE 0 -#define ATOMIC_SHORT_LOCK_FREE 0 -#define ATOMIC_INT_LOCK_FREE 0 -#define ATOMIC_LONG_LOCK_FREE 0 -#define ATOMIC_LLONG_LOCK_FREE 0 -#define ATOMIC_POINTER_LOCK_FREE 0 - -typedef enum { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -} memory_order; - -#define ATOMIC_VAR_INIT(VALUE) (VALUE) -#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) - -static inline void -atomic_thread_fence(memory_order order OVS_UNUSED) -{ - /* Nothing to do. */ -} - -static inline void -atomic_signal_fence(memory_order order OVS_UNUSED) -{ - /* Nothing to do. */ -} - -#define atomic_is_lock_free(OBJ) false - -#define atomic_store(DST, SRC) atomic_store_locked(DST, SRC) -#define atomic_store_explicit(DST, SRC, ORDER) \ - ((void) (ORDER), atomic_store(DST, SRC)) - -#define atomic_read(SRC, DST) atomic_read_locked(SRC, DST) -#define atomic_read_explicit(SRC, DST, ORDER) \ - ((void) (ORDER), atomic_read(SRC, DST)) - -#define atomic_compare_exchange_strong(DST, EXP, SRC) \ - atomic_compare_exchange_locked(DST, EXP, SRC) -#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ - ((void) (ORD1), (void) (ORD2), \ - atomic_compare_exchange_strong(DST, EXP, SRC)) -#define atomic_compare_exchange_weak \ - atomic_compare_exchange_strong -#define atomic_compare_exchange_weak_explicit \ - atomic_compare_exchange_strong_explicit - -#define atomic_exchange(DST, SRC) \ - atomic_exchange_locked(DST, SRC) -#define atomic_exchange_explicit(DST, SRC, ORDER) \ - ((void) (ORDER), atomic_exchange(DST, SRC)) - -#define atomic_add(RMW, ARG, ORIG) atomic_op_locked(RMW, add, ARG, ORIG) -#define atomic_sub(RMW, ARG, ORIG) atomic_op_locked(RMW, sub, ARG, ORIG) -#define atomic_or( RMW, ARG, ORIG) atomic_op_locked(RMW, or, ARG, ORIG) -#define atomic_xor(RMW, ARG, ORIG) atomic_op_locked(RMW, xor, ARG, ORIG) -#define atomic_and(RMW, ARG, ORIG) atomic_op_locked(RMW, and, ARG, ORIG) - -#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ - ((void) (ORDER), atomic_add(RMW, ARG, ORIG)) -#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ - ((void) (ORDER), atomic_sub(RMW, ARG, ORIG)) -#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ - ((void) (ORDER), atomic_or(RMW, ARG, ORIG)) -#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ - ((void) (ORDER), atomic_xor(RMW, ARG, ORIG)) -#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ - ((void) (ORDER), atomic_and(RMW, ARG, ORIG)) - -/* atomic_flag */ - -typedef struct { - bool b; -} atomic_flag; -#define ATOMIC_FLAG_INIT { false } - -static inline bool -atomic_flag_test_and_set(volatile atomic_flag *flag_) -{ - atomic_flag *flag = CONST_CAST(atomic_flag *, flag_); - bool old_value; - - atomic_lock__(flag); - old_value = flag->b; - flag->b = true; - atomic_unlock__(flag); - - return old_value; -} - -static inline bool -atomic_flag_test_and_set_explicit(volatile atomic_flag *flag, - memory_order order OVS_UNUSED) -{ - return atomic_flag_test_and_set(flag); -} - -static inline void -atomic_flag_clear(volatile atomic_flag *flag_) -{ - atomic_flag *flag = CONST_CAST(atomic_flag *, flag_); - - atomic_lock__(flag); - flag->b = false; - atomic_unlock__(flag); -} - -static inline void -atomic_flag_clear_explicit(volatile atomic_flag *flag, - memory_order order OVS_UNUSED) -{ - atomic_flag_clear(flag); -} Index: openvswitch-2.17.2/include/internal/ovs-atomic-pthreads.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-pthreads.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header implements atomic operation primitives using pthreads. */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#include "internal/ovs-atomic-locked.h" + +#define OVS_ATOMIC_PTHREADS_IMPL 1 + +#define ATOMIC(TYPE) TYPE + +#define ATOMIC_BOOL_LOCK_FREE 0 +#define ATOMIC_CHAR_LOCK_FREE 0 +#define ATOMIC_SHORT_LOCK_FREE 0 +#define ATOMIC_INT_LOCK_FREE 0 +#define ATOMIC_LONG_LOCK_FREE 0 +#define ATOMIC_LLONG_LOCK_FREE 0 +#define ATOMIC_POINTER_LOCK_FREE 0 + +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +} memory_order; + +#define ATOMIC_VAR_INIT(VALUE) (VALUE) +#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) + +static inline void +atomic_thread_fence(memory_order order OVS_UNUSED) +{ + /* Nothing to do. */ +} + +static inline void +atomic_signal_fence(memory_order order OVS_UNUSED) +{ + /* Nothing to do. */ +} + +#define atomic_is_lock_free(OBJ) false + +#define atomic_store(DST, SRC) atomic_store_locked(DST, SRC) +#define atomic_store_explicit(DST, SRC, ORDER) \ + ((void) (ORDER), atomic_store(DST, SRC)) + +#define atomic_read(SRC, DST) atomic_read_locked(SRC, DST) +#define atomic_read_explicit(SRC, DST, ORDER) \ + ((void) (ORDER), atomic_read(SRC, DST)) + +#define atomic_compare_exchange_strong(DST, EXP, SRC) \ + atomic_compare_exchange_locked(DST, EXP, SRC) +#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ + ((void) (ORD1), (void) (ORD2), \ + atomic_compare_exchange_strong(DST, EXP, SRC)) +#define atomic_compare_exchange_weak \ + atomic_compare_exchange_strong +#define atomic_compare_exchange_weak_explicit \ + atomic_compare_exchange_strong_explicit + +#define atomic_exchange(DST, SRC) \ + atomic_exchange_locked(DST, SRC) +#define atomic_exchange_explicit(DST, SRC, ORDER) \ + ((void) (ORDER), atomic_exchange(DST, SRC)) + +#define atomic_add(RMW, ARG, ORIG) atomic_op_locked(RMW, add, ARG, ORIG) +#define atomic_sub(RMW, ARG, ORIG) atomic_op_locked(RMW, sub, ARG, ORIG) +#define atomic_or( RMW, ARG, ORIG) atomic_op_locked(RMW, or, ARG, ORIG) +#define atomic_xor(RMW, ARG, ORIG) atomic_op_locked(RMW, xor, ARG, ORIG) +#define atomic_and(RMW, ARG, ORIG) atomic_op_locked(RMW, and, ARG, ORIG) + +#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ + ((void) (ORDER), atomic_add(RMW, ARG, ORIG)) +#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ + ((void) (ORDER), atomic_sub(RMW, ARG, ORIG)) +#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ + ((void) (ORDER), atomic_or(RMW, ARG, ORIG)) +#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ + ((void) (ORDER), atomic_xor(RMW, ARG, ORIG)) +#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ + ((void) (ORDER), atomic_and(RMW, ARG, ORIG)) + +/* atomic_flag */ + +typedef struct { + bool b; +} atomic_flag; +#define ATOMIC_FLAG_INIT { false } + +static inline bool +atomic_flag_test_and_set(volatile atomic_flag *flag_) +{ + atomic_flag *flag = CONST_CAST(atomic_flag *, flag_); + bool old_value; + + atomic_lock__(flag); + old_value = flag->b; + flag->b = true; + atomic_unlock__(flag); + + return old_value; +} + +static inline bool +atomic_flag_test_and_set_explicit(volatile atomic_flag *flag, + memory_order order OVS_UNUSED) +{ + return atomic_flag_test_and_set(flag); +} + +static inline void +atomic_flag_clear(volatile atomic_flag *flag_) +{ + atomic_flag *flag = CONST_CAST(atomic_flag *, flag_); + + atomic_lock__(flag); + flag->b = false; + atomic_unlock__(flag); +} + +static inline void +atomic_flag_clear_explicit(volatile atomic_flag *flag, + memory_order order OVS_UNUSED) +{ + atomic_flag_clear(flag); +} Index: openvswitch-2.17.2/lib/packets.h =================================================================== --- openvswitch-2.17.2.orig/lib/packets.h +++ /dev/null @@ -1,1671 +0,0 @@ -/* - * 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. - */ - -#ifndef PACKETS_H -#define PACKETS_H 1 - -#include -#include -#include -#include -#include "openvswitch/compiler.h" -#include "openvswitch/geneve.h" -#include "openvswitch/packets.h" -#include "openvswitch/types.h" -#include "openvswitch/nsh.h" -#include "odp-netlink.h" -#include "random.h" -#include "hash.h" -#include "tun-metadata.h" -#include "unaligned.h" -#include "util.h" -#include "timeval.h" - -struct dp_packet; -struct conn; -struct ds; - -/* Purely internal to OVS userspace. These flags should never be exposed to - * the outside world and so aren't included in the flags mask. */ - -/* Tunnel information is in userspace datapath format. */ -#define FLOW_TNL_F_UDPIF (1 << 4) - -static inline bool ipv6_addr_is_set(const struct in6_addr *addr); - -static inline bool -flow_tnl_dst_is_set(const struct flow_tnl *tnl) -{ - return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst); -} - -static inline bool -flow_tnl_src_is_set(const struct flow_tnl *tnl) -{ - return tnl->ip_src || ipv6_addr_is_set(&tnl->ipv6_src); -} - -struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl); -struct in6_addr flow_tnl_src(const struct flow_tnl *tnl); - -/* Returns an offset to 'src' covering all the meaningful fields in 'src'. */ -static inline size_t -flow_tnl_size(const struct flow_tnl *src) -{ - if (!flow_tnl_dst_is_set(src)) { - /* Covers ip_dst and ipv6_dst only. */ - return offsetof(struct flow_tnl, ip_src); - } - if (src->flags & FLOW_TNL_F_UDPIF) { - /* Datapath format, cover all options we have. */ - return offsetof(struct flow_tnl, metadata.opts) - + src->metadata.present.len; - } - if (!src->metadata.present.map) { - /* No TLVs, opts is irrelevant. */ - return offsetof(struct flow_tnl, metadata.opts); - } - /* Have decoded TLVs, opts is relevant. */ - return sizeof *src; -} - -/* Copy flow_tnl, but avoid copying unused portions of tun_metadata. Unused - * data in 'dst' is NOT cleared, so this must not be used in cases where the - * uninitialized portion may be hashed over. */ -static inline void -flow_tnl_copy__(struct flow_tnl *dst, const struct flow_tnl *src) -{ - memcpy(dst, src, flow_tnl_size(src)); -} - -static inline bool -flow_tnl_equal(const struct flow_tnl *a, const struct flow_tnl *b) -{ - size_t a_size = flow_tnl_size(a); - - return a_size == flow_tnl_size(b) && !memcmp(a, b, a_size); -} - -/* Datapath packet metadata */ -struct pkt_metadata { -PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0, - uint32_t recirc_id; /* Recirculation id carried with the - recirculating packets. 0 for packets - received from the wire. */ - uint32_t dp_hash; /* hash value computed by the recirculation - action. */ - uint32_t skb_priority; /* Packet priority for QoS. */ - uint32_t pkt_mark; /* Packet mark. */ - uint8_t ct_state; /* Connection state. */ - bool ct_orig_tuple_ipv6; - uint16_t ct_zone; /* Connection zone. */ - uint32_t ct_mark; /* Connection mark. */ - ovs_u128 ct_label; /* Connection label. */ - union flow_in_port in_port; /* Input port. */ - odp_port_t orig_in_port; /* Originating in_port for tunneled packets */ - struct conn *conn; /* Cached conntrack connection. */ - bool reply; /* True if reply direction. */ - bool icmp_related; /* True if ICMP related. */ -); - -PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline1, - union { /* Populated only for non-zero 'ct_state'. */ - struct ovs_key_ct_tuple_ipv4 ipv4; - struct ovs_key_ct_tuple_ipv6 ipv6; /* Used only if */ - } ct_orig_tuple; /* 'ct_orig_tuple_ipv6' is set */ -); - -PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline2, - struct flow_tnl tunnel; /* Encapsulating tunnel parameters. Note that - * if 'ip_dst' == 0, the rest of the fields may - * be uninitialized. */ -); -}; - -BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline0) == 0); -BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline1) == - CACHE_LINE_SIZE); -BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline2) == - 2 * CACHE_LINE_SIZE); - -static inline void -pkt_metadata_init_tnl(struct pkt_metadata *md) -{ - odp_port_t orig_in_port; - - /* Zero up through the tunnel metadata options. The length and table - * are before this and as long as they are empty, the options won't - * be looked at. Keep the orig_in_port field. */ - orig_in_port = md->in_port.odp_port; - memset(md, 0, offsetof(struct pkt_metadata, tunnel.metadata.opts)); - md->orig_in_port = orig_in_port; -} - -static inline void -pkt_metadata_init_conn(struct pkt_metadata *md) -{ - md->conn = NULL; -} - -static inline void -pkt_metadata_init(struct pkt_metadata *md, odp_port_t port) -{ - /* This is called for every packet in userspace datapath and affects - * performance if all the metadata is initialized. Hence, fields should - * only be zeroed out when necessary. - * - * Initialize only till ct_state. Once the ct_state is zeroed out rest - * of ct fields will not be looked at unless ct_state != 0. - */ - memset(md, 0, offsetof(struct pkt_metadata, ct_orig_tuple_ipv6)); - - /* It can be expensive to zero out all of the tunnel metadata. However, - * we can just zero out ip_dst and the rest of the data will never be - * looked at. */ - md->tunnel.ip_dst = 0; - md->tunnel.ipv6_dst = in6addr_any; - md->in_port.odp_port = port; - md->orig_in_port = port; - md->conn = NULL; -} - -/* This function prefetches the cachelines touched by pkt_metadata_init() - * and pkt_metadata_init_tnl(). For performance reasons the two functions - * should be kept in sync. */ -static inline void -pkt_metadata_prefetch_init(struct pkt_metadata *md) -{ - /* Prefetch cacheline0 as members till ct_state and odp_port will - * be initialized later in pkt_metadata_init(). */ - OVS_PREFETCH(md->cacheline0); - - /* Prefetch cacheline1 as members of this cacheline will be zeroed out - * in pkt_metadata_init_tnl(). */ - OVS_PREFETCH(md->cacheline1); - - /* Prefetch cachline2 as ip_dst & ipv6_dst fields will be initialized. */ - OVS_PREFETCH(md->cacheline2); -} - -bool dpid_from_string(const char *s, uint64_t *dpidp); - -#define ETH_ADDR_LEN 6 - -static const struct eth_addr eth_addr_broadcast OVS_UNUSED - = ETH_ADDR_C(ff,ff,ff,ff,ff,ff); - -static const struct eth_addr eth_addr_exact OVS_UNUSED - = ETH_ADDR_C(ff,ff,ff,ff,ff,ff); - -static const struct eth_addr eth_addr_zero OVS_UNUSED - = ETH_ADDR_C(00,00,00,00,00,00); -static const struct eth_addr64 eth_addr64_zero OVS_UNUSED - = ETH_ADDR64_C(00,00,00,00,00,00,00,00); - -static const struct eth_addr eth_addr_stp OVS_UNUSED - = ETH_ADDR_C(01,80,c2,00,00,00); - -static const struct eth_addr eth_addr_lacp OVS_UNUSED - = ETH_ADDR_C(01,80,c2,00,00,02); - -static const struct eth_addr eth_addr_bfd OVS_UNUSED - = ETH_ADDR_C(00,23,20,00,00,01); - -static inline bool eth_addr_is_broadcast(const struct eth_addr a) -{ - return (a.be16[0] & a.be16[1] & a.be16[2]) == htons(0xffff); -} - -static inline bool eth_addr_is_multicast(const struct eth_addr a) -{ - return a.ea[0] & 1; -} - -static inline bool eth_addr_is_local(const struct eth_addr a) -{ - /* Local if it is either a locally administered address or a Nicira random - * address. */ - return a.ea[0] & 2 - || (a.be16[0] == htons(0x0023) - && (a.be16[1] & htons(0xff80)) == htons(0x2080)); -} -static inline bool eth_addr_is_zero(const struct eth_addr a) -{ - return !(a.be16[0] | a.be16[1] | a.be16[2]); -} -static inline bool eth_addr64_is_zero(const struct eth_addr64 a) -{ - return !(a.be16[0] | a.be16[1] | a.be16[2] | a.be16[3]); -} - -static inline int eth_mask_is_exact(const struct eth_addr a) -{ - return (a.be16[0] & a.be16[1] & a.be16[2]) == htons(0xffff); -} - -static inline int eth_addr_compare_3way(const struct eth_addr a, - const struct eth_addr b) -{ - return memcmp(&a, &b, sizeof a); -} -static inline int eth_addr64_compare_3way(const struct eth_addr64 a, - const struct eth_addr64 b) -{ - return memcmp(&a, &b, sizeof a); -} - -static inline bool eth_addr_equals(const struct eth_addr a, - const struct eth_addr b) -{ - return !eth_addr_compare_3way(a, b); -} -static inline bool eth_addr64_equals(const struct eth_addr64 a, - const struct eth_addr64 b) -{ - return !eth_addr64_compare_3way(a, b); -} - -static inline bool eth_addr_equal_except(const struct eth_addr a, - const struct eth_addr b, - const struct eth_addr mask) -{ - return !(((a.be16[0] ^ b.be16[0]) & mask.be16[0]) - || ((a.be16[1] ^ b.be16[1]) & mask.be16[1]) - || ((a.be16[2] ^ b.be16[2]) & mask.be16[2])); -} - -uint64_t eth_addr_to_uint64(const struct eth_addr ea); - -static inline uint64_t eth_addr_vlan_to_uint64(const struct eth_addr ea, - uint16_t vlan) -{ - return (((uint64_t)vlan << 48) | eth_addr_to_uint64(ea)); -} - -void eth_addr_from_uint64(uint64_t x, struct eth_addr *ea); - -static inline struct eth_addr eth_addr_invert(const struct eth_addr src) -{ - struct eth_addr dst; - - for (int i = 0; i < ARRAY_SIZE(src.be16); i++) { - dst.be16[i] = ~src.be16[i]; - } - - return dst; -} - -void eth_addr_mark_random(struct eth_addr *ea); - -static inline void eth_addr_random(struct eth_addr *ea) -{ - random_bytes((uint8_t *)ea, sizeof *ea); - eth_addr_mark_random(ea); -} - -static inline void eth_addr_nicira_random(struct eth_addr *ea) -{ - eth_addr_random(ea); - - /* Set the OUI to the Nicira one. */ - ea->ea[0] = 0x00; - ea->ea[1] = 0x23; - ea->ea[2] = 0x20; - - /* Set the top bit to indicate random Nicira address. */ - ea->ea[3] |= 0x80; -} -static inline uint32_t hash_mac(const struct eth_addr ea, - const uint16_t vlan, const uint32_t basis) -{ - return hash_uint64_basis(eth_addr_vlan_to_uint64(ea, vlan), basis); -} - -bool eth_addr_is_reserved(const struct eth_addr); -bool eth_addr_from_string(const char *, struct eth_addr *); - -void compose_rarp(struct dp_packet *, const struct eth_addr); - -void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci); -void eth_pop_vlan(struct dp_packet *); - -const char *eth_from_hex(const char *hex, struct dp_packet **packetp); -void eth_format_masked(const struct eth_addr ea, - const struct eth_addr *mask, struct ds *s); - -void set_mpls_lse(struct dp_packet *, ovs_be32 label); -void push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse); -void pop_mpls(struct dp_packet *, ovs_be16 ethtype); - -void set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl); -void set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc); -void set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label); -void set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos); -ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos, - ovs_be32 label); -void add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse, - bool l3_encap); - -/* Example: - * - * struct eth_addr mac; - * [...] - * printf("The Ethernet address is "ETH_ADDR_FMT"\n", ETH_ADDR_ARGS(mac)); - * - */ -#define ETH_ADDR_FMT \ - "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8 -#define ETH_ADDR_ARGS(EA) ETH_ADDR_BYTES_ARGS((EA).ea) -#define ETH_ADDR_BYTES_ARGS(EAB) \ - (EAB)[0], (EAB)[1], (EAB)[2], (EAB)[3], (EAB)[4], (EAB)[5] -#define ETH_ADDR_STRLEN 17 - -/* Example: - * - * struct eth_addr64 eui64; - * [...] - * printf("The EUI-64 address is "ETH_ADDR64_FMT"\n", ETH_ADDR64_ARGS(mac)); - * - */ -#define ETH_ADDR64_FMT \ - "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":" \ - "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8 -#define ETH_ADDR64_ARGS(EA) ETH_ADDR64_BYTES_ARGS((EA).ea64) -#define ETH_ADDR64_BYTES_ARGS(EAB) \ - (EAB)[0], (EAB)[1], (EAB)[2], (EAB)[3], \ - (EAB)[4], (EAB)[5], (EAB)[6], (EAB)[7] -#define ETH_ADDR64_STRLEN 23 - -/* Example: - * - * char *string = "1 00:11:22:33:44:55 2"; - * struct eth_addr mac; - * int a, b; - * - * if (ovs_scan(string, "%d"ETH_ADDR_SCAN_FMT"%d", - * &a, ETH_ADDR_SCAN_ARGS(mac), &b)) { - * ... - * } - */ -#define ETH_ADDR_SCAN_FMT "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8 -#define ETH_ADDR_SCAN_ARGS(EA) \ - &(EA).ea[0], &(EA).ea[1], &(EA).ea[2], &(EA).ea[3], &(EA).ea[4], &(EA).ea[5] - -#define ETH_TYPE_IP 0x0800 -#define ETH_TYPE_ARP 0x0806 -#define ETH_TYPE_TEB 0x6558 -#define ETH_TYPE_VLAN_8021Q 0x8100 -#define ETH_TYPE_VLAN ETH_TYPE_VLAN_8021Q -#define ETH_TYPE_VLAN_8021AD 0x88a8 -#define ETH_TYPE_IPV6 0x86dd -#define ETH_TYPE_LACP 0x8809 -#define ETH_TYPE_RARP 0x8035 -#define ETH_TYPE_MPLS 0x8847 -#define ETH_TYPE_MPLS_MCAST 0x8848 -#define ETH_TYPE_NSH 0x894f -#define ETH_TYPE_ERSPAN1 0x88be /* version 1 type II */ -#define ETH_TYPE_ERSPAN2 0x22eb /* version 2 type III */ - -static inline bool eth_type_mpls(ovs_be16 eth_type) -{ - return eth_type == htons(ETH_TYPE_MPLS) || - eth_type == htons(ETH_TYPE_MPLS_MCAST); -} - -static inline bool eth_type_vlan(ovs_be16 eth_type) -{ - return eth_type == htons(ETH_TYPE_VLAN_8021Q) || - eth_type == htons(ETH_TYPE_VLAN_8021AD); -} - - -/* Minimum value for an Ethernet type. Values below this are IEEE 802.2 frame - * lengths. */ -#define ETH_TYPE_MIN 0x600 - -#define ETH_HEADER_LEN 14 -#define ETH_PAYLOAD_MIN 46 -#define ETH_PAYLOAD_MAX 1500 -#define ETH_TOTAL_MIN (ETH_HEADER_LEN + ETH_PAYLOAD_MIN) -#define ETH_TOTAL_MAX (ETH_HEADER_LEN + ETH_PAYLOAD_MAX) -#define ETH_VLAN_TOTAL_MAX (ETH_HEADER_LEN + VLAN_HEADER_LEN + ETH_PAYLOAD_MAX) -struct eth_header { - struct eth_addr eth_dst; - struct eth_addr eth_src; - ovs_be16 eth_type; -}; -BUILD_ASSERT_DECL(ETH_HEADER_LEN == sizeof(struct eth_header)); - -void push_eth(struct dp_packet *packet, const struct eth_addr *dst, - const struct eth_addr *src); -void pop_eth(struct dp_packet *packet); - -void push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src); -bool pop_nsh(struct dp_packet *packet); - -#define LLC_DSAP_SNAP 0xaa -#define LLC_SSAP_SNAP 0xaa -#define LLC_CNTL_SNAP 3 - -#define LLC_HEADER_LEN 3 -struct llc_header { - uint8_t llc_dsap; - uint8_t llc_ssap; - uint8_t llc_cntl; -}; -BUILD_ASSERT_DECL(LLC_HEADER_LEN == sizeof(struct llc_header)); - -/* LLC field values used for STP frames. */ -#define STP_LLC_SSAP 0x42 -#define STP_LLC_DSAP 0x42 -#define STP_LLC_CNTL 0x03 - -#define SNAP_ORG_ETHERNET "\0\0" /* The compiler adds a null byte, so - sizeof(SNAP_ORG_ETHERNET) == 3. */ -#define SNAP_HEADER_LEN 5 -OVS_PACKED( -struct snap_header { - uint8_t snap_org[3]; - ovs_be16 snap_type; -}); -BUILD_ASSERT_DECL(SNAP_HEADER_LEN == sizeof(struct snap_header)); - -#define LLC_SNAP_HEADER_LEN (LLC_HEADER_LEN + SNAP_HEADER_LEN) -OVS_PACKED( -struct llc_snap_header { - struct llc_header llc; - struct snap_header snap; -}); -BUILD_ASSERT_DECL(LLC_SNAP_HEADER_LEN == sizeof(struct llc_snap_header)); - -#define VLAN_VID_MASK 0x0fff -#define VLAN_VID_SHIFT 0 - -#define VLAN_PCP_MASK 0xe000 -#define VLAN_PCP_SHIFT 13 - -#define VLAN_CFI 0x1000 -#define VLAN_CFI_SHIFT 12 - -/* Given the vlan_tci field from an 802.1Q header, in network byte order, - * returns the VLAN ID in host byte order. */ -static inline uint16_t -vlan_tci_to_vid(ovs_be16 vlan_tci) -{ - return (ntohs(vlan_tci) & VLAN_VID_MASK) >> VLAN_VID_SHIFT; -} - -/* Given the vlan_tci field from an 802.1Q header, in network byte order, - * returns the priority code point (PCP) in host byte order. */ -static inline int -vlan_tci_to_pcp(ovs_be16 vlan_tci) -{ - return (ntohs(vlan_tci) & VLAN_PCP_MASK) >> VLAN_PCP_SHIFT; -} - -/* Given the vlan_tci field from an 802.1Q header, in network byte order, - * returns the Canonical Format Indicator (CFI). */ -static inline int -vlan_tci_to_cfi(ovs_be16 vlan_tci) -{ - return (vlan_tci & htons(VLAN_CFI)) != 0; -} - -#define VLAN_HEADER_LEN 4 -struct vlan_header { - ovs_be16 vlan_tci; /* Lowest 12 bits are VLAN ID. */ - ovs_be16 vlan_next_type; -}; -BUILD_ASSERT_DECL(VLAN_HEADER_LEN == sizeof(struct vlan_header)); - -#define VLAN_ETH_HEADER_LEN (ETH_HEADER_LEN + VLAN_HEADER_LEN) -struct vlan_eth_header { - struct eth_addr veth_dst; - struct eth_addr veth_src; - ovs_be16 veth_type; /* Always htons(ETH_TYPE_VLAN). */ - ovs_be16 veth_tci; /* Lowest 12 bits are VLAN ID. */ - ovs_be16 veth_next_type; -}; -BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header)); - -/* MPLS related definitions */ -#define MPLS_TTL_MASK 0x000000ff -#define MPLS_TTL_SHIFT 0 - -#define MPLS_BOS_MASK 0x00000100 -#define MPLS_BOS_SHIFT 8 - -#define MPLS_TC_MASK 0x00000e00 -#define MPLS_TC_SHIFT 9 - -#define MPLS_LABEL_MASK 0xfffff000 -#define MPLS_LABEL_SHIFT 12 - -#define MPLS_HLEN 4 - -struct mpls_hdr { - ovs_16aligned_be32 mpls_lse; -}; -BUILD_ASSERT_DECL(MPLS_HLEN == sizeof(struct mpls_hdr)); - -/* Given a mpls label stack entry in network byte order - * return mpls label in host byte order */ -static inline uint32_t -mpls_lse_to_label(ovs_be32 mpls_lse) -{ - return (ntohl(mpls_lse) & MPLS_LABEL_MASK) >> MPLS_LABEL_SHIFT; -} - -/* Given a mpls label stack entry in network byte order - * return mpls tc */ -static inline uint8_t -mpls_lse_to_tc(ovs_be32 mpls_lse) -{ - return (ntohl(mpls_lse) & MPLS_TC_MASK) >> MPLS_TC_SHIFT; -} - -/* Given a mpls label stack entry in network byte order - * return mpls ttl */ -static inline uint8_t -mpls_lse_to_ttl(ovs_be32 mpls_lse) -{ - return (ntohl(mpls_lse) & MPLS_TTL_MASK) >> MPLS_TTL_SHIFT; -} - -/* Set label in mpls lse. */ -static inline void -flow_set_mpls_lse_label(ovs_be32 *mpls_lse, uint32_t label) -{ - *mpls_lse &= ~htonl(MPLS_LABEL_MASK); - *mpls_lse |= htonl(label << MPLS_LABEL_SHIFT); -} - -/* Set TC in mpls lse. */ -static inline void -flow_set_mpls_lse_tc(ovs_be32 *mpls_lse, uint8_t tc) -{ - *mpls_lse &= ~htonl(MPLS_TC_MASK); - *mpls_lse |= htonl((tc & 0x7) << MPLS_TC_SHIFT); -} - -/* Set BOS in mpls lse. */ -static inline void -flow_set_mpls_lse_bos(ovs_be32 *mpls_lse, uint8_t bos) -{ - *mpls_lse &= ~htonl(MPLS_BOS_MASK); - *mpls_lse |= htonl((bos & 0x1) << MPLS_BOS_SHIFT); -} - -/* Set TTL in mpls lse. */ -static inline void -flow_set_mpls_lse_ttl(ovs_be32 *mpls_lse, uint8_t ttl) -{ - *mpls_lse &= ~htonl(MPLS_TTL_MASK); - *mpls_lse |= htonl(ttl << MPLS_TTL_SHIFT); -} - -/* Given a mpls label stack entry in network byte order - * return mpls BoS bit */ -static inline uint8_t -mpls_lse_to_bos(ovs_be32 mpls_lse) -{ - return (mpls_lse & htonl(MPLS_BOS_MASK)) != 0; -} - -#define IP_FMT "%"PRIu32".%"PRIu32".%"PRIu32".%"PRIu32 -#define IP_ARGS(ip) \ - ntohl(ip) >> 24, \ - (ntohl(ip) >> 16) & 0xff, \ - (ntohl(ip) >> 8) & 0xff, \ - ntohl(ip) & 0xff - -/* Example: - * - * char *string = "1 33.44.55.66 2"; - * ovs_be32 ip; - * int a, b; - * - * if (ovs_scan(string, "%d"IP_SCAN_FMT"%d", &a, IP_SCAN_ARGS(&ip), &b)) { - * ... - * } - */ -#define IP_SCAN_FMT "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8 -#define IP_SCAN_ARGS(ip) \ - ((void) (ovs_be32) *(ip), &((uint8_t *) ip)[0]), \ - &((uint8_t *) ip)[1], \ - &((uint8_t *) ip)[2], \ - &((uint8_t *) ip)[3] - -#define IP_PORT_SCAN_FMT "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8":%"SCNu16 -#define IP_PORT_SCAN_ARGS(ip, port) \ - ((void) (ovs_be32) *(ip), &((uint8_t *) ip)[0]), \ - &((uint8_t *) ip)[1], \ - &((uint8_t *) ip)[2], \ - &((uint8_t *) ip)[3], \ - ((void) (ovs_be16) *(port), (uint16_t *) port) - -/* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N - * high-order 1-bits and 32-N low-order 0-bits. */ -static inline bool -ip_is_cidr(ovs_be32 netmask) -{ - uint32_t x = ~ntohl(netmask); - return !(x & (x + 1)); -} -static inline bool -ip_is_multicast(ovs_be32 ip) -{ - return (ip & htonl(0xf0000000)) == htonl(0xe0000000); -} -static inline bool -ip_is_local_multicast(ovs_be32 ip) -{ - return (ip & htonl(0xffffff00)) == htonl(0xe0000000); -} -int ip_count_cidr_bits(ovs_be32 netmask); -void ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *); -bool ip_parse(const char *s, ovs_be32 *ip); -char *ip_parse_port(const char *s, ovs_be32 *ip, ovs_be16 *port) - OVS_WARN_UNUSED_RESULT; -char *ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask) - OVS_WARN_UNUSED_RESULT; -char *ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen) - OVS_WARN_UNUSED_RESULT; -char *ip_parse_masked_len(const char *s, int *n, ovs_be32 *ip, ovs_be32 *mask) - OVS_WARN_UNUSED_RESULT; -char *ip_parse_cidr_len(const char *s, int *n, ovs_be32 *ip, - unsigned int *plen) - OVS_WARN_UNUSED_RESULT; - -#define IP_VER(ip_ihl_ver) ((ip_ihl_ver) >> 4) -#define IP_IHL(ip_ihl_ver) ((ip_ihl_ver) & 15) -#define IP_IHL_VER(ihl, ver) (((ver) << 4) | (ihl)) - -#ifndef IPPROTO_SCTP -#define IPPROTO_SCTP 132 -#endif - -#ifndef IPPROTO_DCCP -#define IPPROTO_DCCP 33 -#endif - -#ifndef IPPROTO_IGMP -#define IPPROTO_IGMP 2 -#endif - -#ifndef IPPROTO_UDPLITE -#define IPPROTO_UDPLITE 136 -#endif - -/* TOS fields. */ -#define IP_ECN_NOT_ECT 0x0 -#define IP_ECN_ECT_1 0x01 -#define IP_ECN_ECT_0 0x02 -#define IP_ECN_CE 0x03 -#define IP_ECN_MASK 0x03 -#define IP_DSCP_CS6 0xc0 -#define IP_DSCP_MASK 0xfc - -static inline int -IP_ECN_is_ce(uint8_t dsfield) -{ - return (dsfield & IP_ECN_MASK) == IP_ECN_CE; -} - -#define IP_VERSION 4 - -#define IP_DONT_FRAGMENT 0x4000 /* Don't fragment. */ -#define IP_MORE_FRAGMENTS 0x2000 /* More fragments. */ -#define IP_FRAG_OFF_MASK 0x1fff /* Fragment offset. */ -#define IP_IS_FRAGMENT(ip_frag_off) \ - ((ip_frag_off) & htons(IP_MORE_FRAGMENTS | IP_FRAG_OFF_MASK)) - -#define IP_HEADER_LEN 20 -struct ip_header { - uint8_t ip_ihl_ver; - uint8_t ip_tos; - ovs_be16 ip_tot_len; - ovs_be16 ip_id; - ovs_be16 ip_frag_off; - uint8_t ip_ttl; - uint8_t ip_proto; - ovs_be16 ip_csum; - ovs_16aligned_be32 ip_src; - ovs_16aligned_be32 ip_dst; -}; -BUILD_ASSERT_DECL(IP_HEADER_LEN == sizeof(struct ip_header)); - -/* ICMPv4 types. */ -#define ICMP4_ECHO_REPLY 0 -#define ICMP4_DST_UNREACH 3 -#define ICMP4_SOURCEQUENCH 4 -#define ICMP4_REDIRECT 5 -#define ICMP4_ECHO_REQUEST 8 -#define ICMP4_TIME_EXCEEDED 11 -#define ICMP4_PARAM_PROB 12 -#define ICMP4_TIMESTAMP 13 -#define ICMP4_TIMESTAMPREPLY 14 -#define ICMP4_INFOREQUEST 15 -#define ICMP4_INFOREPLY 16 - -#define ICMP_HEADER_LEN 8 -struct icmp_header { - uint8_t icmp_type; - uint8_t icmp_code; - ovs_be16 icmp_csum; - union { - struct { - ovs_be16 id; - ovs_be16 seq; - } echo; - struct { - ovs_be16 empty; - ovs_be16 mtu; - } frag; - ovs_16aligned_be32 gateway; - } icmp_fields; -}; -BUILD_ASSERT_DECL(ICMP_HEADER_LEN == sizeof(struct icmp_header)); - -/* ICMPV4 */ -#define ICMP_ERROR_DATA_L4_LEN 8 - -#define IGMP_HEADER_LEN 8 -struct igmp_header { - uint8_t igmp_type; - uint8_t igmp_code; - ovs_be16 igmp_csum; - ovs_16aligned_be32 group; -}; -BUILD_ASSERT_DECL(IGMP_HEADER_LEN == sizeof(struct igmp_header)); - -#define IGMPV3_HEADER_LEN 8 -struct igmpv3_header { - uint8_t type; - uint8_t rsvr1; - ovs_be16 csum; - ovs_be16 rsvr2; - ovs_be16 ngrp; -}; -BUILD_ASSERT_DECL(IGMPV3_HEADER_LEN == sizeof(struct igmpv3_header)); - -#define IGMPV3_QUERY_HEADER_LEN 12 -struct igmpv3_query_header { - uint8_t type; - uint8_t max_resp; - ovs_be16 csum; - ovs_16aligned_be32 group; - uint8_t srs_qrv; - uint8_t qqic; - ovs_be16 nsrcs; -}; -BUILD_ASSERT_DECL( - IGMPV3_QUERY_HEADER_LEN == sizeof(struct igmpv3_query_header -)); - -#define IGMPV3_RECORD_LEN 8 -struct igmpv3_record { - uint8_t type; - uint8_t aux_len; - ovs_be16 nsrcs; - ovs_16aligned_be32 maddr; -}; -BUILD_ASSERT_DECL(IGMPV3_RECORD_LEN == sizeof(struct igmpv3_record)); - -#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */ -#define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ -#define IGMPV2_HOST_MEMBERSHIP_REPORT 0x16 /* V2 version of 0x12 */ -#define IGMP_HOST_LEAVE_MESSAGE 0x17 -#define IGMPV3_HOST_MEMBERSHIP_REPORT 0x22 /* V3 version of 0x12 */ - -/* - * IGMPv3 and MLDv2 use the same codes. - */ -#define IGMPV3_MODE_IS_INCLUDE 1 -#define IGMPV3_MODE_IS_EXCLUDE 2 -#define IGMPV3_CHANGE_TO_INCLUDE_MODE 3 -#define IGMPV3_CHANGE_TO_EXCLUDE_MODE 4 -#define IGMPV3_ALLOW_NEW_SOURCES 5 -#define IGMPV3_BLOCK_OLD_SOURCES 6 - -#define SCTP_HEADER_LEN 12 -struct sctp_header { - ovs_be16 sctp_src; - ovs_be16 sctp_dst; - ovs_16aligned_be32 sctp_vtag; - ovs_16aligned_be32 sctp_csum; -}; -BUILD_ASSERT_DECL(SCTP_HEADER_LEN == sizeof(struct sctp_header)); - -#define UDP_HEADER_LEN 8 -struct udp_header { - ovs_be16 udp_src; - ovs_be16 udp_dst; - ovs_be16 udp_len; - ovs_be16 udp_csum; -}; -BUILD_ASSERT_DECL(UDP_HEADER_LEN == sizeof(struct udp_header)); - -#define ESP_HEADER_LEN 8 -struct esp_header { - ovs_be32 spi; - ovs_be32 seq_no; -}; -BUILD_ASSERT_DECL(ESP_HEADER_LEN == sizeof(struct esp_header)); - -#define ESP_TRAILER_LEN 2 -struct esp_trailer { - uint8_t pad_len; - uint8_t next_hdr; -}; -BUILD_ASSERT_DECL(ESP_TRAILER_LEN == sizeof(struct esp_trailer)); - -#define TCP_FIN 0x001 -#define TCP_SYN 0x002 -#define TCP_RST 0x004 -#define TCP_PSH 0x008 -#define TCP_ACK 0x010 -#define TCP_URG 0x020 -#define TCP_ECE 0x040 -#define TCP_CWR 0x080 -#define TCP_NS 0x100 - -#define TCP_CTL(flags, offset) (htons((flags) | ((offset) << 12))) -#define TCP_FLAGS(tcp_ctl) (ntohs(tcp_ctl) & 0x0fff) -#define TCP_FLAGS_BE16(tcp_ctl) ((tcp_ctl) & htons(0x0fff)) -#define TCP_OFFSET(tcp_ctl) (ntohs(tcp_ctl) >> 12) - -#define TCP_HEADER_LEN 20 -struct tcp_header { - ovs_be16 tcp_src; - ovs_be16 tcp_dst; - ovs_16aligned_be32 tcp_seq; - ovs_16aligned_be32 tcp_ack; - ovs_be16 tcp_ctl; - ovs_be16 tcp_winsz; - ovs_be16 tcp_csum; - ovs_be16 tcp_urg; -}; -BUILD_ASSERT_DECL(TCP_HEADER_LEN == sizeof(struct tcp_header)); - -/* Connection states. - * - * Names like CS_RELATED are bit values, e.g. 1 << 2. - * Names like CS_RELATED_BIT are bit indexes, e.g. 2. */ -#define CS_STATES \ - CS_STATE(NEW, 0, "new") \ - CS_STATE(ESTABLISHED, 1, "est") \ - CS_STATE(RELATED, 2, "rel") \ - CS_STATE(REPLY_DIR, 3, "rpl") \ - CS_STATE(INVALID, 4, "inv") \ - CS_STATE(TRACKED, 5, "trk") \ - CS_STATE(SRC_NAT, 6, "snat") \ - CS_STATE(DST_NAT, 7, "dnat") - -enum { -#define CS_STATE(ENUM, INDEX, NAME) \ - CS_##ENUM = 1 << INDEX, \ - CS_##ENUM##_BIT = INDEX, - CS_STATES -#undef CS_STATE -}; - -/* Undefined connection state bits. */ -enum { -#define CS_STATE(ENUM, INDEX, NAME) +CS_##ENUM - CS_SUPPORTED_MASK = CS_STATES -#undef CS_STATE -}; -#define CS_UNSUPPORTED_MASK (~(uint32_t)CS_SUPPORTED_MASK) - -#define ARP_HRD_ETHERNET 1 -#define ARP_PRO_IP 0x0800 -#define ARP_OP_REQUEST 1 -#define ARP_OP_REPLY 2 -#define ARP_OP_RARP 3 - -#define ARP_ETH_HEADER_LEN 28 -struct arp_eth_header { - /* Generic members. */ - ovs_be16 ar_hrd; /* Hardware type. */ - ovs_be16 ar_pro; /* Protocol type. */ - uint8_t ar_hln; /* Hardware address length. */ - uint8_t ar_pln; /* Protocol address length. */ - ovs_be16 ar_op; /* Opcode. */ - - /* Ethernet+IPv4 specific members. */ - struct eth_addr ar_sha; /* Sender hardware address. */ - ovs_16aligned_be32 ar_spa; /* Sender protocol address. */ - struct eth_addr ar_tha; /* Target hardware address. */ - ovs_16aligned_be32 ar_tpa; /* Target protocol address. */ -}; -BUILD_ASSERT_DECL(ARP_ETH_HEADER_LEN == sizeof(struct arp_eth_header)); - -#define IPV6_HEADER_LEN 40 - -/* Like struct in6_addr, but whereas that struct requires 32-bit alignment on - * most implementations, this one only requires 16-bit alignment. */ -union ovs_16aligned_in6_addr { - ovs_be16 be16[8]; - ovs_16aligned_be32 be32[4]; -}; - -/* Like struct ip6_hdr, but whereas that struct requires 32-bit alignment, this - * one only requires 16-bit alignment. */ -struct ovs_16aligned_ip6_hdr { - union { - struct ovs_16aligned_ip6_hdrctl { - ovs_16aligned_be32 ip6_un1_flow; - ovs_be16 ip6_un1_plen; - uint8_t ip6_un1_nxt; - uint8_t ip6_un1_hlim; - } ip6_un1; - uint8_t ip6_un2_vfc; - } ip6_ctlun; - union ovs_16aligned_in6_addr ip6_src; - union ovs_16aligned_in6_addr ip6_dst; -}; - -/* Like struct in6_frag, but whereas that struct requires 32-bit alignment, - * this one only requires 16-bit alignment. */ -struct ovs_16aligned_ip6_frag { - uint8_t ip6f_nxt; - uint8_t ip6f_reserved; - ovs_be16 ip6f_offlg; - ovs_16aligned_be32 ip6f_ident; -}; - -#define ICMP6_HEADER_LEN 4 -struct icmp6_header { - uint8_t icmp6_type; - uint8_t icmp6_code; - ovs_be16 icmp6_cksum; -}; -BUILD_ASSERT_DECL(ICMP6_HEADER_LEN == sizeof(struct icmp6_header)); - -#define ICMP6_DATA_HEADER_LEN 8 -struct icmp6_data_header { - struct icmp6_header icmp6_base; - union { - ovs_16aligned_be32 be32[1]; - ovs_be16 be16[2]; - uint8_t u8[4]; - } icmp6_data; -}; -BUILD_ASSERT_DECL(ICMP6_DATA_HEADER_LEN == sizeof(struct icmp6_data_header)); - -uint32_t packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *); -ovs_be16 packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *, - const void *, uint8_t, uint16_t); - -/* Neighbor Discovery option field. - * ND options are always a multiple of 8 bytes in size. */ -#define ND_LLA_OPT_LEN 8 -struct ovs_nd_lla_opt { - uint8_t type; /* One of ND_OPT_*_LINKADDR. */ - uint8_t len; - struct eth_addr mac; -}; -BUILD_ASSERT_DECL(ND_LLA_OPT_LEN == sizeof(struct ovs_nd_lla_opt)); - -/* Neighbor Discovery option: Prefix Information. */ -#define ND_PREFIX_OPT_LEN 32 -struct ovs_nd_prefix_opt { - uint8_t type; /* ND_OPT_PREFIX_INFORMATION. */ - uint8_t len; /* Always 4. */ - uint8_t prefix_len; - uint8_t la_flags; /* ND_PREFIX_* flags. */ - ovs_16aligned_be32 valid_lifetime; - ovs_16aligned_be32 preferred_lifetime; - ovs_16aligned_be32 reserved; /* Always 0. */ - union ovs_16aligned_in6_addr prefix; -}; -BUILD_ASSERT_DECL(ND_PREFIX_OPT_LEN == sizeof(struct ovs_nd_prefix_opt)); - -/* Neighbor Discovery option: MTU. */ -#define ND_MTU_OPT_LEN 8 -#define ND_MTU_DEFAULT 0 -struct ovs_nd_mtu_opt { - uint8_t type; /* ND_OPT_MTU */ - uint8_t len; /* Always 1. */ - ovs_be16 reserved; /* Always 0. */ - ovs_16aligned_be32 mtu; -}; -BUILD_ASSERT_DECL(ND_MTU_OPT_LEN == sizeof(struct ovs_nd_mtu_opt)); - -/* Like struct nd_msg (from ndisc.h), but whereas that struct requires 32-bit - * alignment, this one only requires 16-bit alignment. */ -#define ND_MSG_LEN 24 -struct ovs_nd_msg { - struct icmp6_header icmph; - ovs_16aligned_be32 rso_flags; - union ovs_16aligned_in6_addr target; - struct ovs_nd_lla_opt options[0]; -}; -BUILD_ASSERT_DECL(ND_MSG_LEN == sizeof(struct ovs_nd_msg)); - -/* Neighbor Discovery packet flags. */ -#define ND_RSO_ROUTER 0x80000000 -#define ND_RSO_SOLICITED 0x40000000 -#define ND_RSO_OVERRIDE 0x20000000 - -#define RA_MSG_LEN 16 -struct ovs_ra_msg { - struct icmp6_header icmph; - uint8_t cur_hop_limit; - uint8_t mo_flags; /* ND_RA_MANAGED_ADDRESS and ND_RA_OTHER_CONFIG flags. */ - ovs_be16 router_lifetime; - ovs_be32 reachable_time; - ovs_be32 retrans_timer; - struct ovs_nd_lla_opt options[0]; -}; -BUILD_ASSERT_DECL(RA_MSG_LEN == sizeof(struct ovs_ra_msg)); - -#define ND_RA_MANAGED_ADDRESS 0x80 -#define ND_RA_OTHER_CONFIG 0x40 - -/* Defaults based on MaxRtrInterval and MinRtrInterval from RFC 4861 section - * 6.2.1 - */ -#define ND_RA_MAX_INTERVAL_DEFAULT 600 - -static inline int -nd_ra_min_interval_default(int max) -{ - return max >= 9 ? max / 3 : max * 3 / 4; -} - -/* - * Use the same struct for MLD and MLD2, naming members as the defined fields in - * in the corresponding version of the protocol, though they are reserved in the - * other one. - */ -#define MLD_HEADER_LEN 8 -struct mld_header { - uint8_t type; - uint8_t code; - ovs_be16 csum; - ovs_be16 mrd; - ovs_be16 ngrp; -}; -BUILD_ASSERT_DECL(MLD_HEADER_LEN == sizeof(struct mld_header)); - -#define MLD2_RECORD_LEN 20 -struct mld2_record { - uint8_t type; - uint8_t aux_len; - ovs_be16 nsrcs; - union ovs_16aligned_in6_addr maddr; -}; -BUILD_ASSERT_DECL(MLD2_RECORD_LEN == sizeof(struct mld2_record)); - -#define MLD_QUERY 130 -#define MLD_REPORT 131 -#define MLD_DONE 132 -#define MLD2_REPORT 143 - -/* The IPv6 flow label is in the lower 20 bits of the first 32-bit word. */ -#define IPV6_LABEL_MASK 0x000fffff - -/* Example: - * - * char *string = "1 ::1 2"; - * char ipv6_s[IPV6_SCAN_LEN + 1]; - * struct in6_addr ipv6; - * - * if (ovs_scan(string, "%d"IPV6_SCAN_FMT"%d", &a, ipv6_s, &b) - * && inet_pton(AF_INET6, ipv6_s, &ipv6) == 1) { - * ... - * } - */ -#define IPV6_SCAN_FMT "%46[0123456789abcdefABCDEF:.]" -#define IPV6_SCAN_LEN 46 - -extern const struct in6_addr in6addr_exact; -#define IN6ADDR_EXACT_INIT { { { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, \ - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } } } - -extern const struct in6_addr in6addr_all_hosts; -#define IN6ADDR_ALL_HOSTS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 } } } - -extern const struct in6_addr in6addr_all_routers; -#define IN6ADDR_ALL_ROUTERS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \ - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 } } } - -static inline bool ipv6_addr_equals(const struct in6_addr *a, - const struct in6_addr *b) -{ -#ifdef IN6_ARE_ADDR_EQUAL - return IN6_ARE_ADDR_EQUAL(a, b); -#else - return !memcmp(a, b, sizeof(*a)); -#endif -} - -/* Checks the IPv6 address in 'mask' for all zeroes. */ -static inline bool ipv6_mask_is_any(const struct in6_addr *mask) { - return ipv6_addr_equals(mask, &in6addr_any); -} - -static inline bool ipv6_mask_is_exact(const struct in6_addr *mask) { - return ipv6_addr_equals(mask, &in6addr_exact); -} - -static inline bool ipv6_is_all_hosts(const struct in6_addr *addr) { - return ipv6_addr_equals(addr, &in6addr_all_hosts); -} - -static inline bool ipv6_addr_is_set(const struct in6_addr *addr) { - return !ipv6_addr_equals(addr, &in6addr_any); -} - -static inline bool ipv6_addr_is_multicast(const struct in6_addr *ip) { - return ip->s6_addr[0] == 0xff; -} - -static inline struct in6_addr -in6_addr_mapped_ipv4(ovs_be32 ip4) -{ - struct in6_addr ip6; - memset(&ip6, 0, sizeof(ip6)); - ip6.s6_addr[10] = 0xff, ip6.s6_addr[11] = 0xff; - memcpy(&ip6.s6_addr[12], &ip4, 4); - return ip6; -} - -static inline void -in6_addr_set_mapped_ipv4(struct in6_addr *ip6, ovs_be32 ip4) -{ - *ip6 = in6_addr_mapped_ipv4(ip4); -} - -static inline ovs_be32 -in6_addr_get_mapped_ipv4(const struct in6_addr *addr) -{ - union ovs_16aligned_in6_addr *taddr = - (union ovs_16aligned_in6_addr *) addr; - if (IN6_IS_ADDR_V4MAPPED(addr)) { - return get_16aligned_be32(&taddr->be32[3]); - } else { - return INADDR_ANY; - } -} - -void in6_addr_solicited_node(struct in6_addr *addr, - const struct in6_addr *ip6); - -void in6_generate_eui64(struct eth_addr ea, const struct in6_addr *prefix, - struct in6_addr *lla); - -void in6_generate_lla(struct eth_addr ea, struct in6_addr *lla); - -/* Returns true if 'addr' is a link local address. Otherwise, false. */ -bool in6_is_lla(struct in6_addr *addr); - -void ipv6_multicast_to_ethernet(struct eth_addr *eth, - const struct in6_addr *ip6); - -static inline bool dl_type_is_ip_any(ovs_be16 dl_type) -{ - return dl_type == htons(ETH_TYPE_IP) - || dl_type == htons(ETH_TYPE_IPV6); -} - -/* Tunnel header */ - -/* GRE protocol header */ -struct gre_base_hdr { - ovs_be16 flags; - ovs_be16 protocol; -}; - -#define GRE_CSUM 0x8000 -#define GRE_ROUTING 0x4000 -#define GRE_KEY 0x2000 -#define GRE_SEQ 0x1000 -#define GRE_STRICT 0x0800 -#define GRE_REC 0x0700 -#define GRE_FLAGS 0x00F8 -#define GRE_VERSION 0x0007 - -/* - * ERSPAN protocol header and metadata - * - * Version 1 (Type II) header (8 octets [42:49]) - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Ver | VLAN | COS | En|T| Session ID | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Reserved | Index | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * - * ERSPAN Version 2 (Type III) header (12 octets [42:49]) - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Ver | VLAN | COS |BSO|T| Session ID | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Timestamp | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | SGT |P| FT | Hw ID |D|Gra|O| - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - */ - -/* ERSPAN has fixed 8-byte GRE header */ -#define ERSPAN_GREHDR_LEN 8 -#define ERSPAN_HDR(gre_base_hdr) \ - ((struct erspan_base_hdr *)((char *)gre_base_hdr + ERSPAN_GREHDR_LEN)) - -#define ERSPAN_V1_MDSIZE 4 -#define ERSPAN_V2_MDSIZE 8 - -#define ERSPAN_SID_MASK 0x03ff /* 10-bit Session ID. */ -#define ERSPAN_IDX_MASK 0xfffff /* v1 Index */ -#define ERSPAN_HWID_MASK 0x03f0 -#define ERSPAN_DIR_MASK 0x0008 - -struct erspan_base_hdr { -#ifdef WORDS_BIGENDIAN - uint8_t ver:4, - vlan_upper:4; - uint8_t vlan:8; - uint8_t cos:3, - en:2, - t:1, - session_id_upper:2; - uint8_t session_id:8; -#else - uint8_t vlan_upper:4, - ver:4; - uint8_t vlan:8; - uint8_t session_id_upper:2, - t:1, - en:2, - cos:3; - uint8_t session_id:8; -#endif -}; - -struct erspan_md2 { - ovs_16aligned_be32 timestamp; - ovs_be16 sgt; -#ifdef WORDS_BIGENDIAN - uint8_t p:1, - ft:5, - hwid_upper:2; - uint8_t hwid:4, - dir:1, - gra:2, - o:1; -#else - uint8_t hwid_upper:2, - ft:5, - p:1; - uint8_t o:1, - gra:2, - dir:1, - hwid:4; -#endif -}; - -struct erspan_metadata { - int version; - union { - ovs_be32 index; /* Version 1 (type II)*/ - struct erspan_md2 md2; /* Version 2 (type III) */ - } u; -}; - -static inline uint16_t get_sid(const struct erspan_base_hdr *ershdr) -{ - return (ershdr->session_id_upper << 8) + ershdr->session_id; -} - -static inline void set_sid(struct erspan_base_hdr *ershdr, uint16_t id) -{ - ershdr->session_id = id & 0xff; - ershdr->session_id_upper = (id >> 8) &0x3; -} - -static inline uint8_t get_hwid(const struct erspan_md2 *md2) -{ - return (md2->hwid_upper << 4) + md2->hwid; -} - -static inline void set_hwid(struct erspan_md2 *md2, uint8_t hwid) -{ - md2->hwid = hwid & 0xf; - md2->hwid_upper = (hwid >> 4) & 0x3; -} - -/* ERSPAN timestamp granularity - * 00b --> granularity = 100 microseconds - * 01b --> granularity = 100 nanoseconds - * 10b --> granularity = IEEE 1588 - * Here we only support 100 microseconds. - */ -enum erspan_ts_gra { - ERSPAN_100US, - ERSPAN_100NS, - ERSPAN_IEEE1588, -}; - -static inline ovs_be32 get_erspan_ts(enum erspan_ts_gra gra) -{ - ovs_be32 ts = 0; - - switch (gra) { - case ERSPAN_100US: - ts = htonl((uint32_t)(time_wall_usec() / 100)); - break; - case ERSPAN_100NS: - /* fall back */ - case ERSPAN_IEEE1588: - /* fall back */ - default: - OVS_NOT_REACHED(); - break; - } - return ts; -} - -/* - * GTP-U protocol header and metadata - * See: - * User Plane Protocol and Architectural Analysis on 3GPP 5G System - * draft-hmm-dmm-5g-uplane-analysis-00 - * - * 0 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Ver |P|R|E|S|N| Message Type| Length | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Tunnel Endpoint Identifier | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | Sequence Number | N-PDU Number | Next-Ext-Hdr | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * GTP-U Flags: - * P: Protocol Type (Set to '1') - * R: Reserved Bit (Set to '0') - * E: Extension Header Flag (Set to '1' if extension header exists) - * S: Sequence Number Flag (Set to '1' if sequence number exists) - * N: N-PDU Number Flag (Set to '1' if N-PDU number exists) - * - * GTP-U Message Type: - * Indicates the type of GTP-U message. - * - * GTP-U Length: - * Indicates the length in octets of the payload. - * - * User payload is transmitted in G-PDU packets. - */ - -#define GTPU_VER_MASK 0xe0 -#define GTPU_P_MASK 0x10 -#define GTPU_E_MASK 0x04 -#define GTPU_S_MASK 0x02 - -/* GTP-U UDP port. */ -#define GTPU_DST_PORT 2152 - -/* Default GTP-U flags: Ver = 1 and P = 1. */ -#define GTPU_FLAGS_DEFAULT 0x30 - -/* GTP-U message type for normal user plane PDU. */ -#define GTPU_MSGTYPE_REQ 1 /* Echo Request. */ -#define GTPU_MSGTYPE_REPL 2 /* Echo Reply. */ -#define GTPU_MSGTYPE_GPDU 255 /* User Payload. */ - -struct gtpu_metadata { - uint8_t flags; - uint8_t msgtype; -}; -BUILD_ASSERT_DECL(sizeof(struct gtpu_metadata) == 2); - -struct gtpuhdr { - struct gtpu_metadata md; - ovs_be16 len; - ovs_16aligned_be32 teid; -}; -BUILD_ASSERT_DECL(sizeof(struct gtpuhdr) == 8); - -struct gtpuhdr_opt { - ovs_be16 seqno; - uint8_t pdu_number; - uint8_t next_ext_type; -}; -BUILD_ASSERT_DECL(sizeof(struct gtpuhdr_opt) == 4); - -/* VXLAN protocol header */ -struct vxlanhdr { - union { - ovs_16aligned_be32 vx_flags; /* VXLAN flags. */ - struct { - uint8_t flags; /* VXLAN GPE flags. */ - uint8_t reserved[2]; /* 16 bits reserved. */ - uint8_t next_protocol; /* Next Protocol field for VXLAN GPE. */ - } vx_gpe; - }; - ovs_16aligned_be32 vx_vni; -}; -BUILD_ASSERT_DECL(sizeof(struct vxlanhdr) == 8); - -#define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */ - -/* - * VXLAN Generic Protocol Extension (VXLAN_F_GPE): - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * |R|R|Ver|I|P|R|O| Reserved |Next Protocol | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * | VXLAN Network Identifier (VNI) | Reserved | - * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - * - * Ver = Version. Indicates VXLAN GPE protocol version. - * - * P = Next Protocol Bit. The P bit is set to indicate that the - * Next Protocol field is present. - * - * O = OAM Flag Bit. The O bit is set to indicate that the packet - * is an OAM packet. - * - * Next Protocol = This 8 bit field indicates the protocol header - * immediately following the VXLAN GPE header. - * - * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 - */ - -/* Fields in struct vxlanhdr.vx_gpe.flags */ -#define VXLAN_GPE_FLAGS_VER 0x30 /* Version. */ -#define VXLAN_GPE_FLAGS_P 0x04 /* Next Protocol Bit. */ -#define VXLAN_GPE_FLAGS_O 0x01 /* OAM Bit. */ - -/* VXLAN-GPE header flags. */ -#define VXLAN_HF_VER ((1U <<29) | (1U <<28)) -#define VXLAN_HF_NP (1U <<26) -#define VXLAN_HF_OAM (1U <<24) - -#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \ - 0xff) - -/* VXLAN-GPE header Next Protocol. */ -#define VXLAN_GPE_NP_IPV4 0x01 -#define VXLAN_GPE_NP_IPV6 0x02 -#define VXLAN_GPE_NP_ETHERNET 0x03 -#define VXLAN_GPE_NP_NSH 0x04 - -#define VXLAN_F_GPE 0x4000 -#define VXLAN_HF_GPE 0x04000000 - -/* Input values for PACKET_TYPE macros have to be in host byte order. - * The _BE postfix indicates result is in network byte order. Otherwise result - * is in host byte order. */ -#define PACKET_TYPE(NS, NS_TYPE) ((uint32_t) ((NS) << 16 | (NS_TYPE))) -#define PACKET_TYPE_BE(NS, NS_TYPE) (htonl((NS) << 16 | (NS_TYPE))) - -/* Returns the host byte ordered namespace of 'packet type'. */ -static inline uint16_t -pt_ns(ovs_be32 packet_type) -{ - return ntohl(packet_type) >> 16; -} - -/* Returns the network byte ordered namespace type of 'packet type'. */ -static inline ovs_be16 -pt_ns_type_be(ovs_be32 packet_type) -{ - return be32_to_be16(packet_type); -} - -/* Returns the host byte ordered namespace type of 'packet type'. */ -static inline uint16_t -pt_ns_type(ovs_be32 packet_type) -{ - return ntohs(pt_ns_type_be(packet_type)); -} - -/* Well-known packet_type field values. */ -enum packet_type { - PT_ETH = PACKET_TYPE(OFPHTN_ONF, 0x0000), /* Default PT: Ethernet */ - PT_USE_NEXT_PROTO = PACKET_TYPE(OFPHTN_ONF, 0xfffe), /* Pseudo PT for decap. */ - PT_IPV4 = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_IP), - PT_IPV6 = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_IPV6), - PT_MPLS = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS), - PT_MPLS_MC = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS_MCAST), - PT_NSH = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_NSH), - PT_UNKNOWN = PACKET_TYPE(0xffff, 0xffff), /* Unknown packet type. */ -}; - - -void ipv6_format_addr(const struct in6_addr *addr, struct ds *); -void ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *, - bool bracket); -void ipv6_format_mapped(const struct in6_addr *addr, struct ds *); -void ipv6_format_masked(const struct in6_addr *addr, - const struct in6_addr *mask, struct ds *); -const char * ipv6_string_mapped(char *addr_str, const struct in6_addr *addr); -struct in6_addr ipv6_addr_bitand(const struct in6_addr *src, - const struct in6_addr *mask); -struct in6_addr ipv6_addr_bitxor(const struct in6_addr *a, - const struct in6_addr *b); -bool ipv6_is_zero(const struct in6_addr *a); -struct in6_addr ipv6_create_mask(int mask); -int ipv6_count_cidr_bits(const struct in6_addr *netmask); -bool ipv6_is_cidr(const struct in6_addr *netmask); - -bool ipv6_parse(const char *s, struct in6_addr *ip); -char *ipv6_parse_masked(const char *s, struct in6_addr *ipv6, - struct in6_addr *mask); -char *ipv6_parse_cidr(const char *s, struct in6_addr *ip, unsigned int *plen) - OVS_WARN_UNUSED_RESULT; -char *ipv6_parse_masked_len(const char *s, int *n, struct in6_addr *ipv6, - struct in6_addr *mask); -char *ipv6_parse_cidr_len(const char *s, int *n, struct in6_addr *ip, - unsigned int *plen) - OVS_WARN_UNUSED_RESULT; - -void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst, - const struct eth_addr eth_src, uint16_t eth_type, - size_t size); -void *snap_compose(struct dp_packet *, const struct eth_addr eth_dst, - const struct eth_addr eth_src, - unsigned int oui, uint16_t snap_type, size_t size); -void packet_set_ipv4(struct dp_packet *, ovs_be32 src, ovs_be32 dst, uint8_t tos, - uint8_t ttl); -void packet_set_ipv4_addr(struct dp_packet *packet, ovs_16aligned_be32 *addr, - ovs_be32 new_addr); -void packet_set_ipv6(struct dp_packet *, const struct in6_addr *src, - const struct in6_addr *dst, uint8_t tc, - ovs_be32 fl, uint8_t hlmit); -void packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto, - ovs_16aligned_be32 addr[4], - const struct in6_addr *new_addr, - bool recalculate_csum); -void packet_set_tcp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); -void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); -void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); -void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code); -void packet_set_nd(struct dp_packet *, const struct in6_addr *target, - const struct eth_addr sll, const struct eth_addr tll); -void packet_set_nd_ext(struct dp_packet *packet, - const ovs_16aligned_be32 rso_flags, - const uint8_t opt_type); -void packet_set_igmp3_query(struct dp_packet *, uint8_t max_resp, - ovs_be32 group, bool srs, uint8_t qrv, - uint8_t qqic); -void packet_format_tcp_flags(struct ds *, uint16_t); -const char *packet_tcp_flag_to_string(uint32_t flag); -void *compose_ipv6(struct dp_packet *packet, uint8_t proto, - const struct in6_addr *src, const struct in6_addr *dst, - uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size); -void compose_arp__(struct dp_packet *); -void compose_arp(struct dp_packet *, uint16_t arp_op, - const struct eth_addr arp_sha, - const struct eth_addr arp_tha, bool broadcast, - ovs_be32 arp_spa, ovs_be32 arp_tpa); -void compose_nd_ns(struct dp_packet *, const struct eth_addr eth_src, - const struct in6_addr *ipv6_src, - const struct in6_addr *ipv6_dst); -void compose_nd_na(struct dp_packet *, const struct eth_addr eth_src, - const struct eth_addr eth_dst, - const struct in6_addr *ipv6_src, - const struct in6_addr *ipv6_dst, - ovs_be32 rso_flags); -void compose_nd_ra(struct dp_packet *, - const struct eth_addr eth_src, - const struct eth_addr eth_dst, - const struct in6_addr *ipv6_src, - const struct in6_addr *ipv6_dst, - uint8_t cur_hop_limit, uint8_t mo_flags, - ovs_be16 router_lt, ovs_be32 reachable_time, - ovs_be32 retrans_timer, uint32_t mtu); -void packet_put_ra_prefix_opt(struct dp_packet *, - uint8_t plen, uint8_t la_flags, - ovs_be32 valid_lifetime, - ovs_be32 preferred_lifetime, - const ovs_be128 router_prefix); -uint32_t packet_csum_pseudoheader(const struct ip_header *); -void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6); - -#define DNS_HEADER_LEN 12 -struct dns_header { - ovs_be16 id; - uint8_t lo_flag; /* QR (1), OPCODE (4), AA (1), TC (1) and RD (1) */ - uint8_t hi_flag; /* RA (1), Z (3) and RCODE (4) */ - ovs_be16 qdcount; /* Num of entries in the question section. */ - ovs_be16 ancount; /* Num of resource records in the answer section. */ - - /* Num of name server records in the authority record section. */ - ovs_be16 nscount; - - /* Num of resource records in the additional records section. */ - ovs_be16 arcount; -}; - -BUILD_ASSERT_DECL(DNS_HEADER_LEN == sizeof(struct dns_header)); - -#define DNS_QUERY_TYPE_A 0x01 -#define DNS_QUERY_TYPE_AAAA 0x1c -#define DNS_QUERY_TYPE_ANY 0xff - -#define DNS_CLASS_IN 0x01 -#define DNS_DEFAULT_RR_TTL 3600 - -#endif /* packets.h */ Index: openvswitch-2.17.2/include/internal/packets.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/packets.h @@ -0,0 +1,1671 @@ +/* + * 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. + */ + +#ifndef PACKETS_H +#define PACKETS_H 1 + +#include +#include +#include +#include +#include "openvswitch/compiler.h" +#include "openvswitch/geneve.h" +#include "openvswitch/packets.h" +#include "openvswitch/types.h" +#include "openvswitch/nsh.h" +#include "odp-netlink.h" +#include "internal/random.h" +#include "internal/hash.h" +#include "internal/tun-metadata-private.h" +#include "internal/unaligned.h" +#include "internal/util.h" +#include "internal/timeval.h" + +struct dp_packet; +struct conn; +struct ds; + +/* Purely internal to OVS userspace. These flags should never be exposed to + * the outside world and so aren't included in the flags mask. */ + +/* Tunnel information is in userspace datapath format. */ +#define FLOW_TNL_F_UDPIF (1 << 4) + +static inline bool ipv6_addr_is_set(const struct in6_addr *addr); + +static inline bool +flow_tnl_dst_is_set(const struct flow_tnl *tnl) +{ + return tnl->ip_dst || ipv6_addr_is_set(&tnl->ipv6_dst); +} + +static inline bool +flow_tnl_src_is_set(const struct flow_tnl *tnl) +{ + return tnl->ip_src || ipv6_addr_is_set(&tnl->ipv6_src); +} + +struct in6_addr flow_tnl_dst(const struct flow_tnl *tnl); +struct in6_addr flow_tnl_src(const struct flow_tnl *tnl); + +/* Returns an offset to 'src' covering all the meaningful fields in 'src'. */ +static inline size_t +flow_tnl_size(const struct flow_tnl *src) +{ + if (!flow_tnl_dst_is_set(src)) { + /* Covers ip_dst and ipv6_dst only. */ + return offsetof(struct flow_tnl, ip_src); + } + if (src->flags & FLOW_TNL_F_UDPIF) { + /* Datapath format, cover all options we have. */ + return offsetof(struct flow_tnl, metadata.opts) + + src->metadata.present.len; + } + if (!src->metadata.present.map) { + /* No TLVs, opts is irrelevant. */ + return offsetof(struct flow_tnl, metadata.opts); + } + /* Have decoded TLVs, opts is relevant. */ + return sizeof *src; +} + +/* Copy flow_tnl, but avoid copying unused portions of tun_metadata. Unused + * data in 'dst' is NOT cleared, so this must not be used in cases where the + * uninitialized portion may be hashed over. */ +static inline void +flow_tnl_copy__(struct flow_tnl *dst, const struct flow_tnl *src) +{ + memcpy(dst, src, flow_tnl_size(src)); +} + +static inline bool +flow_tnl_equal(const struct flow_tnl *a, const struct flow_tnl *b) +{ + size_t a_size = flow_tnl_size(a); + + return a_size == flow_tnl_size(b) && !memcmp(a, b, a_size); +} + +/* Datapath packet metadata */ +struct pkt_metadata { +PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline0, + uint32_t recirc_id; /* Recirculation id carried with the + recirculating packets. 0 for packets + received from the wire. */ + uint32_t dp_hash; /* hash value computed by the recirculation + action. */ + uint32_t skb_priority; /* Packet priority for QoS. */ + uint32_t pkt_mark; /* Packet mark. */ + uint8_t ct_state; /* Connection state. */ + bool ct_orig_tuple_ipv6; + uint16_t ct_zone; /* Connection zone. */ + uint32_t ct_mark; /* Connection mark. */ + ovs_u128 ct_label; /* Connection label. */ + union flow_in_port in_port; /* Input port. */ + odp_port_t orig_in_port; /* Originating in_port for tunneled packets */ + struct conn *conn; /* Cached conntrack connection. */ + bool reply; /* True if reply direction. */ + bool icmp_related; /* True if ICMP related. */ +); + +PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline1, + union { /* Populated only for non-zero 'ct_state'. */ + struct ovs_key_ct_tuple_ipv4 ipv4; + struct ovs_key_ct_tuple_ipv6 ipv6; /* Used only if */ + } ct_orig_tuple; /* 'ct_orig_tuple_ipv6' is set */ +); + +PADDED_MEMBERS_CACHELINE_MARKER(CACHE_LINE_SIZE, cacheline2, + struct flow_tnl tunnel; /* Encapsulating tunnel parameters. Note that + * if 'ip_dst' == 0, the rest of the fields may + * be uninitialized. */ +); +}; + +BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline0) == 0); +BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline1) == + CACHE_LINE_SIZE); +BUILD_ASSERT_DECL(offsetof(struct pkt_metadata, cacheline2) == + 2 * CACHE_LINE_SIZE); + +static inline void +pkt_metadata_init_tnl(struct pkt_metadata *md) +{ + odp_port_t orig_in_port; + + /* Zero up through the tunnel metadata options. The length and table + * are before this and as long as they are empty, the options won't + * be looked at. Keep the orig_in_port field. */ + orig_in_port = md->in_port.odp_port; + memset(md, 0, offsetof(struct pkt_metadata, tunnel.metadata.opts)); + md->orig_in_port = orig_in_port; +} + +static inline void +pkt_metadata_init_conn(struct pkt_metadata *md) +{ + md->conn = NULL; +} + +static inline void +pkt_metadata_init(struct pkt_metadata *md, odp_port_t port) +{ + /* This is called for every packet in userspace datapath and affects + * performance if all the metadata is initialized. Hence, fields should + * only be zeroed out when necessary. + * + * Initialize only till ct_state. Once the ct_state is zeroed out rest + * of ct fields will not be looked at unless ct_state != 0. + */ + memset(md, 0, offsetof(struct pkt_metadata, ct_orig_tuple_ipv6)); + + /* It can be expensive to zero out all of the tunnel metadata. However, + * we can just zero out ip_dst and the rest of the data will never be + * looked at. */ + md->tunnel.ip_dst = 0; + md->tunnel.ipv6_dst = in6addr_any; + md->in_port.odp_port = port; + md->orig_in_port = port; + md->conn = NULL; +} + +/* This function prefetches the cachelines touched by pkt_metadata_init() + * and pkt_metadata_init_tnl(). For performance reasons the two functions + * should be kept in sync. */ +static inline void +pkt_metadata_prefetch_init(struct pkt_metadata *md) +{ + /* Prefetch cacheline0 as members till ct_state and odp_port will + * be initialized later in pkt_metadata_init(). */ + OVS_PREFETCH(md->cacheline0); + + /* Prefetch cacheline1 as members of this cacheline will be zeroed out + * in pkt_metadata_init_tnl(). */ + OVS_PREFETCH(md->cacheline1); + + /* Prefetch cachline2 as ip_dst & ipv6_dst fields will be initialized. */ + OVS_PREFETCH(md->cacheline2); +} + +bool dpid_from_string(const char *s, uint64_t *dpidp); + +#define ETH_ADDR_LEN 6 + +static const struct eth_addr eth_addr_broadcast OVS_UNUSED + = ETH_ADDR_C(ff,ff,ff,ff,ff,ff); + +static const struct eth_addr eth_addr_exact OVS_UNUSED + = ETH_ADDR_C(ff,ff,ff,ff,ff,ff); + +static const struct eth_addr eth_addr_zero OVS_UNUSED + = ETH_ADDR_C(00,00,00,00,00,00); +static const struct eth_addr64 eth_addr64_zero OVS_UNUSED + = ETH_ADDR64_C(00,00,00,00,00,00,00,00); + +static const struct eth_addr eth_addr_stp OVS_UNUSED + = ETH_ADDR_C(01,80,c2,00,00,00); + +static const struct eth_addr eth_addr_lacp OVS_UNUSED + = ETH_ADDR_C(01,80,c2,00,00,02); + +static const struct eth_addr eth_addr_bfd OVS_UNUSED + = ETH_ADDR_C(00,23,20,00,00,01); + +static inline bool eth_addr_is_broadcast(const struct eth_addr a) +{ + return (a.be16[0] & a.be16[1] & a.be16[2]) == htons(0xffff); +} + +static inline bool eth_addr_is_multicast(const struct eth_addr a) +{ + return a.ea[0] & 1; +} + +static inline bool eth_addr_is_local(const struct eth_addr a) +{ + /* Local if it is either a locally administered address or a Nicira random + * address. */ + return a.ea[0] & 2 + || (a.be16[0] == htons(0x0023) + && (a.be16[1] & htons(0xff80)) == htons(0x2080)); +} +static inline bool eth_addr_is_zero(const struct eth_addr a) +{ + return !(a.be16[0] | a.be16[1] | a.be16[2]); +} +static inline bool eth_addr64_is_zero(const struct eth_addr64 a) +{ + return !(a.be16[0] | a.be16[1] | a.be16[2] | a.be16[3]); +} + +static inline int eth_mask_is_exact(const struct eth_addr a) +{ + return (a.be16[0] & a.be16[1] & a.be16[2]) == htons(0xffff); +} + +static inline int eth_addr_compare_3way(const struct eth_addr a, + const struct eth_addr b) +{ + return memcmp(&a, &b, sizeof a); +} +static inline int eth_addr64_compare_3way(const struct eth_addr64 a, + const struct eth_addr64 b) +{ + return memcmp(&a, &b, sizeof a); +} + +static inline bool eth_addr_equals(const struct eth_addr a, + const struct eth_addr b) +{ + return !eth_addr_compare_3way(a, b); +} +static inline bool eth_addr64_equals(const struct eth_addr64 a, + const struct eth_addr64 b) +{ + return !eth_addr64_compare_3way(a, b); +} + +static inline bool eth_addr_equal_except(const struct eth_addr a, + const struct eth_addr b, + const struct eth_addr mask) +{ + return !(((a.be16[0] ^ b.be16[0]) & mask.be16[0]) + || ((a.be16[1] ^ b.be16[1]) & mask.be16[1]) + || ((a.be16[2] ^ b.be16[2]) & mask.be16[2])); +} + +uint64_t eth_addr_to_uint64(const struct eth_addr ea); + +static inline uint64_t eth_addr_vlan_to_uint64(const struct eth_addr ea, + uint16_t vlan) +{ + return (((uint64_t)vlan << 48) | eth_addr_to_uint64(ea)); +} + +void eth_addr_from_uint64(uint64_t x, struct eth_addr *ea); + +static inline struct eth_addr eth_addr_invert(const struct eth_addr src) +{ + struct eth_addr dst; + + for (int i = 0; i < ARRAY_SIZE(src.be16); i++) { + dst.be16[i] = ~src.be16[i]; + } + + return dst; +} + +void eth_addr_mark_random(struct eth_addr *ea); + +static inline void eth_addr_random(struct eth_addr *ea) +{ + random_bytes((uint8_t *)ea, sizeof *ea); + eth_addr_mark_random(ea); +} + +static inline void eth_addr_nicira_random(struct eth_addr *ea) +{ + eth_addr_random(ea); + + /* Set the OUI to the Nicira one. */ + ea->ea[0] = 0x00; + ea->ea[1] = 0x23; + ea->ea[2] = 0x20; + + /* Set the top bit to indicate random Nicira address. */ + ea->ea[3] |= 0x80; +} +static inline uint32_t hash_mac(const struct eth_addr ea, + const uint16_t vlan, const uint32_t basis) +{ + return hash_uint64_basis(eth_addr_vlan_to_uint64(ea, vlan), basis); +} + +bool eth_addr_is_reserved(const struct eth_addr); +bool eth_addr_from_string(const char *, struct eth_addr *); + +void compose_rarp(struct dp_packet *, const struct eth_addr); + +void eth_push_vlan(struct dp_packet *, ovs_be16 tpid, ovs_be16 tci); +void eth_pop_vlan(struct dp_packet *); + +const char *eth_from_hex(const char *hex, struct dp_packet **packetp); +void eth_format_masked(const struct eth_addr ea, + const struct eth_addr *mask, struct ds *s); + +void set_mpls_lse(struct dp_packet *, ovs_be32 label); +void push_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse); +void pop_mpls(struct dp_packet *, ovs_be16 ethtype); + +void set_mpls_lse_ttl(ovs_be32 *lse, uint8_t ttl); +void set_mpls_lse_tc(ovs_be32 *lse, uint8_t tc); +void set_mpls_lse_label(ovs_be32 *lse, ovs_be32 label); +void set_mpls_lse_bos(ovs_be32 *lse, uint8_t bos); +ovs_be32 set_mpls_lse_values(uint8_t ttl, uint8_t tc, uint8_t bos, + ovs_be32 label); +void add_mpls(struct dp_packet *packet, ovs_be16 ethtype, ovs_be32 lse, + bool l3_encap); + +/* Example: + * + * struct eth_addr mac; + * [...] + * printf("The Ethernet address is "ETH_ADDR_FMT"\n", ETH_ADDR_ARGS(mac)); + * + */ +#define ETH_ADDR_FMT \ + "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8 +#define ETH_ADDR_ARGS(EA) ETH_ADDR_BYTES_ARGS((EA).ea) +#define ETH_ADDR_BYTES_ARGS(EAB) \ + (EAB)[0], (EAB)[1], (EAB)[2], (EAB)[3], (EAB)[4], (EAB)[5] +#define ETH_ADDR_STRLEN 17 + +/* Example: + * + * struct eth_addr64 eui64; + * [...] + * printf("The EUI-64 address is "ETH_ADDR64_FMT"\n", ETH_ADDR64_ARGS(mac)); + * + */ +#define ETH_ADDR64_FMT \ + "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8":" \ + "%02"PRIx8":%02"PRIx8":%02"PRIx8":%02"PRIx8 +#define ETH_ADDR64_ARGS(EA) ETH_ADDR64_BYTES_ARGS((EA).ea64) +#define ETH_ADDR64_BYTES_ARGS(EAB) \ + (EAB)[0], (EAB)[1], (EAB)[2], (EAB)[3], \ + (EAB)[4], (EAB)[5], (EAB)[6], (EAB)[7] +#define ETH_ADDR64_STRLEN 23 + +/* Example: + * + * char *string = "1 00:11:22:33:44:55 2"; + * struct eth_addr mac; + * int a, b; + * + * if (ovs_scan(string, "%d"ETH_ADDR_SCAN_FMT"%d", + * &a, ETH_ADDR_SCAN_ARGS(mac), &b)) { + * ... + * } + */ +#define ETH_ADDR_SCAN_FMT "%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8":%"SCNx8 +#define ETH_ADDR_SCAN_ARGS(EA) \ + &(EA).ea[0], &(EA).ea[1], &(EA).ea[2], &(EA).ea[3], &(EA).ea[4], &(EA).ea[5] + +#define ETH_TYPE_IP 0x0800 +#define ETH_TYPE_ARP 0x0806 +#define ETH_TYPE_TEB 0x6558 +#define ETH_TYPE_VLAN_8021Q 0x8100 +#define ETH_TYPE_VLAN ETH_TYPE_VLAN_8021Q +#define ETH_TYPE_VLAN_8021AD 0x88a8 +#define ETH_TYPE_IPV6 0x86dd +#define ETH_TYPE_LACP 0x8809 +#define ETH_TYPE_RARP 0x8035 +#define ETH_TYPE_MPLS 0x8847 +#define ETH_TYPE_MPLS_MCAST 0x8848 +#define ETH_TYPE_NSH 0x894f +#define ETH_TYPE_ERSPAN1 0x88be /* version 1 type II */ +#define ETH_TYPE_ERSPAN2 0x22eb /* version 2 type III */ + +static inline bool eth_type_mpls(ovs_be16 eth_type) +{ + return eth_type == htons(ETH_TYPE_MPLS) || + eth_type == htons(ETH_TYPE_MPLS_MCAST); +} + +static inline bool eth_type_vlan(ovs_be16 eth_type) +{ + return eth_type == htons(ETH_TYPE_VLAN_8021Q) || + eth_type == htons(ETH_TYPE_VLAN_8021AD); +} + + +/* Minimum value for an Ethernet type. Values below this are IEEE 802.2 frame + * lengths. */ +#define ETH_TYPE_MIN 0x600 + +#define ETH_HEADER_LEN 14 +#define ETH_PAYLOAD_MIN 46 +#define ETH_PAYLOAD_MAX 1500 +#define ETH_TOTAL_MIN (ETH_HEADER_LEN + ETH_PAYLOAD_MIN) +#define ETH_TOTAL_MAX (ETH_HEADER_LEN + ETH_PAYLOAD_MAX) +#define ETH_VLAN_TOTAL_MAX (ETH_HEADER_LEN + VLAN_HEADER_LEN + ETH_PAYLOAD_MAX) +struct eth_header { + struct eth_addr eth_dst; + struct eth_addr eth_src; + ovs_be16 eth_type; +}; +BUILD_ASSERT_DECL(ETH_HEADER_LEN == sizeof(struct eth_header)); + +void push_eth(struct dp_packet *packet, const struct eth_addr *dst, + const struct eth_addr *src); +void pop_eth(struct dp_packet *packet); + +void push_nsh(struct dp_packet *packet, const struct nsh_hdr *nsh_hdr_src); +bool pop_nsh(struct dp_packet *packet); + +#define LLC_DSAP_SNAP 0xaa +#define LLC_SSAP_SNAP 0xaa +#define LLC_CNTL_SNAP 3 + +#define LLC_HEADER_LEN 3 +struct llc_header { + uint8_t llc_dsap; + uint8_t llc_ssap; + uint8_t llc_cntl; +}; +BUILD_ASSERT_DECL(LLC_HEADER_LEN == sizeof(struct llc_header)); + +/* LLC field values used for STP frames. */ +#define STP_LLC_SSAP 0x42 +#define STP_LLC_DSAP 0x42 +#define STP_LLC_CNTL 0x03 + +#define SNAP_ORG_ETHERNET "\0\0" /* The compiler adds a null byte, so + sizeof(SNAP_ORG_ETHERNET) == 3. */ +#define SNAP_HEADER_LEN 5 +OVS_PACKED( +struct snap_header { + uint8_t snap_org[3]; + ovs_be16 snap_type; +}); +BUILD_ASSERT_DECL(SNAP_HEADER_LEN == sizeof(struct snap_header)); + +#define LLC_SNAP_HEADER_LEN (LLC_HEADER_LEN + SNAP_HEADER_LEN) +OVS_PACKED( +struct llc_snap_header { + struct llc_header llc; + struct snap_header snap; +}); +BUILD_ASSERT_DECL(LLC_SNAP_HEADER_LEN == sizeof(struct llc_snap_header)); + +#define VLAN_VID_MASK 0x0fff +#define VLAN_VID_SHIFT 0 + +#define VLAN_PCP_MASK 0xe000 +#define VLAN_PCP_SHIFT 13 + +#define VLAN_CFI 0x1000 +#define VLAN_CFI_SHIFT 12 + +/* Given the vlan_tci field from an 802.1Q header, in network byte order, + * returns the VLAN ID in host byte order. */ +static inline uint16_t +vlan_tci_to_vid(ovs_be16 vlan_tci) +{ + return (ntohs(vlan_tci) & VLAN_VID_MASK) >> VLAN_VID_SHIFT; +} + +/* Given the vlan_tci field from an 802.1Q header, in network byte order, + * returns the priority code point (PCP) in host byte order. */ +static inline int +vlan_tci_to_pcp(ovs_be16 vlan_tci) +{ + return (ntohs(vlan_tci) & VLAN_PCP_MASK) >> VLAN_PCP_SHIFT; +} + +/* Given the vlan_tci field from an 802.1Q header, in network byte order, + * returns the Canonical Format Indicator (CFI). */ +static inline int +vlan_tci_to_cfi(ovs_be16 vlan_tci) +{ + return (vlan_tci & htons(VLAN_CFI)) != 0; +} + +#define VLAN_HEADER_LEN 4 +struct vlan_header { + ovs_be16 vlan_tci; /* Lowest 12 bits are VLAN ID. */ + ovs_be16 vlan_next_type; +}; +BUILD_ASSERT_DECL(VLAN_HEADER_LEN == sizeof(struct vlan_header)); + +#define VLAN_ETH_HEADER_LEN (ETH_HEADER_LEN + VLAN_HEADER_LEN) +struct vlan_eth_header { + struct eth_addr veth_dst; + struct eth_addr veth_src; + ovs_be16 veth_type; /* Always htons(ETH_TYPE_VLAN). */ + ovs_be16 veth_tci; /* Lowest 12 bits are VLAN ID. */ + ovs_be16 veth_next_type; +}; +BUILD_ASSERT_DECL(VLAN_ETH_HEADER_LEN == sizeof(struct vlan_eth_header)); + +/* MPLS related definitions */ +#define MPLS_TTL_MASK 0x000000ff +#define MPLS_TTL_SHIFT 0 + +#define MPLS_BOS_MASK 0x00000100 +#define MPLS_BOS_SHIFT 8 + +#define MPLS_TC_MASK 0x00000e00 +#define MPLS_TC_SHIFT 9 + +#define MPLS_LABEL_MASK 0xfffff000 +#define MPLS_LABEL_SHIFT 12 + +#define MPLS_HLEN 4 + +struct mpls_hdr { + ovs_16aligned_be32 mpls_lse; +}; +BUILD_ASSERT_DECL(MPLS_HLEN == sizeof(struct mpls_hdr)); + +/* Given a mpls label stack entry in network byte order + * return mpls label in host byte order */ +static inline uint32_t +mpls_lse_to_label(ovs_be32 mpls_lse) +{ + return (ntohl(mpls_lse) & MPLS_LABEL_MASK) >> MPLS_LABEL_SHIFT; +} + +/* Given a mpls label stack entry in network byte order + * return mpls tc */ +static inline uint8_t +mpls_lse_to_tc(ovs_be32 mpls_lse) +{ + return (ntohl(mpls_lse) & MPLS_TC_MASK) >> MPLS_TC_SHIFT; +} + +/* Given a mpls label stack entry in network byte order + * return mpls ttl */ +static inline uint8_t +mpls_lse_to_ttl(ovs_be32 mpls_lse) +{ + return (ntohl(mpls_lse) & MPLS_TTL_MASK) >> MPLS_TTL_SHIFT; +} + +/* Set label in mpls lse. */ +static inline void +flow_set_mpls_lse_label(ovs_be32 *mpls_lse, uint32_t label) +{ + *mpls_lse &= ~htonl(MPLS_LABEL_MASK); + *mpls_lse |= htonl(label << MPLS_LABEL_SHIFT); +} + +/* Set TC in mpls lse. */ +static inline void +flow_set_mpls_lse_tc(ovs_be32 *mpls_lse, uint8_t tc) +{ + *mpls_lse &= ~htonl(MPLS_TC_MASK); + *mpls_lse |= htonl((tc & 0x7) << MPLS_TC_SHIFT); +} + +/* Set BOS in mpls lse. */ +static inline void +flow_set_mpls_lse_bos(ovs_be32 *mpls_lse, uint8_t bos) +{ + *mpls_lse &= ~htonl(MPLS_BOS_MASK); + *mpls_lse |= htonl((bos & 0x1) << MPLS_BOS_SHIFT); +} + +/* Set TTL in mpls lse. */ +static inline void +flow_set_mpls_lse_ttl(ovs_be32 *mpls_lse, uint8_t ttl) +{ + *mpls_lse &= ~htonl(MPLS_TTL_MASK); + *mpls_lse |= htonl(ttl << MPLS_TTL_SHIFT); +} + +/* Given a mpls label stack entry in network byte order + * return mpls BoS bit */ +static inline uint8_t +mpls_lse_to_bos(ovs_be32 mpls_lse) +{ + return (mpls_lse & htonl(MPLS_BOS_MASK)) != 0; +} + +#define IP_FMT "%"PRIu32".%"PRIu32".%"PRIu32".%"PRIu32 +#define IP_ARGS(ip) \ + ntohl(ip) >> 24, \ + (ntohl(ip) >> 16) & 0xff, \ + (ntohl(ip) >> 8) & 0xff, \ + ntohl(ip) & 0xff + +/* Example: + * + * char *string = "1 33.44.55.66 2"; + * ovs_be32 ip; + * int a, b; + * + * if (ovs_scan(string, "%d"IP_SCAN_FMT"%d", &a, IP_SCAN_ARGS(&ip), &b)) { + * ... + * } + */ +#define IP_SCAN_FMT "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8 +#define IP_SCAN_ARGS(ip) \ + ((void) (ovs_be32) *(ip), &((uint8_t *) ip)[0]), \ + &((uint8_t *) ip)[1], \ + &((uint8_t *) ip)[2], \ + &((uint8_t *) ip)[3] + +#define IP_PORT_SCAN_FMT "%"SCNu8".%"SCNu8".%"SCNu8".%"SCNu8":%"SCNu16 +#define IP_PORT_SCAN_ARGS(ip, port) \ + ((void) (ovs_be32) *(ip), &((uint8_t *) ip)[0]), \ + &((uint8_t *) ip)[1], \ + &((uint8_t *) ip)[2], \ + &((uint8_t *) ip)[3], \ + ((void) (ovs_be16) *(port), (uint16_t *) port) + +/* Returns true if 'netmask' is a CIDR netmask, that is, if it consists of N + * high-order 1-bits and 32-N low-order 0-bits. */ +static inline bool +ip_is_cidr(ovs_be32 netmask) +{ + uint32_t x = ~ntohl(netmask); + return !(x & (x + 1)); +} +static inline bool +ip_is_multicast(ovs_be32 ip) +{ + return (ip & htonl(0xf0000000)) == htonl(0xe0000000); +} +static inline bool +ip_is_local_multicast(ovs_be32 ip) +{ + return (ip & htonl(0xffffff00)) == htonl(0xe0000000); +} +int ip_count_cidr_bits(ovs_be32 netmask); +void ip_format_masked(ovs_be32 ip, ovs_be32 mask, struct ds *); +bool ip_parse(const char *s, ovs_be32 *ip); +char *ip_parse_port(const char *s, ovs_be32 *ip, ovs_be16 *port) + OVS_WARN_UNUSED_RESULT; +char *ip_parse_masked(const char *s, ovs_be32 *ip, ovs_be32 *mask) + OVS_WARN_UNUSED_RESULT; +char *ip_parse_cidr(const char *s, ovs_be32 *ip, unsigned int *plen) + OVS_WARN_UNUSED_RESULT; +char *ip_parse_masked_len(const char *s, int *n, ovs_be32 *ip, ovs_be32 *mask) + OVS_WARN_UNUSED_RESULT; +char *ip_parse_cidr_len(const char *s, int *n, ovs_be32 *ip, + unsigned int *plen) + OVS_WARN_UNUSED_RESULT; + +#define IP_VER(ip_ihl_ver) ((ip_ihl_ver) >> 4) +#define IP_IHL(ip_ihl_ver) ((ip_ihl_ver) & 15) +#define IP_IHL_VER(ihl, ver) (((ver) << 4) | (ihl)) + +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + +#ifndef IPPROTO_DCCP +#define IPPROTO_DCCP 33 +#endif + +#ifndef IPPROTO_IGMP +#define IPPROTO_IGMP 2 +#endif + +#ifndef IPPROTO_UDPLITE +#define IPPROTO_UDPLITE 136 +#endif + +/* TOS fields. */ +#define IP_ECN_NOT_ECT 0x0 +#define IP_ECN_ECT_1 0x01 +#define IP_ECN_ECT_0 0x02 +#define IP_ECN_CE 0x03 +#define IP_ECN_MASK 0x03 +#define IP_DSCP_CS6 0xc0 +#define IP_DSCP_MASK 0xfc + +static inline int +IP_ECN_is_ce(uint8_t dsfield) +{ + return (dsfield & IP_ECN_MASK) == IP_ECN_CE; +} + +#define IP_VERSION 4 + +#define IP_DONT_FRAGMENT 0x4000 /* Don't fragment. */ +#define IP_MORE_FRAGMENTS 0x2000 /* More fragments. */ +#define IP_FRAG_OFF_MASK 0x1fff /* Fragment offset. */ +#define IP_IS_FRAGMENT(ip_frag_off) \ + ((ip_frag_off) & htons(IP_MORE_FRAGMENTS | IP_FRAG_OFF_MASK)) + +#define IP_HEADER_LEN 20 +struct ip_header { + uint8_t ip_ihl_ver; + uint8_t ip_tos; + ovs_be16 ip_tot_len; + ovs_be16 ip_id; + ovs_be16 ip_frag_off; + uint8_t ip_ttl; + uint8_t ip_proto; + ovs_be16 ip_csum; + ovs_16aligned_be32 ip_src; + ovs_16aligned_be32 ip_dst; +}; +BUILD_ASSERT_DECL(IP_HEADER_LEN == sizeof(struct ip_header)); + +/* ICMPv4 types. */ +#define ICMP4_ECHO_REPLY 0 +#define ICMP4_DST_UNREACH 3 +#define ICMP4_SOURCEQUENCH 4 +#define ICMP4_REDIRECT 5 +#define ICMP4_ECHO_REQUEST 8 +#define ICMP4_TIME_EXCEEDED 11 +#define ICMP4_PARAM_PROB 12 +#define ICMP4_TIMESTAMP 13 +#define ICMP4_TIMESTAMPREPLY 14 +#define ICMP4_INFOREQUEST 15 +#define ICMP4_INFOREPLY 16 + +#define ICMP_HEADER_LEN 8 +struct icmp_header { + uint8_t icmp_type; + uint8_t icmp_code; + ovs_be16 icmp_csum; + union { + struct { + ovs_be16 id; + ovs_be16 seq; + } echo; + struct { + ovs_be16 empty; + ovs_be16 mtu; + } frag; + ovs_16aligned_be32 gateway; + } icmp_fields; +}; +BUILD_ASSERT_DECL(ICMP_HEADER_LEN == sizeof(struct icmp_header)); + +/* ICMPV4 */ +#define ICMP_ERROR_DATA_L4_LEN 8 + +#define IGMP_HEADER_LEN 8 +struct igmp_header { + uint8_t igmp_type; + uint8_t igmp_code; + ovs_be16 igmp_csum; + ovs_16aligned_be32 group; +}; +BUILD_ASSERT_DECL(IGMP_HEADER_LEN == sizeof(struct igmp_header)); + +#define IGMPV3_HEADER_LEN 8 +struct igmpv3_header { + uint8_t type; + uint8_t rsvr1; + ovs_be16 csum; + ovs_be16 rsvr2; + ovs_be16 ngrp; +}; +BUILD_ASSERT_DECL(IGMPV3_HEADER_LEN == sizeof(struct igmpv3_header)); + +#define IGMPV3_QUERY_HEADER_LEN 12 +struct igmpv3_query_header { + uint8_t type; + uint8_t max_resp; + ovs_be16 csum; + ovs_16aligned_be32 group; + uint8_t srs_qrv; + uint8_t qqic; + ovs_be16 nsrcs; +}; +BUILD_ASSERT_DECL( + IGMPV3_QUERY_HEADER_LEN == sizeof(struct igmpv3_query_header +)); + +#define IGMPV3_RECORD_LEN 8 +struct igmpv3_record { + uint8_t type; + uint8_t aux_len; + ovs_be16 nsrcs; + ovs_16aligned_be32 maddr; +}; +BUILD_ASSERT_DECL(IGMPV3_RECORD_LEN == sizeof(struct igmpv3_record)); + +#define IGMP_HOST_MEMBERSHIP_QUERY 0x11 /* From RFC1112 */ +#define IGMP_HOST_MEMBERSHIP_REPORT 0x12 /* Ditto */ +#define IGMPV2_HOST_MEMBERSHIP_REPORT 0x16 /* V2 version of 0x12 */ +#define IGMP_HOST_LEAVE_MESSAGE 0x17 +#define IGMPV3_HOST_MEMBERSHIP_REPORT 0x22 /* V3 version of 0x12 */ + +/* + * IGMPv3 and MLDv2 use the same codes. + */ +#define IGMPV3_MODE_IS_INCLUDE 1 +#define IGMPV3_MODE_IS_EXCLUDE 2 +#define IGMPV3_CHANGE_TO_INCLUDE_MODE 3 +#define IGMPV3_CHANGE_TO_EXCLUDE_MODE 4 +#define IGMPV3_ALLOW_NEW_SOURCES 5 +#define IGMPV3_BLOCK_OLD_SOURCES 6 + +#define SCTP_HEADER_LEN 12 +struct sctp_header { + ovs_be16 sctp_src; + ovs_be16 sctp_dst; + ovs_16aligned_be32 sctp_vtag; + ovs_16aligned_be32 sctp_csum; +}; +BUILD_ASSERT_DECL(SCTP_HEADER_LEN == sizeof(struct sctp_header)); + +#define UDP_HEADER_LEN 8 +struct udp_header { + ovs_be16 udp_src; + ovs_be16 udp_dst; + ovs_be16 udp_len; + ovs_be16 udp_csum; +}; +BUILD_ASSERT_DECL(UDP_HEADER_LEN == sizeof(struct udp_header)); + +#define ESP_HEADER_LEN 8 +struct esp_header { + ovs_be32 spi; + ovs_be32 seq_no; +}; +BUILD_ASSERT_DECL(ESP_HEADER_LEN == sizeof(struct esp_header)); + +#define ESP_TRAILER_LEN 2 +struct esp_trailer { + uint8_t pad_len; + uint8_t next_hdr; +}; +BUILD_ASSERT_DECL(ESP_TRAILER_LEN == sizeof(struct esp_trailer)); + +#define TCP_FIN 0x001 +#define TCP_SYN 0x002 +#define TCP_RST 0x004 +#define TCP_PSH 0x008 +#define TCP_ACK 0x010 +#define TCP_URG 0x020 +#define TCP_ECE 0x040 +#define TCP_CWR 0x080 +#define TCP_NS 0x100 + +#define TCP_CTL(flags, offset) (htons((flags) | ((offset) << 12))) +#define TCP_FLAGS(tcp_ctl) (ntohs(tcp_ctl) & 0x0fff) +#define TCP_FLAGS_BE16(tcp_ctl) ((tcp_ctl) & htons(0x0fff)) +#define TCP_OFFSET(tcp_ctl) (ntohs(tcp_ctl) >> 12) + +#define TCP_HEADER_LEN 20 +struct tcp_header { + ovs_be16 tcp_src; + ovs_be16 tcp_dst; + ovs_16aligned_be32 tcp_seq; + ovs_16aligned_be32 tcp_ack; + ovs_be16 tcp_ctl; + ovs_be16 tcp_winsz; + ovs_be16 tcp_csum; + ovs_be16 tcp_urg; +}; +BUILD_ASSERT_DECL(TCP_HEADER_LEN == sizeof(struct tcp_header)); + +/* Connection states. + * + * Names like CS_RELATED are bit values, e.g. 1 << 2. + * Names like CS_RELATED_BIT are bit indexes, e.g. 2. */ +#define CS_STATES \ + CS_STATE(NEW, 0, "new") \ + CS_STATE(ESTABLISHED, 1, "est") \ + CS_STATE(RELATED, 2, "rel") \ + CS_STATE(REPLY_DIR, 3, "rpl") \ + CS_STATE(INVALID, 4, "inv") \ + CS_STATE(TRACKED, 5, "trk") \ + CS_STATE(SRC_NAT, 6, "snat") \ + CS_STATE(DST_NAT, 7, "dnat") + +enum { +#define CS_STATE(ENUM, INDEX, NAME) \ + CS_##ENUM = 1 << INDEX, \ + CS_##ENUM##_BIT = INDEX, + CS_STATES +#undef CS_STATE +}; + +/* Undefined connection state bits. */ +enum { +#define CS_STATE(ENUM, INDEX, NAME) +CS_##ENUM + CS_SUPPORTED_MASK = CS_STATES +#undef CS_STATE +}; +#define CS_UNSUPPORTED_MASK (~(uint32_t)CS_SUPPORTED_MASK) + +#define ARP_HRD_ETHERNET 1 +#define ARP_PRO_IP 0x0800 +#define ARP_OP_REQUEST 1 +#define ARP_OP_REPLY 2 +#define ARP_OP_RARP 3 + +#define ARP_ETH_HEADER_LEN 28 +struct arp_eth_header { + /* Generic members. */ + ovs_be16 ar_hrd; /* Hardware type. */ + ovs_be16 ar_pro; /* Protocol type. */ + uint8_t ar_hln; /* Hardware address length. */ + uint8_t ar_pln; /* Protocol address length. */ + ovs_be16 ar_op; /* Opcode. */ + + /* Ethernet+IPv4 specific members. */ + struct eth_addr ar_sha; /* Sender hardware address. */ + ovs_16aligned_be32 ar_spa; /* Sender protocol address. */ + struct eth_addr ar_tha; /* Target hardware address. */ + ovs_16aligned_be32 ar_tpa; /* Target protocol address. */ +}; +BUILD_ASSERT_DECL(ARP_ETH_HEADER_LEN == sizeof(struct arp_eth_header)); + +#define IPV6_HEADER_LEN 40 + +/* Like struct in6_addr, but whereas that struct requires 32-bit alignment on + * most implementations, this one only requires 16-bit alignment. */ +union ovs_16aligned_in6_addr { + ovs_be16 be16[8]; + ovs_16aligned_be32 be32[4]; +}; + +/* Like struct ip6_hdr, but whereas that struct requires 32-bit alignment, this + * one only requires 16-bit alignment. */ +struct ovs_16aligned_ip6_hdr { + union { + struct ovs_16aligned_ip6_hdrctl { + ovs_16aligned_be32 ip6_un1_flow; + ovs_be16 ip6_un1_plen; + uint8_t ip6_un1_nxt; + uint8_t ip6_un1_hlim; + } ip6_un1; + uint8_t ip6_un2_vfc; + } ip6_ctlun; + union ovs_16aligned_in6_addr ip6_src; + union ovs_16aligned_in6_addr ip6_dst; +}; + +/* Like struct in6_frag, but whereas that struct requires 32-bit alignment, + * this one only requires 16-bit alignment. */ +struct ovs_16aligned_ip6_frag { + uint8_t ip6f_nxt; + uint8_t ip6f_reserved; + ovs_be16 ip6f_offlg; + ovs_16aligned_be32 ip6f_ident; +}; + +#define ICMP6_HEADER_LEN 4 +struct icmp6_header { + uint8_t icmp6_type; + uint8_t icmp6_code; + ovs_be16 icmp6_cksum; +}; +BUILD_ASSERT_DECL(ICMP6_HEADER_LEN == sizeof(struct icmp6_header)); + +#define ICMP6_DATA_HEADER_LEN 8 +struct icmp6_data_header { + struct icmp6_header icmp6_base; + union { + ovs_16aligned_be32 be32[1]; + ovs_be16 be16[2]; + uint8_t u8[4]; + } icmp6_data; +}; +BUILD_ASSERT_DECL(ICMP6_DATA_HEADER_LEN == sizeof(struct icmp6_data_header)); + +uint32_t packet_csum_pseudoheader6(const struct ovs_16aligned_ip6_hdr *); +ovs_be16 packet_csum_upperlayer6(const struct ovs_16aligned_ip6_hdr *, + const void *, uint8_t, uint16_t); + +/* Neighbor Discovery option field. + * ND options are always a multiple of 8 bytes in size. */ +#define ND_LLA_OPT_LEN 8 +struct ovs_nd_lla_opt { + uint8_t type; /* One of ND_OPT_*_LINKADDR. */ + uint8_t len; + struct eth_addr mac; +}; +BUILD_ASSERT_DECL(ND_LLA_OPT_LEN == sizeof(struct ovs_nd_lla_opt)); + +/* Neighbor Discovery option: Prefix Information. */ +#define ND_PREFIX_OPT_LEN 32 +struct ovs_nd_prefix_opt { + uint8_t type; /* ND_OPT_PREFIX_INFORMATION. */ + uint8_t len; /* Always 4. */ + uint8_t prefix_len; + uint8_t la_flags; /* ND_PREFIX_* flags. */ + ovs_16aligned_be32 valid_lifetime; + ovs_16aligned_be32 preferred_lifetime; + ovs_16aligned_be32 reserved; /* Always 0. */ + union ovs_16aligned_in6_addr prefix; +}; +BUILD_ASSERT_DECL(ND_PREFIX_OPT_LEN == sizeof(struct ovs_nd_prefix_opt)); + +/* Neighbor Discovery option: MTU. */ +#define ND_MTU_OPT_LEN 8 +#define ND_MTU_DEFAULT 0 +struct ovs_nd_mtu_opt { + uint8_t type; /* ND_OPT_MTU */ + uint8_t len; /* Always 1. */ + ovs_be16 reserved; /* Always 0. */ + ovs_16aligned_be32 mtu; +}; +BUILD_ASSERT_DECL(ND_MTU_OPT_LEN == sizeof(struct ovs_nd_mtu_opt)); + +/* Like struct nd_msg (from ndisc.h), but whereas that struct requires 32-bit + * alignment, this one only requires 16-bit alignment. */ +#define ND_MSG_LEN 24 +struct ovs_nd_msg { + struct icmp6_header icmph; + ovs_16aligned_be32 rso_flags; + union ovs_16aligned_in6_addr target; + struct ovs_nd_lla_opt options[0]; +}; +BUILD_ASSERT_DECL(ND_MSG_LEN == sizeof(struct ovs_nd_msg)); + +/* Neighbor Discovery packet flags. */ +#define ND_RSO_ROUTER 0x80000000 +#define ND_RSO_SOLICITED 0x40000000 +#define ND_RSO_OVERRIDE 0x20000000 + +#define RA_MSG_LEN 16 +struct ovs_ra_msg { + struct icmp6_header icmph; + uint8_t cur_hop_limit; + uint8_t mo_flags; /* ND_RA_MANAGED_ADDRESS and ND_RA_OTHER_CONFIG flags. */ + ovs_be16 router_lifetime; + ovs_be32 reachable_time; + ovs_be32 retrans_timer; + struct ovs_nd_lla_opt options[0]; +}; +BUILD_ASSERT_DECL(RA_MSG_LEN == sizeof(struct ovs_ra_msg)); + +#define ND_RA_MANAGED_ADDRESS 0x80 +#define ND_RA_OTHER_CONFIG 0x40 + +/* Defaults based on MaxRtrInterval and MinRtrInterval from RFC 4861 section + * 6.2.1 + */ +#define ND_RA_MAX_INTERVAL_DEFAULT 600 + +static inline int +nd_ra_min_interval_default(int max) +{ + return max >= 9 ? max / 3 : max * 3 / 4; +} + +/* + * Use the same struct for MLD and MLD2, naming members as the defined fields in + * in the corresponding version of the protocol, though they are reserved in the + * other one. + */ +#define MLD_HEADER_LEN 8 +struct mld_header { + uint8_t type; + uint8_t code; + ovs_be16 csum; + ovs_be16 mrd; + ovs_be16 ngrp; +}; +BUILD_ASSERT_DECL(MLD_HEADER_LEN == sizeof(struct mld_header)); + +#define MLD2_RECORD_LEN 20 +struct mld2_record { + uint8_t type; + uint8_t aux_len; + ovs_be16 nsrcs; + union ovs_16aligned_in6_addr maddr; +}; +BUILD_ASSERT_DECL(MLD2_RECORD_LEN == sizeof(struct mld2_record)); + +#define MLD_QUERY 130 +#define MLD_REPORT 131 +#define MLD_DONE 132 +#define MLD2_REPORT 143 + +/* The IPv6 flow label is in the lower 20 bits of the first 32-bit word. */ +#define IPV6_LABEL_MASK 0x000fffff + +/* Example: + * + * char *string = "1 ::1 2"; + * char ipv6_s[IPV6_SCAN_LEN + 1]; + * struct in6_addr ipv6; + * + * if (ovs_scan(string, "%d"IPV6_SCAN_FMT"%d", &a, ipv6_s, &b) + * && inet_pton(AF_INET6, ipv6_s, &ipv6) == 1) { + * ... + * } + */ +#define IPV6_SCAN_FMT "%46[0123456789abcdefABCDEF:.]" +#define IPV6_SCAN_LEN 46 + +extern const struct in6_addr in6addr_exact; +#define IN6ADDR_EXACT_INIT { { { 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, \ + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff } } } + +extern const struct in6_addr in6addr_all_hosts; +#define IN6ADDR_ALL_HOSTS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01 } } } + +extern const struct in6_addr in6addr_all_routers; +#define IN6ADDR_ALL_ROUTERS_INIT { { { 0xff,0x02,0x00,0x00,0x00,0x00,0x00,0x00, \ + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02 } } } + +static inline bool ipv6_addr_equals(const struct in6_addr *a, + const struct in6_addr *b) +{ +#ifdef IN6_ARE_ADDR_EQUAL + return IN6_ARE_ADDR_EQUAL(a, b); +#else + return !memcmp(a, b, sizeof(*a)); +#endif +} + +/* Checks the IPv6 address in 'mask' for all zeroes. */ +static inline bool ipv6_mask_is_any(const struct in6_addr *mask) { + return ipv6_addr_equals(mask, &in6addr_any); +} + +static inline bool ipv6_mask_is_exact(const struct in6_addr *mask) { + return ipv6_addr_equals(mask, &in6addr_exact); +} + +static inline bool ipv6_is_all_hosts(const struct in6_addr *addr) { + return ipv6_addr_equals(addr, &in6addr_all_hosts); +} + +static inline bool ipv6_addr_is_set(const struct in6_addr *addr) { + return !ipv6_addr_equals(addr, &in6addr_any); +} + +static inline bool ipv6_addr_is_multicast(const struct in6_addr *ip) { + return ip->s6_addr[0] == 0xff; +} + +static inline struct in6_addr +in6_addr_mapped_ipv4(ovs_be32 ip4) +{ + struct in6_addr ip6; + memset(&ip6, 0, sizeof(ip6)); + ip6.s6_addr[10] = 0xff, ip6.s6_addr[11] = 0xff; + memcpy(&ip6.s6_addr[12], &ip4, 4); + return ip6; +} + +static inline void +in6_addr_set_mapped_ipv4(struct in6_addr *ip6, ovs_be32 ip4) +{ + *ip6 = in6_addr_mapped_ipv4(ip4); +} + +static inline ovs_be32 +in6_addr_get_mapped_ipv4(const struct in6_addr *addr) +{ + union ovs_16aligned_in6_addr *taddr = + (union ovs_16aligned_in6_addr *) addr; + if (IN6_IS_ADDR_V4MAPPED(addr)) { + return get_16aligned_be32(&taddr->be32[3]); + } else { + return INADDR_ANY; + } +} + +void in6_addr_solicited_node(struct in6_addr *addr, + const struct in6_addr *ip6); + +void in6_generate_eui64(struct eth_addr ea, const struct in6_addr *prefix, + struct in6_addr *lla); + +void in6_generate_lla(struct eth_addr ea, struct in6_addr *lla); + +/* Returns true if 'addr' is a link local address. Otherwise, false. */ +bool in6_is_lla(struct in6_addr *addr); + +void ipv6_multicast_to_ethernet(struct eth_addr *eth, + const struct in6_addr *ip6); + +static inline bool dl_type_is_ip_any(ovs_be16 dl_type) +{ + return dl_type == htons(ETH_TYPE_IP) + || dl_type == htons(ETH_TYPE_IPV6); +} + +/* Tunnel header */ + +/* GRE protocol header */ +struct gre_base_hdr { + ovs_be16 flags; + ovs_be16 protocol; +}; + +#define GRE_CSUM 0x8000 +#define GRE_ROUTING 0x4000 +#define GRE_KEY 0x2000 +#define GRE_SEQ 0x1000 +#define GRE_STRICT 0x0800 +#define GRE_REC 0x0700 +#define GRE_FLAGS 0x00F8 +#define GRE_VERSION 0x0007 + +/* + * ERSPAN protocol header and metadata + * + * Version 1 (Type II) header (8 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS | En|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Reserved | Index | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * + * ERSPAN Version 2 (Type III) header (12 octets [42:49]) + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver | VLAN | COS |BSO|T| Session ID | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Timestamp | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | SGT |P| FT | Hw ID |D|Gra|O| + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + */ + +/* ERSPAN has fixed 8-byte GRE header */ +#define ERSPAN_GREHDR_LEN 8 +#define ERSPAN_HDR(gre_base_hdr) \ + ((struct erspan_base_hdr *)((char *)gre_base_hdr + ERSPAN_GREHDR_LEN)) + +#define ERSPAN_V1_MDSIZE 4 +#define ERSPAN_V2_MDSIZE 8 + +#define ERSPAN_SID_MASK 0x03ff /* 10-bit Session ID. */ +#define ERSPAN_IDX_MASK 0xfffff /* v1 Index */ +#define ERSPAN_HWID_MASK 0x03f0 +#define ERSPAN_DIR_MASK 0x0008 + +struct erspan_base_hdr { +#ifdef WORDS_BIGENDIAN + uint8_t ver:4, + vlan_upper:4; + uint8_t vlan:8; + uint8_t cos:3, + en:2, + t:1, + session_id_upper:2; + uint8_t session_id:8; +#else + uint8_t vlan_upper:4, + ver:4; + uint8_t vlan:8; + uint8_t session_id_upper:2, + t:1, + en:2, + cos:3; + uint8_t session_id:8; +#endif +}; + +struct erspan_md2 { + ovs_16aligned_be32 timestamp; + ovs_be16 sgt; +#ifdef WORDS_BIGENDIAN + uint8_t p:1, + ft:5, + hwid_upper:2; + uint8_t hwid:4, + dir:1, + gra:2, + o:1; +#else + uint8_t hwid_upper:2, + ft:5, + p:1; + uint8_t o:1, + gra:2, + dir:1, + hwid:4; +#endif +}; + +struct erspan_metadata { + int version; + union { + ovs_be32 index; /* Version 1 (type II)*/ + struct erspan_md2 md2; /* Version 2 (type III) */ + } u; +}; + +static inline uint16_t get_sid(const struct erspan_base_hdr *ershdr) +{ + return (ershdr->session_id_upper << 8) + ershdr->session_id; +} + +static inline void set_sid(struct erspan_base_hdr *ershdr, uint16_t id) +{ + ershdr->session_id = id & 0xff; + ershdr->session_id_upper = (id >> 8) &0x3; +} + +static inline uint8_t get_hwid(const struct erspan_md2 *md2) +{ + return (md2->hwid_upper << 4) + md2->hwid; +} + +static inline void set_hwid(struct erspan_md2 *md2, uint8_t hwid) +{ + md2->hwid = hwid & 0xf; + md2->hwid_upper = (hwid >> 4) & 0x3; +} + +/* ERSPAN timestamp granularity + * 00b --> granularity = 100 microseconds + * 01b --> granularity = 100 nanoseconds + * 10b --> granularity = IEEE 1588 + * Here we only support 100 microseconds. + */ +enum erspan_ts_gra { + ERSPAN_100US, + ERSPAN_100NS, + ERSPAN_IEEE1588, +}; + +static inline ovs_be32 get_erspan_ts(enum erspan_ts_gra gra) +{ + ovs_be32 ts = 0; + + switch (gra) { + case ERSPAN_100US: + ts = htonl((uint32_t)(time_wall_usec() / 100)); + break; + case ERSPAN_100NS: + /* fall back */ + case ERSPAN_IEEE1588: + /* fall back */ + default: + OVS_NOT_REACHED(); + break; + } + return ts; +} + +/* + * GTP-U protocol header and metadata + * See: + * User Plane Protocol and Architectural Analysis on 3GPP 5G System + * draft-hmm-dmm-5g-uplane-analysis-00 + * + * 0 1 2 3 + * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Ver |P|R|E|S|N| Message Type| Length | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Tunnel Endpoint Identifier | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | Sequence Number | N-PDU Number | Next-Ext-Hdr | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * GTP-U Flags: + * P: Protocol Type (Set to '1') + * R: Reserved Bit (Set to '0') + * E: Extension Header Flag (Set to '1' if extension header exists) + * S: Sequence Number Flag (Set to '1' if sequence number exists) + * N: N-PDU Number Flag (Set to '1' if N-PDU number exists) + * + * GTP-U Message Type: + * Indicates the type of GTP-U message. + * + * GTP-U Length: + * Indicates the length in octets of the payload. + * + * User payload is transmitted in G-PDU packets. + */ + +#define GTPU_VER_MASK 0xe0 +#define GTPU_P_MASK 0x10 +#define GTPU_E_MASK 0x04 +#define GTPU_S_MASK 0x02 + +/* GTP-U UDP port. */ +#define GTPU_DST_PORT 2152 + +/* Default GTP-U flags: Ver = 1 and P = 1. */ +#define GTPU_FLAGS_DEFAULT 0x30 + +/* GTP-U message type for normal user plane PDU. */ +#define GTPU_MSGTYPE_REQ 1 /* Echo Request. */ +#define GTPU_MSGTYPE_REPL 2 /* Echo Reply. */ +#define GTPU_MSGTYPE_GPDU 255 /* User Payload. */ + +struct gtpu_metadata { + uint8_t flags; + uint8_t msgtype; +}; +BUILD_ASSERT_DECL(sizeof(struct gtpu_metadata) == 2); + +struct gtpuhdr { + struct gtpu_metadata md; + ovs_be16 len; + ovs_16aligned_be32 teid; +}; +BUILD_ASSERT_DECL(sizeof(struct gtpuhdr) == 8); + +struct gtpuhdr_opt { + ovs_be16 seqno; + uint8_t pdu_number; + uint8_t next_ext_type; +}; +BUILD_ASSERT_DECL(sizeof(struct gtpuhdr_opt) == 4); + +/* VXLAN protocol header */ +struct vxlanhdr { + union { + ovs_16aligned_be32 vx_flags; /* VXLAN flags. */ + struct { + uint8_t flags; /* VXLAN GPE flags. */ + uint8_t reserved[2]; /* 16 bits reserved. */ + uint8_t next_protocol; /* Next Protocol field for VXLAN GPE. */ + } vx_gpe; + }; + ovs_16aligned_be32 vx_vni; +}; +BUILD_ASSERT_DECL(sizeof(struct vxlanhdr) == 8); + +#define VXLAN_FLAGS 0x08000000 /* struct vxlanhdr.vx_flags required value. */ + +/* + * VXLAN Generic Protocol Extension (VXLAN_F_GPE): + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * |R|R|Ver|I|P|R|O| Reserved |Next Protocol | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * | VXLAN Network Identifier (VNI) | Reserved | + * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + * + * Ver = Version. Indicates VXLAN GPE protocol version. + * + * P = Next Protocol Bit. The P bit is set to indicate that the + * Next Protocol field is present. + * + * O = OAM Flag Bit. The O bit is set to indicate that the packet + * is an OAM packet. + * + * Next Protocol = This 8 bit field indicates the protocol header + * immediately following the VXLAN GPE header. + * + * https://tools.ietf.org/html/draft-ietf-nvo3-vxlan-gpe-01 + */ + +/* Fields in struct vxlanhdr.vx_gpe.flags */ +#define VXLAN_GPE_FLAGS_VER 0x30 /* Version. */ +#define VXLAN_GPE_FLAGS_P 0x04 /* Next Protocol Bit. */ +#define VXLAN_GPE_FLAGS_O 0x01 /* OAM Bit. */ + +/* VXLAN-GPE header flags. */ +#define VXLAN_HF_VER ((1U <<29) | (1U <<28)) +#define VXLAN_HF_NP (1U <<26) +#define VXLAN_HF_OAM (1U <<24) + +#define VXLAN_GPE_USED_BITS (VXLAN_HF_VER | VXLAN_HF_NP | VXLAN_HF_OAM | \ + 0xff) + +/* VXLAN-GPE header Next Protocol. */ +#define VXLAN_GPE_NP_IPV4 0x01 +#define VXLAN_GPE_NP_IPV6 0x02 +#define VXLAN_GPE_NP_ETHERNET 0x03 +#define VXLAN_GPE_NP_NSH 0x04 + +#define VXLAN_F_GPE 0x4000 +#define VXLAN_HF_GPE 0x04000000 + +/* Input values for PACKET_TYPE macros have to be in host byte order. + * The _BE postfix indicates result is in network byte order. Otherwise result + * is in host byte order. */ +#define PACKET_TYPE(NS, NS_TYPE) ((uint32_t) ((NS) << 16 | (NS_TYPE))) +#define PACKET_TYPE_BE(NS, NS_TYPE) (htonl((NS) << 16 | (NS_TYPE))) + +/* Returns the host byte ordered namespace of 'packet type'. */ +static inline uint16_t +pt_ns(ovs_be32 packet_type) +{ + return ntohl(packet_type) >> 16; +} + +/* Returns the network byte ordered namespace type of 'packet type'. */ +static inline ovs_be16 +pt_ns_type_be(ovs_be32 packet_type) +{ + return be32_to_be16(packet_type); +} + +/* Returns the host byte ordered namespace type of 'packet type'. */ +static inline uint16_t +pt_ns_type(ovs_be32 packet_type) +{ + return ntohs(pt_ns_type_be(packet_type)); +} + +/* Well-known packet_type field values. */ +enum packet_type { + PT_ETH = PACKET_TYPE(OFPHTN_ONF, 0x0000), /* Default PT: Ethernet */ + PT_USE_NEXT_PROTO = PACKET_TYPE(OFPHTN_ONF, 0xfffe), /* Pseudo PT for decap. */ + PT_IPV4 = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_IP), + PT_IPV6 = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_IPV6), + PT_MPLS = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS), + PT_MPLS_MC = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_MPLS_MCAST), + PT_NSH = PACKET_TYPE(OFPHTN_ETHERTYPE, ETH_TYPE_NSH), + PT_UNKNOWN = PACKET_TYPE(0xffff, 0xffff), /* Unknown packet type. */ +}; + + +void ipv6_format_addr(const struct in6_addr *addr, struct ds *); +void ipv6_format_addr_bracket(const struct in6_addr *addr, struct ds *, + bool bracket); +void ipv6_format_mapped(const struct in6_addr *addr, struct ds *); +void ipv6_format_masked(const struct in6_addr *addr, + const struct in6_addr *mask, struct ds *); +const char * ipv6_string_mapped(char *addr_str, const struct in6_addr *addr); +struct in6_addr ipv6_addr_bitand(const struct in6_addr *src, + const struct in6_addr *mask); +struct in6_addr ipv6_addr_bitxor(const struct in6_addr *a, + const struct in6_addr *b); +bool ipv6_is_zero(const struct in6_addr *a); +struct in6_addr ipv6_create_mask(int mask); +int ipv6_count_cidr_bits(const struct in6_addr *netmask); +bool ipv6_is_cidr(const struct in6_addr *netmask); + +bool ipv6_parse(const char *s, struct in6_addr *ip); +char *ipv6_parse_masked(const char *s, struct in6_addr *ipv6, + struct in6_addr *mask); +char *ipv6_parse_cidr(const char *s, struct in6_addr *ip, unsigned int *plen) + OVS_WARN_UNUSED_RESULT; +char *ipv6_parse_masked_len(const char *s, int *n, struct in6_addr *ipv6, + struct in6_addr *mask); +char *ipv6_parse_cidr_len(const char *s, int *n, struct in6_addr *ip, + unsigned int *plen) + OVS_WARN_UNUSED_RESULT; + +void *eth_compose(struct dp_packet *, const struct eth_addr eth_dst, + const struct eth_addr eth_src, uint16_t eth_type, + size_t size); +void *snap_compose(struct dp_packet *, const struct eth_addr eth_dst, + const struct eth_addr eth_src, + unsigned int oui, uint16_t snap_type, size_t size); +void packet_set_ipv4(struct dp_packet *, ovs_be32 src, ovs_be32 dst, uint8_t tos, + uint8_t ttl); +void packet_set_ipv4_addr(struct dp_packet *packet, ovs_16aligned_be32 *addr, + ovs_be32 new_addr); +void packet_set_ipv6(struct dp_packet *, const struct in6_addr *src, + const struct in6_addr *dst, uint8_t tc, + ovs_be32 fl, uint8_t hlmit); +void packet_set_ipv6_addr(struct dp_packet *packet, uint8_t proto, + ovs_16aligned_be32 addr[4], + const struct in6_addr *new_addr, + bool recalculate_csum); +void packet_set_tcp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); +void packet_set_udp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); +void packet_set_sctp_port(struct dp_packet *, ovs_be16 src, ovs_be16 dst); +void packet_set_icmp(struct dp_packet *, uint8_t type, uint8_t code); +void packet_set_nd(struct dp_packet *, const struct in6_addr *target, + const struct eth_addr sll, const struct eth_addr tll); +void packet_set_nd_ext(struct dp_packet *packet, + const ovs_16aligned_be32 rso_flags, + const uint8_t opt_type); +void packet_set_igmp3_query(struct dp_packet *, uint8_t max_resp, + ovs_be32 group, bool srs, uint8_t qrv, + uint8_t qqic); +void packet_format_tcp_flags(struct ds *, uint16_t); +const char *packet_tcp_flag_to_string(uint32_t flag); +void *compose_ipv6(struct dp_packet *packet, uint8_t proto, + const struct in6_addr *src, const struct in6_addr *dst, + uint8_t key_tc, ovs_be32 key_fl, uint8_t key_hl, int size); +void compose_arp__(struct dp_packet *); +void compose_arp(struct dp_packet *, uint16_t arp_op, + const struct eth_addr arp_sha, + const struct eth_addr arp_tha, bool broadcast, + ovs_be32 arp_spa, ovs_be32 arp_tpa); +void compose_nd_ns(struct dp_packet *, const struct eth_addr eth_src, + const struct in6_addr *ipv6_src, + const struct in6_addr *ipv6_dst); +void compose_nd_na(struct dp_packet *, const struct eth_addr eth_src, + const struct eth_addr eth_dst, + const struct in6_addr *ipv6_src, + const struct in6_addr *ipv6_dst, + ovs_be32 rso_flags); +void compose_nd_ra(struct dp_packet *, + const struct eth_addr eth_src, + const struct eth_addr eth_dst, + const struct in6_addr *ipv6_src, + const struct in6_addr *ipv6_dst, + uint8_t cur_hop_limit, uint8_t mo_flags, + ovs_be16 router_lt, ovs_be32 reachable_time, + ovs_be32 retrans_timer, uint32_t mtu); +void packet_put_ra_prefix_opt(struct dp_packet *, + uint8_t plen, uint8_t la_flags, + ovs_be32 valid_lifetime, + ovs_be32 preferred_lifetime, + const ovs_be128 router_prefix); +uint32_t packet_csum_pseudoheader(const struct ip_header *); +void IP_ECN_set_ce(struct dp_packet *pkt, bool is_ipv6); + +#define DNS_HEADER_LEN 12 +struct dns_header { + ovs_be16 id; + uint8_t lo_flag; /* QR (1), OPCODE (4), AA (1), TC (1) and RD (1) */ + uint8_t hi_flag; /* RA (1), Z (3) and RCODE (4) */ + ovs_be16 qdcount; /* Num of entries in the question section. */ + ovs_be16 ancount; /* Num of resource records in the answer section. */ + + /* Num of name server records in the authority record section. */ + ovs_be16 nscount; + + /* Num of resource records in the additional records section. */ + ovs_be16 arcount; +}; + +BUILD_ASSERT_DECL(DNS_HEADER_LEN == sizeof(struct dns_header)); + +#define DNS_QUERY_TYPE_A 0x01 +#define DNS_QUERY_TYPE_AAAA 0x1c +#define DNS_QUERY_TYPE_ANY 0xff + +#define DNS_CLASS_IN 0x01 +#define DNS_DEFAULT_RR_TTL 3600 + +#endif /* packets.h */ Index: openvswitch-2.17.2/lib/pvector.h =================================================================== --- openvswitch-2.17.2.orig/lib/pvector.h +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (c) 2014, 2016 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 PVECTOR_H -#define PVECTOR_H 1 - -#include -#include -#include -#include "ovs-rcu.h" -#include "util.h" - -/* Concurrent Priority Vector - * ========================== - * - * Concurrent priority vector holds non-NULL pointers to objects in a - * nondecreasing priority order and allows readers to traverse the vector - * without being concerned about writers modifying the vector as they are - * traversing it. - * - * Multiple elements of a given priority are allowed. - * - * The priority order is maintained as a linear vector of elements to allow - * for efficient memory prefetching. - * - * Concurrency is implemented with OVS RCU so that the readers can assume - * that once they have taken a pointer to the vector with - * pvector_cursor_init(), the 'size' member will not decrease, so that - * they can safely read 'size' entries from 'vector', and find that each - * entry has a valid, non-NULL 'ptr', and the vector is in order from highest - * to lowest 'priority'. The 'priority' values can change any time, but only - * so that the order of the entries does not change, so readers can use - * 'priority' values read at any time after acquisition of the vector pointer. - * - * Writers can concurrently add entries to the end of the vector, incrementing - * 'size', or update the 'priority' value of an entry, but only if that does - * not change the ordering of the entries. Writers will never change the 'ptr' - * values, or decrement the 'size' on a copy that readers have access to. - * - * Most modifications are internally staged at the 'temp' vector, from which - * they can be published at 'impl' by calling pvector_publish(). This saves - * unnecessary memory allocations when many changes are done back-to-back. - * 'temp' may contain NULL pointers and it may be in unsorted order. It is - * sorted before it is published at 'impl', which also removes the NULLs from - * the published vector. - * - * Since the vector is RCU protected, the entry destruction after removal must - * be RCU postponed. Also, if it happens before changes published with - * pvector_publish(), destruction must be double postponed, i.e., the second - * ovsrcu_postpone() call to destruct the entry should be called from the first - * RCU callback. This is required because readers could still obtain the - * unmodified vector until updated version is published. - */ - -struct pvector_entry { - int priority; - void *ptr; -}; - -struct pvector_impl { - atomic_size_t size; /* Number of entries in the vector. */ - size_t allocated; /* Number of allocated entries. */ - struct pvector_entry vector[]; -}; - -/* Concurrent priority vector. */ -struct pvector { - OVSRCU_TYPE(struct pvector_impl *) impl; - struct pvector_impl *temp; -}; - -/* Initialization. */ -void pvector_init(struct pvector *); -void pvector_destroy(struct pvector *); - -/* Insertion and deletion. These work on 'temp'. */ -void pvector_insert(struct pvector *, void *, int priority); -void pvector_change_priority(struct pvector *, void *, int priority); -void pvector_remove(struct pvector *, void *); - -/* Make the modified pvector available for iteration. */ -static inline void pvector_publish(struct pvector *); - -/* Count. These operate on the published pvector. */ -static inline size_t pvector_count(const struct pvector *); -static inline bool pvector_is_empty(const struct pvector *); - -/* Iteration. - * - * - * Thread-safety - * ============= - * - * Iteration is safe even in a pvector that is changing concurrently. - * Multiple writers must exclude each other via e.g., a mutex. - * - * Example - * ======= - * - * struct my_node { - * int data; - * }; - * - * struct my_node elem1, elem2, *iter; - * struct pvector my_pvector; - * - * pvector_init(&my_pvector); - * ...add data... - * pvector_insert(&my_pvector, &elem1, 1); - * pvector_insert(&my_pvector, &elem2, 2); - * ... - * PVECTOR_FOR_EACH (iter, &my_pvector) { - * ...operate on '*iter'... - * ...elem2 to be seen before elem1... - * } - * ... - * pvector_destroy(&my_pvector); - * - * There is no PVECTOR_FOR_EACH_SAFE variant as iteration is performed on RCU - * protected instance of the priority vector. Any concurrent modifications - * that would be disruptive for readers (such as deletions), will be performed - * on a new instance. To see any of the modifications, a new iteration loop - * has to be started. - * - * The PVECTOR_FOR_EACH_PRIORITY limits the iteration to entries with higher - * than or equal to the given priority and allows for object lookahead. - * - * The iteration loop must be completed without entering the OVS RCU quiescent - * period. That is, an old iteration loop must not be continued after any - * blocking IO (VLOG is non-blocking, so that is OK). - */ -struct pvector_cursor { - size_t size; /* Number of entries in the vector. */ - size_t entry_idx; /* Current index. */ - const struct pvector_entry *vector; -}; - -static inline struct pvector_cursor pvector_cursor_init(const struct pvector *, - size_t n_ahead, - size_t obj_size); -static inline void *pvector_cursor_next(struct pvector_cursor *, - int lowest_priority, - size_t n_ahead, size_t obj_size); -static inline void pvector_cursor_lookahead(const struct pvector_cursor *, - int n, size_t size); - -#define PVECTOR_FOR_EACH(PTR, PVECTOR) \ - for (struct pvector_cursor cursor__ = pvector_cursor_init(PVECTOR, 0, 0); \ - ((PTR) = pvector_cursor_next(&cursor__, INT_MIN, 0, 0)) != NULL; ) - -/* Loop while priority is higher than or equal to 'PRIORITY' and prefetch - * objects of size 'SZ' 'N' objects ahead from the current object. */ -#define PVECTOR_FOR_EACH_PRIORITY(PTR, PRIORITY, N, SZ, PVECTOR) \ - for (struct pvector_cursor cursor__ = pvector_cursor_init(PVECTOR, N, SZ); \ - ((PTR) = pvector_cursor_next(&cursor__, PRIORITY, N, SZ)) != NULL; ) - -#define PVECTOR_CURSOR_FOR_EACH(PTR, CURSOR, PVECTOR) \ - for (*(CURSOR) = pvector_cursor_init(PVECTOR, 0, 0); \ - ((PTR) = pvector_cursor_next(CURSOR, INT_MIN, 0, 0)) != NULL; ) - -#define PVECTOR_CURSOR_FOR_EACH_CONTINUE(PTR, CURSOR) \ - for (; ((PTR) = pvector_cursor_next(CURSOR, INT_MIN, 0, 0)) != NULL; ) - - -/* Inline implementations. */ - -static inline struct pvector_cursor -pvector_cursor_init(const struct pvector *pvec, - size_t n_ahead, size_t obj_size) -{ - const struct pvector_impl *impl; - struct pvector_cursor cursor; - size_t size; - - impl = ovsrcu_get(struct pvector_impl *, &pvec->impl); - - /* Use memory_order_acquire to ensure entry access can not be - * reordered to happen before size read. */ - atomic_read_explicit(&CONST_CAST(struct pvector_impl *, impl)->size, - &size, memory_order_acquire); - ovs_prefetch_range(impl->vector, size * sizeof impl->vector[0]); - - cursor.size = size; - cursor.vector = impl->vector; - cursor.entry_idx = -1; - - for (size_t i = 0; i < n_ahead; i++) { - /* Prefetch the first objects. */ - pvector_cursor_lookahead(&cursor, i, obj_size); - } - return cursor; -} - -static inline void *pvector_cursor_next(struct pvector_cursor *cursor, - int lowest_priority, - size_t n_ahead, size_t obj_size) -{ - if (++cursor->entry_idx < cursor->size && - cursor->vector[cursor->entry_idx].priority >= lowest_priority) { - if (n_ahead) { - pvector_cursor_lookahead(cursor, n_ahead, obj_size); - } - return cursor->vector[cursor->entry_idx].ptr; - } - return NULL; -} - -static inline void pvector_cursor_lookahead(const struct pvector_cursor *cursor, - int n, size_t size) -{ - if (cursor->entry_idx + n < cursor->size) { - ovs_prefetch_range(cursor->vector[cursor->entry_idx + n].ptr, size); - } -} - -static inline size_t pvector_count(const struct pvector *pvec) -{ - return ovsrcu_get(struct pvector_impl *, &pvec->impl)->size; -} - -static inline bool pvector_is_empty(const struct pvector *pvec) -{ - return pvector_count(pvec) == 0; -} - -void pvector_publish__(struct pvector *); - -/* Make the modified pvector available for iteration. */ -static inline void pvector_publish(struct pvector *pvec) -{ - if (pvec->temp) { - pvector_publish__(pvec); - } -} - -#endif /* pvector.h */ Index: openvswitch-2.17.2/include/internal/pvector.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/pvector.h @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2014, 2016 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 PVECTOR_H +#define PVECTOR_H 1 + +#include +#include +#include +#include "openvswitch/ovs-rcu.h" +#include "internal/util.h" + +/* Concurrent Priority Vector + * ========================== + * + * Concurrent priority vector holds non-NULL pointers to objects in a + * nondecreasing priority order and allows readers to traverse the vector + * without being concerned about writers modifying the vector as they are + * traversing it. + * + * Multiple elements of a given priority are allowed. + * + * The priority order is maintained as a linear vector of elements to allow + * for efficient memory prefetching. + * + * Concurrency is implemented with OVS RCU so that the readers can assume + * that once they have taken a pointer to the vector with + * pvector_cursor_init(), the 'size' member will not decrease, so that + * they can safely read 'size' entries from 'vector', and find that each + * entry has a valid, non-NULL 'ptr', and the vector is in order from highest + * to lowest 'priority'. The 'priority' values can change any time, but only + * so that the order of the entries does not change, so readers can use + * 'priority' values read at any time after acquisition of the vector pointer. + * + * Writers can concurrently add entries to the end of the vector, incrementing + * 'size', or update the 'priority' value of an entry, but only if that does + * not change the ordering of the entries. Writers will never change the 'ptr' + * values, or decrement the 'size' on a copy that readers have access to. + * + * Most modifications are internally staged at the 'temp' vector, from which + * they can be published at 'impl' by calling pvector_publish(). This saves + * unnecessary memory allocations when many changes are done back-to-back. + * 'temp' may contain NULL pointers and it may be in unsorted order. It is + * sorted before it is published at 'impl', which also removes the NULLs from + * the published vector. + * + * Since the vector is RCU protected, the entry destruction after removal must + * be RCU postponed. Also, if it happens before changes published with + * pvector_publish(), destruction must be double postponed, i.e., the second + * ovsrcu_postpone() call to destruct the entry should be called from the first + * RCU callback. This is required because readers could still obtain the + * unmodified vector until updated version is published. + */ + +struct pvector_entry { + int priority; + void *ptr; +}; + +struct pvector_impl { + atomic_size_t size; /* Number of entries in the vector. */ + size_t allocated; /* Number of allocated entries. */ + struct pvector_entry vector[]; +}; + +/* Concurrent priority vector. */ +struct pvector { + OVSRCU_TYPE(struct pvector_impl *) impl; + struct pvector_impl *temp; +}; + +/* Initialization. */ +void pvector_init(struct pvector *); +void pvector_destroy(struct pvector *); + +/* Insertion and deletion. These work on 'temp'. */ +void pvector_insert(struct pvector *, void *, int priority); +void pvector_change_priority(struct pvector *, void *, int priority); +void pvector_remove(struct pvector *, void *); + +/* Make the modified pvector available for iteration. */ +static inline void pvector_publish(struct pvector *); + +/* Count. These operate on the published pvector. */ +static inline size_t pvector_count(const struct pvector *); +static inline bool pvector_is_empty(const struct pvector *); + +/* Iteration. + * + * + * Thread-safety + * ============= + * + * Iteration is safe even in a pvector that is changing concurrently. + * Multiple writers must exclude each other via e.g., a mutex. + * + * Example + * ======= + * + * struct my_node { + * int data; + * }; + * + * struct my_node elem1, elem2, *iter; + * struct pvector my_pvector; + * + * pvector_init(&my_pvector); + * ...add data... + * pvector_insert(&my_pvector, &elem1, 1); + * pvector_insert(&my_pvector, &elem2, 2); + * ... + * PVECTOR_FOR_EACH (iter, &my_pvector) { + * ...operate on '*iter'... + * ...elem2 to be seen before elem1... + * } + * ... + * pvector_destroy(&my_pvector); + * + * There is no PVECTOR_FOR_EACH_SAFE variant as iteration is performed on RCU + * protected instance of the priority vector. Any concurrent modifications + * that would be disruptive for readers (such as deletions), will be performed + * on a new instance. To see any of the modifications, a new iteration loop + * has to be started. + * + * The PVECTOR_FOR_EACH_PRIORITY limits the iteration to entries with higher + * than or equal to the given priority and allows for object lookahead. + * + * The iteration loop must be completed without entering the OVS RCU quiescent + * period. That is, an old iteration loop must not be continued after any + * blocking IO (VLOG is non-blocking, so that is OK). + */ +struct pvector_cursor { + size_t size; /* Number of entries in the vector. */ + size_t entry_idx; /* Current index. */ + const struct pvector_entry *vector; +}; + +static inline struct pvector_cursor pvector_cursor_init(const struct pvector *, + size_t n_ahead, + size_t obj_size); +static inline void *pvector_cursor_next(struct pvector_cursor *, + int lowest_priority, + size_t n_ahead, size_t obj_size); +static inline void pvector_cursor_lookahead(const struct pvector_cursor *, + int n, size_t size); + +#define PVECTOR_FOR_EACH(PTR, PVECTOR) \ + for (struct pvector_cursor cursor__ = pvector_cursor_init(PVECTOR, 0, 0); \ + ((PTR) = pvector_cursor_next(&cursor__, INT_MIN, 0, 0)) != NULL; ) + +/* Loop while priority is higher than or equal to 'PRIORITY' and prefetch + * objects of size 'SZ' 'N' objects ahead from the current object. */ +#define PVECTOR_FOR_EACH_PRIORITY(PTR, PRIORITY, N, SZ, PVECTOR) \ + for (struct pvector_cursor cursor__ = pvector_cursor_init(PVECTOR, N, SZ); \ + ((PTR) = pvector_cursor_next(&cursor__, PRIORITY, N, SZ)) != NULL; ) + +#define PVECTOR_CURSOR_FOR_EACH(PTR, CURSOR, PVECTOR) \ + for (*(CURSOR) = pvector_cursor_init(PVECTOR, 0, 0); \ + ((PTR) = pvector_cursor_next(CURSOR, INT_MIN, 0, 0)) != NULL; ) + +#define PVECTOR_CURSOR_FOR_EACH_CONTINUE(PTR, CURSOR) \ + for (; ((PTR) = pvector_cursor_next(CURSOR, INT_MIN, 0, 0)) != NULL; ) + + +/* Inline implementations. */ + +static inline struct pvector_cursor +pvector_cursor_init(const struct pvector *pvec, + size_t n_ahead, size_t obj_size) +{ + const struct pvector_impl *impl; + struct pvector_cursor cursor; + size_t size; + + impl = ovsrcu_get(struct pvector_impl *, &pvec->impl); + + /* Use memory_order_acquire to ensure entry access can not be + * reordered to happen before size read. */ + atomic_read_explicit(&CONST_CAST(struct pvector_impl *, impl)->size, + &size, memory_order_acquire); + ovs_prefetch_range(impl->vector, size * sizeof impl->vector[0]); + + cursor.size = size; + cursor.vector = impl->vector; + cursor.entry_idx = -1; + + for (size_t i = 0; i < n_ahead; i++) { + /* Prefetch the first objects. */ + pvector_cursor_lookahead(&cursor, i, obj_size); + } + return cursor; +} + +static inline void *pvector_cursor_next(struct pvector_cursor *cursor, + int lowest_priority, + size_t n_ahead, size_t obj_size) +{ + if (++cursor->entry_idx < cursor->size && + cursor->vector[cursor->entry_idx].priority >= lowest_priority) { + if (n_ahead) { + pvector_cursor_lookahead(cursor, n_ahead, obj_size); + } + return cursor->vector[cursor->entry_idx].ptr; + } + return NULL; +} + +static inline void pvector_cursor_lookahead(const struct pvector_cursor *cursor, + int n, size_t size) +{ + if (cursor->entry_idx + n < cursor->size) { + ovs_prefetch_range(cursor->vector[cursor->entry_idx + n].ptr, size); + } +} + +static inline size_t pvector_count(const struct pvector *pvec) +{ + return ovsrcu_get(struct pvector_impl *, &pvec->impl)->size; +} + +static inline bool pvector_is_empty(const struct pvector *pvec) +{ + return pvector_count(pvec) == 0; +} + +void pvector_publish__(struct pvector *); + +/* Make the modified pvector available for iteration. */ +static inline void pvector_publish(struct pvector *pvec) +{ + if (pvec->temp) { + pvector_publish__(pvec); + } +} + +#endif /* pvector.h */ Index: openvswitch-2.17.2/lib/rculist.h =================================================================== --- openvswitch-2.17.2.orig/lib/rculist.h +++ /dev/null @@ -1,421 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef RCULIST_H -#define RCULIST_H 1 - -/* A single writer multiple RCU-reader doubly linked list. - * - * RCU readers may iterate over the list at the same time as a writer is - * modifying the list. Multiple writers can be supported by use of mutual - * exclusion, but rculist does not provide that, as the user of rculist - * typically does that already. - * - * To be RCU-friendly, the struct rculist instances must be freed via - * ovsrcu_postpone(). - * - * The API is almost the same as for struct ovs_list, with the following - * exceptions: - * - * - The 'prev' pointer may not be accessed by the user. - * - The 'next' pointer should be accessed via rculist_next() by readers, and - * rculist_next_protected() by the writer. - * - No rculist_moved(): due to the memory management limitation stated above, - * rculist instances may not be reallocated, as realloc may instantly free - * the old memory. - * - rculist_front() returns a const pointer to accommodate for an RCU reader. - * - rculist_splice_hidden(): Spliced elements may not have been visible to - * RCU readers before the operation. - * - rculist_poison(): Only poisons the 'prev' pointer. - * - * The following functions are variations of the struct ovs_list functions with - * similar names, but are now restricted to the writer use: - * - * - rculist_back_protected() - * - rculist_is_short_protected() - * - rculist_is_singleton_protected() - */ - -#include -#include -#include "ovs-rcu.h" -#include "util.h" - -/* A non-existing mutex to make it more difficult for an user to accidentally - * keep using the 'prev' pointer. This may be helpful when porting code from - * struct ovs_list to rculist. */ -extern struct ovs_mutex rculist_fake_mutex; - -/* Doubly linked list head or element. */ -struct rculist { - /* Previous list element. */ - struct rculist *prev OVS_GUARDED_BY(rculist_fake_mutex); - - /* Next list element. */ - OVSRCU_TYPE(struct rculist *) next; -}; - -/* Easier access to 'next' member. */ -static inline const struct rculist *rculist_next(const struct rculist *); -static inline struct rculist *rculist_next_protected(const struct rculist *); - -/* List initialization. */ -#define RCUOVS_LIST_INITIALIZER(LIST) { LIST, OVSRCU_INITIALIZER(LIST) } - -static inline void rculist_init(struct rculist *list); -static inline void rculist_poison(struct rculist *elem); - -/* List insertion. */ -static inline void rculist_insert(struct rculist *list, struct rculist *elem); -static inline void rculist_splice_hidden(struct rculist *before, - struct rculist *first, - struct rculist *last); -static inline void rculist_push_front(struct rculist *list, - struct rculist *elem); -static inline void rculist_push_back(struct rculist *list, - struct rculist *elem); -static inline void rculist_replace(struct rculist *replacement, - struct rculist *replaced); -static inline void rculist_move(struct rculist *dst, struct rculist *src); - -/* List removal. */ -static inline struct rculist *rculist_remove(struct rculist *elem); -static inline struct rculist *rculist_pop_front(struct rculist *list); -static inline struct rculist *rculist_pop_back(struct rculist *list); - -/* List elements. */ -static inline const struct rculist *rculist_front(const struct rculist *); -static inline struct rculist *rculist_back_protected(const struct rculist *); - -/* List properties. */ -static inline size_t rculist_size(const struct rculist *); -static inline bool rculist_is_empty(const struct rculist *); -static inline bool rculist_is_singleton_protected(const struct rculist *); -static inline bool rculist_is_short_protected(const struct rculist *); - - -/* Inline implementations. */ - -static inline const struct rculist * -rculist_next(const struct rculist *list) -{ - return ovsrcu_get(struct rculist *, &list->next); -} - -static inline struct rculist * -rculist_next_protected(const struct rculist *list) - -{ - return ovsrcu_get_protected(struct rculist *, &list->next); -} - -static inline void -rculist_init(struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - list->prev = list; - ovsrcu_init(&list->next, list); -} - -#define RCULIST_POISON (struct rculist *)(UINTPTR_MAX / 0xf * 0xc) - -/* Initializes 'list' with pointers that will (probably) cause segfaults if - * dereferenced and, better yet, show up clearly in a debugger. */ -static inline void -rculist_poison(struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - list->prev = RCULIST_POISON; -} - -/* Initializes 'list' with pointers that will (probably) cause segfaults if - * dereferenced and, better yet, show up clearly in a debugger. - * - * This variant poisons also the next pointer, so this may not be called if - * this list element is still visible to RCU readers. */ -static inline void -rculist_poison__(struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - rculist_poison(list); - ovsrcu_set_hidden(&list->next, RCULIST_POISON); -} - -/* rculist insertion. */ -static inline void -rculist_insert(struct rculist *before, struct rculist *elem) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - elem->prev = before->prev; - ovsrcu_set_hidden(&elem->next, before); - ovsrcu_set(&before->prev->next, elem); - before->prev = elem; -} - -/* Removes elements 'first' though 'last' (exclusive) from their current list, - * which may NOT be visible to any other threads (== be hidden from them), - * then inserts them just before 'before'. */ -static inline void -rculist_splice_hidden(struct rculist *before, struct rculist *first, - struct rculist *last) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - struct rculist *last_next; - - if (first == last) { - return; - } - last = last->prev; - - /* Cleanly remove 'first'...'last' from its current list. */ - last_next = rculist_next_protected(last); - last_next->prev = first->prev; - ovsrcu_set_hidden(&first->prev->next, last_next); - - /* Splice 'first'...'last' into new list. */ - first->prev = before->prev; - ovsrcu_set(&last->next, before); - ovsrcu_set(&before->prev->next, first); - before->prev = last; -} - -/* Inserts 'elem' at the beginning of 'list', so that it becomes the front in - * 'list'. */ -static inline void -rculist_push_front(struct rculist *list, struct rculist *elem) -{ - rculist_insert(rculist_next_protected(list), elem); -} - -/* Inserts 'elem' at the end of 'list', so that it becomes the back in - * 'list'. */ -static inline void -rculist_push_back(struct rculist *list, struct rculist *elem) -{ - rculist_insert(list, elem); -} - -/* Puts 'element' in the position currently occupied by 'position'. - * - * Afterward, 'position' is not linked to from the list any more, but still - * links to the nodes in the list, and may still be referenced by other threads - * until all other threads quiesce. The replaced node ('position') may not be - * re-inserted, re-initialized, or deleted until after all other threads have - * quiesced (use ovsrcu_postpone). */ -static inline void -rculist_replace(struct rculist *element, struct rculist *position) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - struct rculist *position_next = rculist_next_protected(position); - - ovsrcu_set_hidden(&element->next, position_next); - position_next->prev = element; - element->prev = position->prev; - ovsrcu_set(&element->prev->next, element); - rculist_poison(position); -} - -/* Initializes 'dst' with the contents of 'src', compensating for moving it - * around in memory. The effect is that, if 'src' was the head of a list, now - * 'dst' is the head of a list containing the same elements. - * - * Memory for 'src' must be kept around until the next RCU quiescent period. - * rculist cannot be simply reallocated, so there is no rculist_moved(). */ -static inline void -rculist_move(struct rculist *dst, struct rculist *src) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - if (!rculist_is_empty(src)) { - struct rculist *src_next = rculist_next_protected(src); - - dst->prev = src->prev; - ovsrcu_set_hidden(&dst->next, src_next); - - src_next->prev = dst; - ovsrcu_set(&src->prev->next, dst); - } else { - rculist_init(dst); - } - rculist_poison(src); -} - -/* Removes 'elem' from its list and returns the element that followed it. - * Has no effect when 'elem' is initialized, but not in a list. - * Undefined behavior if 'elem' is not initialized. - * - * Afterward, 'elem' is not linked to from the list any more, but still links - * to the nodes in the list, and may still be referenced by other threads until - * all other threads quiesce. The removed node ('elem') may not be - * re-inserted, re-initialized, or deleted until after all other threads have - * quiesced (use ovsrcu_postpone). - */ -static inline struct rculist * -rculist_remove(struct rculist *elem) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - struct rculist *elem_next = rculist_next_protected(elem); - - elem_next->prev = elem->prev; - ovsrcu_set(&elem->prev->next, elem_next); - rculist_poison(elem); - return elem_next; -} - -/* Removes the front element from 'list' and returns it. Undefined behavior if - * 'list' is empty before removal. - * - * Afterward, teh returned former first node is not linked to from the list any - * more, but still links to the nodes in the list, and may still be referenced - * by other threads until all other threads quiesce. The returned node may not - * be re-inserted, re-initialized, or deleted until after all other threads - * have quiesced (use ovsrcu_postpone). */ -static inline struct rculist * -rculist_pop_front(struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - struct rculist *front = rculist_next_protected(list); - rculist_remove(front); - return front; -} - -/* Removes the back element from 'list' and returns it. - * Undefined behavior if 'list' is empty before removal. - * - * Afterward, teh returned former last node is not linked to from the list any - * more, but still links to the nodes in the list, and may still be referenced - * by other threads until all other threads quiesce. The returned node may not - * be re-inserted, re-initialized, or deleted until after all other threads - * have quiesced (use ovsrcu_postpone). */ -static inline struct rculist * -rculist_pop_back(struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - struct rculist *back = list->prev; - rculist_remove(back); - return back; -} - -/* Returns the front element in 'list_'. - * Undefined behavior if 'list_' is empty. */ -static inline const struct rculist * -rculist_front(const struct rculist *list) -{ - ovs_assert(!rculist_is_empty(list)); - - return rculist_next(list); -} - -/* Returns the back element in 'list_'. - * Returns the 'list_' itself, if 'list_' is empty. */ -static inline struct rculist * -rculist_back_protected(const struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - return CONST_CAST(struct rculist *, list)->prev; -} - -/* Returns the number of elements in 'list'. - * Runs in O(n) in the number of elements. */ -static inline size_t -rculist_size(const struct rculist *list) -{ - const struct rculist *e; - size_t cnt = 0; - - for (e = rculist_next(list); e != list; e = rculist_next(e)) { - cnt++; - } - return cnt; -} - -/* Returns true if 'list' is empty, false otherwise. */ -static inline bool -rculist_is_empty(const struct rculist *list) -{ - return rculist_next(list) == list; -} - -/* Returns true if 'list' has 0 or 1 elements, false otherwise. */ -static inline bool -rculist_is_short_protected(const struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - return rculist_next_protected(list) == list->prev; -} - -/* Returns true if 'list' has exactly 1 element, false otherwise. */ -static inline bool -rculist_is_singleton_protected(const struct rculist *list) - OVS_NO_THREAD_SAFETY_ANALYSIS -{ - const struct rculist *list_next = rculist_next_protected(list); - - return list_next == list->prev && list_next != list; -} - -#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST) \ - for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(RCULIST), \ - const struct rculist); \ - CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ - UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER)))) - -#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST) \ - for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(&(ITER)->MEMBER), \ - const struct rculist); \ - CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ - UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER)))) - -#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST) \ - for (INIT_MULTIVAR(ITER, MEMBER, (RCULIST)->prev, struct rculist); \ - CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ - UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev)) - -#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST) \ - for (INIT_MULTIVAR(ITER, MEMBER, (ITER)->MEMBER.prev, struct rculist); \ - CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ - UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev)) - -#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST) \ - for (INIT_MULTIVAR(ITER, MEMBER, rculist_next_protected(RCULIST), \ - struct rculist); \ - CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ - UPDATE_MULTIVAR(ITER, rculist_next_protected(ITER_VAR(ITER))) \ - -#define RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED(ITER, MEMBER, RCULIST) \ - for (INIT_MULTIVAR_SAFE_SHORT(ITER, MEMBER, \ - rculist_next_protected(RCULIST), \ - struct rculist); \ - CONDITION_MULTIVAR_SAFE_SHORT(ITER, MEMBER, \ - ITER_VAR(ITER) != (RCULIST), \ - ITER_NEXT_VAR(ITER) = rculist_next_protected(ITER_VAR(VAR))); \ - UPDATE_MULTIVAR_SHORT(ITER)) - -#define RCULIST_FOR_EACH_SAFE_LONG_PROTECTED(ITER, NEXT, MEMBER, RCULIST) \ - for (INIT_MULTIVAR_SAFE_LONG(ITER, NEXT, MEMBER, \ - rculist_next_protected(RCULIST) \ - struct rculist); \ - CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER \ - ITER_VAR(ITER) != (RCULIST), \ - ITER_VAR(NEXT) = rculist_next_protected(ITER_VAR(VAR)), \ - ITER_VAR(NEXT) != (RCULIST)); \ - UPDATE_MULTIVAR_LONG(ITER)) - -#define RCULIST_FOR_EACH_SAFE_PROTECTED(...) \ - OVERLOAD_SAFE_MACRO(RCULIST_FOR_EACH_SAFE_LONG_PROTECTED, \ - RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED, \ - 4, __VA_ARGS__) - - -#endif /* rculist.h */ Index: openvswitch-2.17.2/include/internal/rculist.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/rculist.h @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RCULIST_H +#define RCULIST_H 1 + +/* A single writer multiple RCU-reader doubly linked list. + * + * RCU readers may iterate over the list at the same time as a writer is + * modifying the list. Multiple writers can be supported by use of mutual + * exclusion, but rculist does not provide that, as the user of rculist + * typically does that already. + * + * To be RCU-friendly, the struct rculist instances must be freed via + * ovsrcu_postpone(). + * + * The API is almost the same as for struct ovs_list, with the following + * exceptions: + * + * - The 'prev' pointer may not be accessed by the user. + * - The 'next' pointer should be accessed via rculist_next() by readers, and + * rculist_next_protected() by the writer. + * - No rculist_moved(): due to the memory management limitation stated above, + * rculist instances may not be reallocated, as realloc may instantly free + * the old memory. + * - rculist_front() returns a const pointer to accommodate for an RCU reader. + * - rculist_splice_hidden(): Spliced elements may not have been visible to + * RCU readers before the operation. + * - rculist_poison(): Only poisons the 'prev' pointer. + * + * The following functions are variations of the struct ovs_list functions with + * similar names, but are now restricted to the writer use: + * + * - rculist_back_protected() + * - rculist_is_short_protected() + * - rculist_is_singleton_protected() + */ + +#include +#include +#include "openvswitch/ovs-rcu.h" +#include "internal/util.h" + +/* A non-existing mutex to make it more difficult for an user to accidentally + * keep using the 'prev' pointer. This may be helpful when porting code from + * struct ovs_list to rculist. */ +extern struct ovs_mutex rculist_fake_mutex; + +/* Doubly linked list head or element. */ +struct rculist { + /* Previous list element. */ + struct rculist *prev OVS_GUARDED_BY(rculist_fake_mutex); + + /* Next list element. */ + OVSRCU_TYPE(struct rculist *) next; +}; + +/* Easier access to 'next' member. */ +static inline const struct rculist *rculist_next(const struct rculist *); +static inline struct rculist *rculist_next_protected(const struct rculist *); + +/* List initialization. */ +#define RCUOVS_LIST_INITIALIZER(LIST) { LIST, OVSRCU_INITIALIZER(LIST) } + +static inline void rculist_init(struct rculist *list); +static inline void rculist_poison(struct rculist *elem); + +/* List insertion. */ +static inline void rculist_insert(struct rculist *list, struct rculist *elem); +static inline void rculist_splice_hidden(struct rculist *before, + struct rculist *first, + struct rculist *last); +static inline void rculist_push_front(struct rculist *list, + struct rculist *elem); +static inline void rculist_push_back(struct rculist *list, + struct rculist *elem); +static inline void rculist_replace(struct rculist *replacement, + struct rculist *replaced); +static inline void rculist_move(struct rculist *dst, struct rculist *src); + +/* List removal. */ +static inline struct rculist *rculist_remove(struct rculist *elem); +static inline struct rculist *rculist_pop_front(struct rculist *list); +static inline struct rculist *rculist_pop_back(struct rculist *list); + +/* List elements. */ +static inline const struct rculist *rculist_front(const struct rculist *); +static inline struct rculist *rculist_back_protected(const struct rculist *); + +/* List properties. */ +static inline size_t rculist_size(const struct rculist *); +static inline bool rculist_is_empty(const struct rculist *); +static inline bool rculist_is_singleton_protected(const struct rculist *); +static inline bool rculist_is_short_protected(const struct rculist *); + + +/* Inline implementations. */ + +static inline const struct rculist * +rculist_next(const struct rculist *list) +{ + return ovsrcu_get(struct rculist *, &list->next); +} + +static inline struct rculist * +rculist_next_protected(const struct rculist *list) + +{ + return ovsrcu_get_protected(struct rculist *, &list->next); +} + +static inline void +rculist_init(struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + list->prev = list; + ovsrcu_init(&list->next, list); +} + +#define RCULIST_POISON (struct rculist *)(UINTPTR_MAX / 0xf * 0xc) + +/* Initializes 'list' with pointers that will (probably) cause segfaults if + * dereferenced and, better yet, show up clearly in a debugger. */ +static inline void +rculist_poison(struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + list->prev = RCULIST_POISON; +} + +/* Initializes 'list' with pointers that will (probably) cause segfaults if + * dereferenced and, better yet, show up clearly in a debugger. + * + * This variant poisons also the next pointer, so this may not be called if + * this list element is still visible to RCU readers. */ +static inline void +rculist_poison__(struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + rculist_poison(list); + ovsrcu_set_hidden(&list->next, RCULIST_POISON); +} + +/* rculist insertion. */ +static inline void +rculist_insert(struct rculist *before, struct rculist *elem) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + elem->prev = before->prev; + ovsrcu_set_hidden(&elem->next, before); + ovsrcu_set(&before->prev->next, elem); + before->prev = elem; +} + +/* Removes elements 'first' though 'last' (exclusive) from their current list, + * which may NOT be visible to any other threads (== be hidden from them), + * then inserts them just before 'before'. */ +static inline void +rculist_splice_hidden(struct rculist *before, struct rculist *first, + struct rculist *last) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + struct rculist *last_next; + + if (first == last) { + return; + } + last = last->prev; + + /* Cleanly remove 'first'...'last' from its current list. */ + last_next = rculist_next_protected(last); + last_next->prev = first->prev; + ovsrcu_set_hidden(&first->prev->next, last_next); + + /* Splice 'first'...'last' into new list. */ + first->prev = before->prev; + ovsrcu_set(&last->next, before); + ovsrcu_set(&before->prev->next, first); + before->prev = last; +} + +/* Inserts 'elem' at the beginning of 'list', so that it becomes the front in + * 'list'. */ +static inline void +rculist_push_front(struct rculist *list, struct rculist *elem) +{ + rculist_insert(rculist_next_protected(list), elem); +} + +/* Inserts 'elem' at the end of 'list', so that it becomes the back in + * 'list'. */ +static inline void +rculist_push_back(struct rculist *list, struct rculist *elem) +{ + rculist_insert(list, elem); +} + +/* Puts 'element' in the position currently occupied by 'position'. + * + * Afterward, 'position' is not linked to from the list any more, but still + * links to the nodes in the list, and may still be referenced by other threads + * until all other threads quiesce. The replaced node ('position') may not be + * re-inserted, re-initialized, or deleted until after all other threads have + * quiesced (use ovsrcu_postpone). */ +static inline void +rculist_replace(struct rculist *element, struct rculist *position) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + struct rculist *position_next = rculist_next_protected(position); + + ovsrcu_set_hidden(&element->next, position_next); + position_next->prev = element; + element->prev = position->prev; + ovsrcu_set(&element->prev->next, element); + rculist_poison(position); +} + +/* Initializes 'dst' with the contents of 'src', compensating for moving it + * around in memory. The effect is that, if 'src' was the head of a list, now + * 'dst' is the head of a list containing the same elements. + * + * Memory for 'src' must be kept around until the next RCU quiescent period. + * rculist cannot be simply reallocated, so there is no rculist_moved(). */ +static inline void +rculist_move(struct rculist *dst, struct rculist *src) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + if (!rculist_is_empty(src)) { + struct rculist *src_next = rculist_next_protected(src); + + dst->prev = src->prev; + ovsrcu_set_hidden(&dst->next, src_next); + + src_next->prev = dst; + ovsrcu_set(&src->prev->next, dst); + } else { + rculist_init(dst); + } + rculist_poison(src); +} + +/* Removes 'elem' from its list and returns the element that followed it. + * Has no effect when 'elem' is initialized, but not in a list. + * Undefined behavior if 'elem' is not initialized. + * + * Afterward, 'elem' is not linked to from the list any more, but still links + * to the nodes in the list, and may still be referenced by other threads until + * all other threads quiesce. The removed node ('elem') may not be + * re-inserted, re-initialized, or deleted until after all other threads have + * quiesced (use ovsrcu_postpone). + */ +static inline struct rculist * +rculist_remove(struct rculist *elem) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + struct rculist *elem_next = rculist_next_protected(elem); + + elem_next->prev = elem->prev; + ovsrcu_set(&elem->prev->next, elem_next); + rculist_poison(elem); + return elem_next; +} + +/* Removes the front element from 'list' and returns it. Undefined behavior if + * 'list' is empty before removal. + * + * Afterward, teh returned former first node is not linked to from the list any + * more, but still links to the nodes in the list, and may still be referenced + * by other threads until all other threads quiesce. The returned node may not + * be re-inserted, re-initialized, or deleted until after all other threads + * have quiesced (use ovsrcu_postpone). */ +static inline struct rculist * +rculist_pop_front(struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + struct rculist *front = rculist_next_protected(list); + rculist_remove(front); + return front; +} + +/* Removes the back element from 'list' and returns it. + * Undefined behavior if 'list' is empty before removal. + * + * Afterward, teh returned former last node is not linked to from the list any + * more, but still links to the nodes in the list, and may still be referenced + * by other threads until all other threads quiesce. The returned node may not + * be re-inserted, re-initialized, or deleted until after all other threads + * have quiesced (use ovsrcu_postpone). */ +static inline struct rculist * +rculist_pop_back(struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + struct rculist *back = list->prev; + rculist_remove(back); + return back; +} + +/* Returns the front element in 'list_'. + * Undefined behavior if 'list_' is empty. */ +static inline const struct rculist * +rculist_front(const struct rculist *list) +{ + ovs_assert(!rculist_is_empty(list)); + + return rculist_next(list); +} + +/* Returns the back element in 'list_'. + * Returns the 'list_' itself, if 'list_' is empty. */ +static inline struct rculist * +rculist_back_protected(const struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + return CONST_CAST(struct rculist *, list)->prev; +} + +/* Returns the number of elements in 'list'. + * Runs in O(n) in the number of elements. */ +static inline size_t +rculist_size(const struct rculist *list) +{ + const struct rculist *e; + size_t cnt = 0; + + for (e = rculist_next(list); e != list; e = rculist_next(e)) { + cnt++; + } + return cnt; +} + +/* Returns true if 'list' is empty, false otherwise. */ +static inline bool +rculist_is_empty(const struct rculist *list) +{ + return rculist_next(list) == list; +} + +/* Returns true if 'list' has 0 or 1 elements, false otherwise. */ +static inline bool +rculist_is_short_protected(const struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + return rculist_next_protected(list) == list->prev; +} + +/* Returns true if 'list' has exactly 1 element, false otherwise. */ +static inline bool +rculist_is_singleton_protected(const struct rculist *list) + OVS_NO_THREAD_SAFETY_ANALYSIS +{ + const struct rculist *list_next = rculist_next_protected(list); + + return list_next == list->prev && list_next != list; +} + +#define RCULIST_FOR_EACH(ITER, MEMBER, RCULIST) \ + for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(RCULIST), \ + const struct rculist); \ + CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ + UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER)))) + +#define RCULIST_FOR_EACH_CONTINUE(ITER, MEMBER, RCULIST) \ + for (INIT_MULTIVAR(ITER, MEMBER, rculist_next(&(ITER)->MEMBER), \ + const struct rculist); \ + CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ + UPDATE_MULTIVAR(ITER, rculist_next(ITER_VAR(ITER)))) + +#define RCULIST_FOR_EACH_REVERSE_PROTECTED(ITER, MEMBER, RCULIST) \ + for (INIT_MULTIVAR(ITER, MEMBER, (RCULIST)->prev, struct rculist); \ + CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ + UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev)) + +#define RCULIST_FOR_EACH_REVERSE_PROTECTED_CONTINUE(ITER, MEMBER, RCULIST) \ + for (INIT_MULTIVAR(ITER, MEMBER, (ITER)->MEMBER.prev, struct rculist); \ + CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ + UPDATE_MULTIVAR(ITER, ITER_VAR(VAR).prev)) + +#define RCULIST_FOR_EACH_PROTECTED(ITER, MEMBER, RCULIST) \ + for (INIT_MULTIVAR(ITER, MEMBER, rculist_next_protected(RCULIST), \ + struct rculist); \ + CONDITION_MULTIVAR(ITER, MEMBER, ITER_VAR(ITER) != (RCULIST)); \ + UPDATE_MULTIVAR(ITER, rculist_next_protected(ITER_VAR(ITER))) \ + +#define RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED(ITER, MEMBER, RCULIST) \ + for (INIT_MULTIVAR_SAFE_SHORT(ITER, MEMBER, \ + rculist_next_protected(RCULIST), \ + struct rculist); \ + CONDITION_MULTIVAR_SAFE_SHORT(ITER, MEMBER, \ + ITER_VAR(ITER) != (RCULIST), \ + ITER_NEXT_VAR(ITER) = rculist_next_protected(ITER_VAR(VAR))); \ + UPDATE_MULTIVAR_SHORT(ITER)) + +#define RCULIST_FOR_EACH_SAFE_LONG_PROTECTED(ITER, NEXT, MEMBER, RCULIST) \ + for (INIT_MULTIVAR_SAFE_LONG(ITER, NEXT, MEMBER, \ + rculist_next_protected(RCULIST) \ + struct rculist); \ + CONDITION_MULTIVAR_SAFE_LONG(VAR, NEXT, MEMBER \ + ITER_VAR(ITER) != (RCULIST), \ + ITER_VAR(NEXT) = rculist_next_protected(ITER_VAR(VAR)), \ + ITER_VAR(NEXT) != (RCULIST)); \ + UPDATE_MULTIVAR_LONG(ITER)) + +#define RCULIST_FOR_EACH_SAFE_PROTECTED(...) \ + OVERLOAD_SAFE_MACRO(RCULIST_FOR_EACH_SAFE_LONG_PROTECTED, \ + RCULIST_FOR_EACH_SAFE_SHORT_PROTECTED, \ + 4, __VA_ARGS__) + + +#endif /* rculist.h */ Index: openvswitch-2.17.2/lib/seq.h =================================================================== --- openvswitch-2.17.2.orig/lib/seq.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SEQ_H -#define SEQ_H 1 - -/* Thread-safe, pollable sequence number. - * - * - * Motivation - * ========== - * - * It is sometimes desirable to take an action whenever an object changes. - * Suppose we associate a sequence number with an object and increment the - * sequence number whenver we change the object. An observer can then record - * the sequence number it sees. Later on, if the current sequence number - * differs from the one it saw last, then the observer knows to examine the - * object for changes. - * - * Code that wants to run when a sequence number changes is challenging to - * implement in a multithreaded environment. A naive implementation, that - * simply checks whether the sequence number changed and, if so, calls - * poll_immediate_wake(), will fail when another thread increments the sequence - * number after the check (including during poll_block()). - * - * struct seq is a solution. It implements a sequence number along with enough - * internal infrastructure so that a thread waiting on a particular value will - * wake up if the sequence number changes, or even if the "struct seq" is - * destroyed. - * - * - * Usage - * ===== - * - * The object that includes a sequence number should use seq_create() and - * seq_destroy() at creation and destruction, and seq_change() whenever the - * object's observable state changes. - * - * An observer may seq_read() to read the current sequence number and - * seq_wait() to cause poll_block() to wake up when the sequence number changes - * from a specified value. - * - * To avoid races, observers should use seq_read() to check for changes, - * process any changes, and then use seq_wait() to wait for a change from the - * previously read value. That is, a correct usage looks something like this: - * - * new_seq = seq_read(seq); - * if (new_seq != last_seq) { - * ...process changes... - * last_seq = new_seq; - * } - * seq_wait(seq, new_seq); - * poll_block(); - * - * - * Alternate Usage - * =============== - * - * struct seq can also be used as a sort of pollable condition variable. - * Suppose that we want a thread to process items in a queue, and thus to be - * able to wake up whenever the queue is nonempty. This requires a lock to - * protect the queue and a seq to signal that the queue has become nonempty, - * e.g.: - * - * struct ovs_mutex mutex; - * struct ovs_list queue OVS_GUARDED_BY(mutex); - * struct seq *nonempty_seq; - * - * To add an element to the queue: - * - * ovs_mutex_lock(&mutex); - * ovs_list_push_back(&queue, ...element...); - * if (ovs_list_is_singleton(&queue)) { <-- The 'if' here is optional. - * seq_change(nonempty_seq); - * } - * ovs_mutex_unlock(&mutex); - * - * To wait for the queue to become nonempty: - * - * ovs_mutex_lock(&mutex); - * if (ovs_list_is_empty(&queue)) { - * seq_wait(nonempty_seq, seq_read(nonempty_seq)); - * } else { - * poll_immediate_wake(); - * } - * ovs_mutex_unlock(&mutex); - * - * (In the above code 'mutex' prevents the queue from changing between - * seq_read() and seq_wait(). Otherwise, it would be necessary to seq_read(), - * check for a nonempty queue, and then seq_wait() on the previously read - * sequence number, as under Usage above.) - * - * - * Thread-safety - * ============= - * - * Fully thread safe. seq_change() synchronizes with seq_read() and - * seq_wait() on the same variable in release-acquire fashion. That - * is, all effects of the memory accesses performed by a thread prior - * to seq_change() are visible to the threads returning from - * seq_read() or seq_wait() observing that change. - */ - -#include -#include "util.h" - -/* For implementation of an object with a sequence number attached. */ -struct seq *seq_create(void); -void seq_destroy(struct seq *); -void seq_change(struct seq *); -void seq_change_protected(struct seq *); -void seq_lock(void); -int seq_try_lock(void); -void seq_unlock(void); - -/* For observers. */ -uint64_t seq_read(const struct seq *); -uint64_t seq_read_protected(const struct seq *); - -void seq_wait_at(const struct seq *, uint64_t value, const char *where); -#define seq_wait(seq, value) seq_wait_at(seq, value, OVS_SOURCE_LOCATOR) - -/* For poll_block() internal use. */ -void seq_woke(void); - -#endif /* seq.h */ Index: openvswitch-2.17.2/include/internal/seq.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/seq.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SEQ_H +#define SEQ_H 1 + +/* Thread-safe, pollable sequence number. + * + * + * Motivation + * ========== + * + * It is sometimes desirable to take an action whenever an object changes. + * Suppose we associate a sequence number with an object and increment the + * sequence number whenver we change the object. An observer can then record + * the sequence number it sees. Later on, if the current sequence number + * differs from the one it saw last, then the observer knows to examine the + * object for changes. + * + * Code that wants to run when a sequence number changes is challenging to + * implement in a multithreaded environment. A naive implementation, that + * simply checks whether the sequence number changed and, if so, calls + * poll_immediate_wake(), will fail when another thread increments the sequence + * number after the check (including during poll_block()). + * + * struct seq is a solution. It implements a sequence number along with enough + * internal infrastructure so that a thread waiting on a particular value will + * wake up if the sequence number changes, or even if the "struct seq" is + * destroyed. + * + * + * Usage + * ===== + * + * The object that includes a sequence number should use seq_create() and + * seq_destroy() at creation and destruction, and seq_change() whenever the + * object's observable state changes. + * + * An observer may seq_read() to read the current sequence number and + * seq_wait() to cause poll_block() to wake up when the sequence number changes + * from a specified value. + * + * To avoid races, observers should use seq_read() to check for changes, + * process any changes, and then use seq_wait() to wait for a change from the + * previously read value. That is, a correct usage looks something like this: + * + * new_seq = seq_read(seq); + * if (new_seq != last_seq) { + * ...process changes... + * last_seq = new_seq; + * } + * seq_wait(seq, new_seq); + * poll_block(); + * + * + * Alternate Usage + * =============== + * + * struct seq can also be used as a sort of pollable condition variable. + * Suppose that we want a thread to process items in a queue, and thus to be + * able to wake up whenever the queue is nonempty. This requires a lock to + * protect the queue and a seq to signal that the queue has become nonempty, + * e.g.: + * + * struct ovs_mutex mutex; + * struct ovs_list queue OVS_GUARDED_BY(mutex); + * struct seq *nonempty_seq; + * + * To add an element to the queue: + * + * ovs_mutex_lock(&mutex); + * ovs_list_push_back(&queue, ...element...); + * if (ovs_list_is_singleton(&queue)) { <-- The 'if' here is optional. + * seq_change(nonempty_seq); + * } + * ovs_mutex_unlock(&mutex); + * + * To wait for the queue to become nonempty: + * + * ovs_mutex_lock(&mutex); + * if (ovs_list_is_empty(&queue)) { + * seq_wait(nonempty_seq, seq_read(nonempty_seq)); + * } else { + * poll_immediate_wake(); + * } + * ovs_mutex_unlock(&mutex); + * + * (In the above code 'mutex' prevents the queue from changing between + * seq_read() and seq_wait(). Otherwise, it would be necessary to seq_read(), + * check for a nonempty queue, and then seq_wait() on the previously read + * sequence number, as under Usage above.) + * + * + * Thread-safety + * ============= + * + * Fully thread safe. seq_change() synchronizes with seq_read() and + * seq_wait() on the same variable in release-acquire fashion. That + * is, all effects of the memory accesses performed by a thread prior + * to seq_change() are visible to the threads returning from + * seq_read() or seq_wait() observing that change. + */ + +#include +#include "internal/util.h" + +/* For implementation of an object with a sequence number attached. */ +struct seq *seq_create(void); +void seq_destroy(struct seq *); +void seq_change(struct seq *); +void seq_change_protected(struct seq *); +void seq_lock(void); +int seq_try_lock(void); +void seq_unlock(void); + +/* For observers. */ +uint64_t seq_read(const struct seq *); +uint64_t seq_read_protected(const struct seq *); + +void seq_wait_at(const struct seq *, uint64_t value, const char *where); +#define seq_wait(seq, value) seq_wait_at(seq, value, OVS_SOURCE_LOCATOR) + +/* For poll_block() internal use. */ +void seq_woke(void); + +#endif /* seq.h */ Index: openvswitch-2.17.2/lib/smap.h =================================================================== --- openvswitch-2.17.2.orig/lib/smap.h +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright (c) 2012, 2014, 2015, 2016 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 SMAP_H -#define SMAP_H 1 - -#include -#include -#include "hash.h" -#include "openvswitch/hmap.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct json; -struct uuid; - -/* A map from string to string. */ -struct smap { - struct hmap map; /* Contains "struct smap_node"s. */ -}; - -struct smap_node { - struct hmap_node node; /* In struct smap's 'map' hmap. */ - char *key; - char *value; -}; - -#define SMAP_INITIALIZER(SMAP) { HMAP_INITIALIZER(&(SMAP)->map) } - -#define SMAP_FOR_EACH(SMAP_NODE, SMAP) \ - HMAP_FOR_EACH_INIT (SMAP_NODE, node, &(SMAP)->map, \ - BUILD_ASSERT_TYPE(SMAP_NODE, struct smap_node *), \ - BUILD_ASSERT_TYPE(SMAP, struct smap *)) - -#define SMAP_FOR_EACH_SAFE_SHORT(SMAP_NODE, SMAP) \ - HMAP_FOR_EACH_SAFE_SHORT_INIT ( \ - SMAP_NODE, node, &(SMAP)->map, \ - BUILD_ASSERT_TYPE(SMAP_NODE, struct smap_node *), \ - BUILD_ASSERT_TYPE(SMAP, struct smap *)) - -#define SMAP_FOR_EACH_SAFE_LONG(SMAP_NODE, NEXT, SMAP) \ - HMAP_FOR_EACH_SAFE_LONG_INIT ( \ - SMAP_NODE, NEXT, node, &(SMAP)->map, \ - BUILD_ASSERT_TYPE(SMAP_NODE, struct smap_node *), \ - BUILD_ASSERT_TYPE(NEXT, struct smap_node *), \ - BUILD_ASSERT_TYPE(SMAP, struct smap *)) - -#define SMAP_FOR_EACH_SAFE(...) \ - OVERLOAD_SAFE_MACRO(SMAP_FOR_EACH_SAFE_LONG, \ - SMAP_FOR_EACH_SAFE_SHORT, \ - 3, __VA_ARGS__) - -/* Initializer for an immutable struct smap 'SMAP' that contains one or two - * key-value pairs, e.g. - * - * const struct smap smap1 = SMAP_CONST1(&smap, "key", "value"); - * const struct smap smap2 = SMAP_CONST2(&smap, "key1", "value1", - * "key2", "value2"); - * - * An smap initialized this way must not be modified or destroyed. - * - * The 'KEY', 'K1', 'K2' arguments are evaluated multiple times. - */ -#define SMAP_CONST1(SMAP, KEY, VALUE) (const struct smap) { \ - HMAP_CONST(&(SMAP)->map, 1, SMAP_NODE(KEY, VALUE, NULL)) \ - } -#define SMAP_CONST2(SMAP, K1, V1, K2, V2) (const struct smap) { \ - HMAP_CONST(&(SMAP)->map, 2, \ - SMAP_NODE(K1, V1, SMAP_NODE(K2, V2, NULL))) \ - } -#define SMAP_NODE(KEY, VALUE, NEXT) \ - &(struct smap_node) { \ - .node = { \ - .hash = hash_string(KEY, 0), \ - .next = (NEXT), \ - }, \ - .key = CONST_CAST(char *, KEY), \ - .value = CONST_CAST(char *, VALUE), \ - }.node - - -void smap_init(struct smap *); -void smap_destroy(struct smap *); - -struct smap_node *smap_add(struct smap *, const char *, const char *); -struct smap_node *smap_add_nocopy(struct smap *, char *, char *); -bool smap_add_once(struct smap *, const char *, const char *); -void smap_add_format(struct smap *, const char *key, const char *, ...) - OVS_PRINTF_FORMAT(3, 4); -void smap_add_ipv6(struct smap *, const char *, struct in6_addr *); -void smap_replace(struct smap *, const char *, const char *); -void smap_replace_nocopy(struct smap *, const char *, char *); - -void smap_remove(struct smap *, const char *); -void smap_remove_node(struct smap *, struct smap_node *); -void smap_steal(struct smap *, struct smap_node *, char **keyp, char **valuep); -void smap_clear(struct smap *); - -const char *smap_get(const struct smap *, const char *key); -const char *smap_get_def(const struct smap *, const char *key, - const char *def); -struct smap_node *smap_get_node(const struct smap *, const char *); -bool smap_get_bool(const struct smap *smap, const char *key, bool def); -int smap_get_int(const struct smap *smap, const char *key, int def); -unsigned int smap_get_uint(const struct smap *smap, const char *key, - unsigned int def); -unsigned long long int smap_get_ullong(const struct smap *, const char *key, - unsigned long long def); -bool smap_get_uuid(const struct smap *, const char *key, struct uuid *); - -bool smap_is_empty(const struct smap *); -size_t smap_count(const struct smap *); - -void smap_clone(struct smap *dst, const struct smap *src); -const struct smap_node **smap_sort(const struct smap *); - -void smap_from_json(struct smap *, const struct json *); -struct json *smap_to_json(const struct smap *); - -bool smap_equal(const struct smap *, const struct smap *); - -#ifdef __cplusplus -} -#endif - -#endif /* smap.h */ Index: openvswitch-2.17.2/include/internal/smap.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/smap.h @@ -0,0 +1,139 @@ +/* Copyright (c) 2012, 2014, 2015, 2016 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 SMAP_H +#define SMAP_H 1 + +#include +#include +#include "internal/hash.h" +#include "openvswitch/hmap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct json; +struct uuid; + +/* A map from string to string. */ +struct smap { + struct hmap map; /* Contains "struct smap_node"s. */ +}; + +struct smap_node { + struct hmap_node node; /* In struct smap's 'map' hmap. */ + char *key; + char *value; +}; + +#define SMAP_INITIALIZER(SMAP) { HMAP_INITIALIZER(&(SMAP)->map) } + +#define SMAP_FOR_EACH(SMAP_NODE, SMAP) \ + HMAP_FOR_EACH_INIT (SMAP_NODE, node, &(SMAP)->map, \ + BUILD_ASSERT_TYPE(SMAP_NODE, struct smap_node *), \ + BUILD_ASSERT_TYPE(SMAP, struct smap *)) + +#define SMAP_FOR_EACH_SAFE_SHORT(SMAP_NODE, SMAP) \ + HMAP_FOR_EACH_SAFE_SHORT_INIT ( \ + SMAP_NODE, node, &(SMAP)->map, \ + BUILD_ASSERT_TYPE(SMAP_NODE, struct smap_node *), \ + BUILD_ASSERT_TYPE(SMAP, struct smap *)) + +#define SMAP_FOR_EACH_SAFE_LONG(SMAP_NODE, NEXT, SMAP) \ + HMAP_FOR_EACH_SAFE_LONG_INIT ( \ + SMAP_NODE, NEXT, node, &(SMAP)->map, \ + BUILD_ASSERT_TYPE(SMAP_NODE, struct smap_node *), \ + BUILD_ASSERT_TYPE(NEXT, struct smap_node *), \ + BUILD_ASSERT_TYPE(SMAP, struct smap *)) + +#define SMAP_FOR_EACH_SAFE(...) \ + OVERLOAD_SAFE_MACRO(SMAP_FOR_EACH_SAFE_LONG, \ + SMAP_FOR_EACH_SAFE_SHORT, \ + 3, __VA_ARGS__) + +/* Initializer for an immutable struct smap 'SMAP' that contains one or two + * key-value pairs, e.g. + * + * const struct smap smap1 = SMAP_CONST1(&smap, "key", "value"); + * const struct smap smap2 = SMAP_CONST2(&smap, "key1", "value1", + * "key2", "value2"); + * + * An smap initialized this way must not be modified or destroyed. + * + * The 'KEY', 'K1', 'K2' arguments are evaluated multiple times. + */ +#define SMAP_CONST1(SMAP, KEY, VALUE) (const struct smap) { \ + HMAP_CONST(&(SMAP)->map, 1, SMAP_NODE(KEY, VALUE, NULL)) \ + } +#define SMAP_CONST2(SMAP, K1, V1, K2, V2) (const struct smap) { \ + HMAP_CONST(&(SMAP)->map, 2, \ + SMAP_NODE(K1, V1, SMAP_NODE(K2, V2, NULL))) \ + } +#define SMAP_NODE(KEY, VALUE, NEXT) \ + &(struct smap_node) { \ + .node = { \ + .hash = hash_string(KEY, 0), \ + .next = (NEXT), \ + }, \ + .key = CONST_CAST(char *, KEY), \ + .value = CONST_CAST(char *, VALUE), \ + }.node + + +void smap_init(struct smap *); +void smap_destroy(struct smap *); + +struct smap_node *smap_add(struct smap *, const char *, const char *); +struct smap_node *smap_add_nocopy(struct smap *, char *, char *); +bool smap_add_once(struct smap *, const char *, const char *); +void smap_add_format(struct smap *, const char *key, const char *, ...) + OVS_PRINTF_FORMAT(3, 4); +void smap_add_ipv6(struct smap *, const char *, struct in6_addr *); +void smap_replace(struct smap *, const char *, const char *); +void smap_replace_nocopy(struct smap *, const char *, char *); + +void smap_remove(struct smap *, const char *); +void smap_remove_node(struct smap *, struct smap_node *); +void smap_steal(struct smap *, struct smap_node *, char **keyp, char **valuep); +void smap_clear(struct smap *); + +const char *smap_get(const struct smap *, const char *key); +const char *smap_get_def(const struct smap *, const char *key, + const char *def); +struct smap_node *smap_get_node(const struct smap *, const char *); +bool smap_get_bool(const struct smap *smap, const char *key, bool def); +int smap_get_int(const struct smap *smap, const char *key, int def); +unsigned int smap_get_uint(const struct smap *smap, const char *key, + unsigned int def); +unsigned long long int smap_get_ullong(const struct smap *, const char *key, + unsigned long long def); +bool smap_get_uuid(const struct smap *, const char *key, struct uuid *); + +bool smap_is_empty(const struct smap *); +size_t smap_count(const struct smap *); + +void smap_clone(struct smap *dst, const struct smap *src); +const struct smap_node **smap_sort(const struct smap *); + +void smap_from_json(struct smap *, const struct json *); +struct json *smap_to_json(const struct smap *); + +bool smap_equal(const struct smap *, const struct smap *); + +#ifdef __cplusplus +} +#endif + +#endif /* smap.h */ Index: openvswitch-2.17.2/lib/sset.h =================================================================== --- openvswitch-2.17.2.orig/lib/sset.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2011, 2012, 2013, 2015, 2016 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 SSET_H -#define SSET_H - -#include "openvswitch/hmap.h" -#include "util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct sset_node { - struct hmap_node hmap_node; - char name[1]; -}; - -/* A set of strings. */ -struct sset { - struct hmap map; -}; - -#define SSET_INITIALIZER(SSET) { HMAP_INITIALIZER(&(SSET)->map) } - -/* Basics. */ -void sset_init(struct sset *); -void sset_destroy(struct sset *); -void sset_clone(struct sset *, const struct sset *); -void sset_swap(struct sset *, struct sset *); -void sset_moved(struct sset *); - -/* String parsing and formatting. */ -void sset_from_delimited_string(struct sset *, const char *s, - const char *delimiters); -char *sset_join(const struct sset *, - const char *delimiter, const char *terminator); - -/* Count. */ -bool sset_is_empty(const struct sset *); -size_t sset_count(const struct sset *); - -/* Insertion. */ -struct sset_node *sset_add(struct sset *, const char *); -struct sset_node *sset_add_and_free(struct sset *, char *); -void sset_add_assert(struct sset *, const char *); -void sset_add_array(struct sset *, char **, size_t n); - -/* Deletion. */ -void sset_clear(struct sset *); -void sset_delete(struct sset *, struct sset_node *); -bool sset_find_and_delete(struct sset *, const char *); -void sset_find_and_delete_assert(struct sset *, const char *); -char *sset_pop(struct sset *); - -/* Search. */ -struct sset_node *sset_find(const struct sset *, const char *); -bool sset_contains(const struct sset *, const char *); -bool sset_equals(const struct sset *, const struct sset *); - -struct sset_position { - struct hmap_position pos; -}; - -struct sset_node *sset_at_position(const struct sset *, - struct sset_position *); - -/* Set operations. */ -void sset_intersect(struct sset *, const struct sset *); - -/* Iteration macros. */ -#define SSET_FOR_EACH(NAME, SSET) \ - for ((NAME) = SSET_FIRST(SSET); \ - NAME != NULL; \ - (NAME) = SSET_NEXT(SSET, NAME)) - -#define SSET_FOR_EACH_SAFE_LONG(NAME, NEXT, SSET) \ - for ((NAME) = SSET_FIRST(SSET); \ - (NAME != NULL \ - ? (NEXT) = SSET_NEXT(SSET, NAME), true \ - : false); \ - (NAME) = (NEXT)) - -#define SSET_FOR_EACH_SAFE_SHORT(NAME, SSET) \ - for (const char * NAME__next = \ - ((NAME) = SSET_FIRST(SSET), NULL); \ - (NAME != NULL \ - ? (NAME__next = SSET_NEXT(SSET, NAME), true) \ - : (NAME__next = NULL, false)); \ - (NAME) = NAME__next) - -#define SSET_FOR_EACH_SAFE(...) \ - OVERLOAD_SAFE_MACRO(SSET_FOR_EACH_SAFE_LONG, \ - SSET_FOR_EACH_SAFE_SHORT, \ - 3, __VA_ARGS__) - -const char **sset_array(const struct sset *); -const char **sset_sort(const struct sset *); - -/* Implementation helper macros. */ - -#define SSET_NODE_FROM_HMAP_NODE(HMAP_NODE) \ - CONTAINER_OF(HMAP_NODE, struct sset_node, hmap_node) -#define SSET_NAME_FROM_HMAP_NODE(HMAP_NODE) \ - HMAP_NODE == NULL \ - ? NULL \ - : (CONST_CAST(const char *, (SSET_NODE_FROM_HMAP_NODE(HMAP_NODE)->name))) -#define SSET_NODE_FROM_NAME(NAME) CONTAINER_OF(NAME, struct sset_node, name) -#define SSET_FIRST(SSET) \ - (BUILD_ASSERT_TYPE(SSET, struct sset *), \ - SSET_NAME_FROM_HMAP_NODE(hmap_first(&(SSET)->map))) -#define SSET_NEXT(SSET, NAME) \ - (BUILD_ASSERT_TYPE(SSET, struct sset *), \ - SSET_NAME_FROM_HMAP_NODE( \ - hmap_next(&(SSET)->map, &SSET_NODE_FROM_NAME(NAME)->hmap_node))) - -#ifdef __cplusplus -} -#endif - -#endif /* sset.h */ Index: openvswitch-2.17.2/include/internal/sset.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/sset.h @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2011, 2012, 2013, 2015, 2016 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 SSET_H +#define SSET_H + +#include "openvswitch/hmap.h" +#include "internal/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct sset_node { + struct hmap_node hmap_node; + char name[1]; +}; + +/* A set of strings. */ +struct sset { + struct hmap map; +}; + +#define SSET_INITIALIZER(SSET) { HMAP_INITIALIZER(&(SSET)->map) } + +/* Basics. */ +void sset_init(struct sset *); +void sset_destroy(struct sset *); +void sset_clone(struct sset *, const struct sset *); +void sset_swap(struct sset *, struct sset *); +void sset_moved(struct sset *); + +/* String parsing and formatting. */ +void sset_from_delimited_string(struct sset *, const char *s, + const char *delimiters); +char *sset_join(const struct sset *, + const char *delimiter, const char *terminator); + +/* Count. */ +bool sset_is_empty(const struct sset *); +size_t sset_count(const struct sset *); + +/* Insertion. */ +struct sset_node *sset_add(struct sset *, const char *); +struct sset_node *sset_add_and_free(struct sset *, char *); +void sset_add_assert(struct sset *, const char *); +void sset_add_array(struct sset *, char **, size_t n); + +/* Deletion. */ +void sset_clear(struct sset *); +void sset_delete(struct sset *, struct sset_node *); +bool sset_find_and_delete(struct sset *, const char *); +void sset_find_and_delete_assert(struct sset *, const char *); +char *sset_pop(struct sset *); + +/* Search. */ +struct sset_node *sset_find(const struct sset *, const char *); +bool sset_contains(const struct sset *, const char *); +bool sset_equals(const struct sset *, const struct sset *); + +struct sset_position { + struct hmap_position pos; +}; + +struct sset_node *sset_at_position(const struct sset *, + struct sset_position *); + +/* Set operations. */ +void sset_intersect(struct sset *, const struct sset *); + +/* Iteration macros. */ +#define SSET_FOR_EACH(NAME, SSET) \ + for ((NAME) = SSET_FIRST(SSET); \ + NAME != NULL; \ + (NAME) = SSET_NEXT(SSET, NAME)) + +#define SSET_FOR_EACH_SAFE_LONG(NAME, NEXT, SSET) \ + for ((NAME) = SSET_FIRST(SSET); \ + (NAME != NULL \ + ? (NEXT) = SSET_NEXT(SSET, NAME), true \ + : false); \ + (NAME) = (NEXT)) + +#define SSET_FOR_EACH_SAFE_SHORT(NAME, SSET) \ + for (const char * NAME__next = \ + ((NAME) = SSET_FIRST(SSET), NULL); \ + (NAME != NULL \ + ? (NAME__next = SSET_NEXT(SSET, NAME), true) \ + : (NAME__next = NULL, false)); \ + (NAME) = NAME__next) + +#define SSET_FOR_EACH_SAFE(...) \ + OVERLOAD_SAFE_MACRO(SSET_FOR_EACH_SAFE_LONG, \ + SSET_FOR_EACH_SAFE_SHORT, \ + 3, __VA_ARGS__) + +const char **sset_array(const struct sset *); +const char **sset_sort(const struct sset *); + +/* Implementation helper macros. */ + +#define SSET_NODE_FROM_HMAP_NODE(HMAP_NODE) \ + CONTAINER_OF(HMAP_NODE, struct sset_node, hmap_node) +#define SSET_NAME_FROM_HMAP_NODE(HMAP_NODE) \ + HMAP_NODE == NULL \ + ? NULL \ + : (CONST_CAST(const char *, (SSET_NODE_FROM_HMAP_NODE(HMAP_NODE)->name))) +#define SSET_NODE_FROM_NAME(NAME) CONTAINER_OF(NAME, struct sset_node, name) +#define SSET_FIRST(SSET) \ + (BUILD_ASSERT_TYPE(SSET, struct sset *), \ + SSET_NAME_FROM_HMAP_NODE(hmap_first(&(SSET)->map))) +#define SSET_NEXT(SSET, NAME) \ + (BUILD_ASSERT_TYPE(SSET, struct sset *), \ + SSET_NAME_FROM_HMAP_NODE( \ + hmap_next(&(SSET)->map, &SSET_NODE_FROM_NAME(NAME)->hmap_node))) + +#ifdef __cplusplus +} +#endif + +#endif /* sset.h */ Index: openvswitch-2.17.2/lib/stream.h =================================================================== --- openvswitch-2.17.2.orig/lib/stream.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2009, 2010, 2011, 2013, 2015 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef STREAM_H -#define STREAM_H 1 - -#include -#include -#include -#include -#include "openvswitch/types.h" -#include "socket-util.h" -#include "util.h" - -struct pstream; -struct stream; -struct vlog_module; - -void stream_usage(const char *name, bool active, bool passive, bool bootstrap); - -/* Bidirectional byte streams. */ -int stream_verify_name(const char *name); -int stream_open(const char *name, struct stream **, uint8_t dscp); -int stream_open_block(int error, long long int timeout, struct stream **); -void stream_close(struct stream *); -const char *stream_get_name(const struct stream *); -int stream_connect(struct stream *); -int stream_recv(struct stream *, void *buffer, size_t n); -int stream_send(struct stream *, const void *buffer, size_t n); - -void stream_run(struct stream *); -void stream_run_wait(struct stream *); - -enum stream_wait_type { - STREAM_CONNECT, - STREAM_RECV, - STREAM_SEND -}; -void stream_wait(struct stream *, enum stream_wait_type); -void stream_connect_wait(struct stream *); -void stream_recv_wait(struct stream *); -void stream_send_wait(struct stream *); -void stream_set_peer_id(struct stream *, const char *); -const char *stream_get_peer_id(const struct stream *); - -/* Passive streams: listeners for incoming stream connections. */ -int pstream_verify_name(const char *name); -int pstream_open(const char *name, struct pstream **, uint8_t dscp); -const char *pstream_get_name(const struct pstream *); -void pstream_close(struct pstream *); -int pstream_accept(struct pstream *, struct stream **); -int pstream_accept_block(struct pstream *, struct stream **); -void pstream_wait(struct pstream *); - -ovs_be16 pstream_get_bound_port(const struct pstream *); - -/* Convenience functions. */ - -int stream_open_with_default_port(const char *name, - uint16_t default_port, - struct stream **, - uint8_t dscp); -int pstream_open_with_default_port(const char *name, - uint16_t default_port, - struct pstream **, - uint8_t dscp); -bool stream_parse_target_with_default_port(const char *target, - int default_port, - struct sockaddr_storage *ss); -int stream_or_pstream_needs_probes(const char *name); - -/* Error reporting. */ - -enum stream_content_type { - STREAM_UNKNOWN, - STREAM_OPENFLOW, - STREAM_SSL, - STREAM_JSONRPC -}; - -void stream_report_content(const void *, ssize_t, enum stream_content_type, - struct vlog_module *, const char *stream_name); - - -/* Stream replay helpers. */ -void stream_replay_open_wfd(struct stream *, int open_result, - const char *name); -void pstream_replay_open_wfd(struct pstream *, int listen_result, - const char *name); -void stream_replay_close_wfd(struct stream *); -void pstream_replay_close_wfd(struct pstream *); -void stream_replay_write(struct stream *, const void *, int, bool is_read); -void pstream_replay_write_accept(struct pstream *, const struct stream *, - int accept_result); - -#endif /* stream.h */ Index: openvswitch-2.17.2/include/internal/stream.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/stream.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2009, 2010, 2011, 2013, 2015 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef STREAM_H +#define STREAM_H 1 + +#include +#include +#include +#include +#include "openvswitch/types.h" +#include "internal/socket-util.h" +#include "internal/util.h" + +struct pstream; +struct stream; +struct vlog_module; + +void stream_usage(const char *name, bool active, bool passive, bool bootstrap); + +/* Bidirectional byte streams. */ +int stream_verify_name(const char *name); +int stream_open(const char *name, struct stream **, uint8_t dscp); +int stream_open_block(int error, long long int timeout, struct stream **); +void stream_close(struct stream *); +const char *stream_get_name(const struct stream *); +int stream_connect(struct stream *); +int stream_recv(struct stream *, void *buffer, size_t n); +int stream_send(struct stream *, const void *buffer, size_t n); + +void stream_run(struct stream *); +void stream_run_wait(struct stream *); + +enum stream_wait_type { + STREAM_CONNECT, + STREAM_RECV, + STREAM_SEND +}; +void stream_wait(struct stream *, enum stream_wait_type); +void stream_connect_wait(struct stream *); +void stream_recv_wait(struct stream *); +void stream_send_wait(struct stream *); +void stream_set_peer_id(struct stream *, const char *); +const char *stream_get_peer_id(const struct stream *); + +/* Passive streams: listeners for incoming stream connections. */ +int pstream_verify_name(const char *name); +int pstream_open(const char *name, struct pstream **, uint8_t dscp); +const char *pstream_get_name(const struct pstream *); +void pstream_close(struct pstream *); +int pstream_accept(struct pstream *, struct stream **); +int pstream_accept_block(struct pstream *, struct stream **); +void pstream_wait(struct pstream *); + +ovs_be16 pstream_get_bound_port(const struct pstream *); + +/* Convenience functions. */ + +int stream_open_with_default_port(const char *name, + uint16_t default_port, + struct stream **, + uint8_t dscp); +int pstream_open_with_default_port(const char *name, + uint16_t default_port, + struct pstream **, + uint8_t dscp); +bool stream_parse_target_with_default_port(const char *target, + int default_port, + struct sockaddr_storage *ss); +int stream_or_pstream_needs_probes(const char *name); + +/* Error reporting. */ + +enum stream_content_type { + STREAM_UNKNOWN, + STREAM_OPENFLOW, + STREAM_SSL, + STREAM_JSONRPC +}; + +void stream_report_content(const void *, ssize_t, enum stream_content_type, + struct vlog_module *, const char *stream_name); + + +/* Stream replay helpers. */ +void stream_replay_open_wfd(struct stream *, int open_result, + const char *name); +void pstream_replay_open_wfd(struct pstream *, int listen_result, + const char *name); +void stream_replay_close_wfd(struct stream *); +void pstream_replay_close_wfd(struct pstream *); +void stream_replay_write(struct stream *, const void *, int, bool is_read); +void pstream_replay_write_accept(struct pstream *, const struct stream *, + int accept_result); + +#endif /* stream.h */ Index: openvswitch-2.17.2/lib/timer.h =================================================================== --- openvswitch-2.17.2.orig/lib/timer.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2011, 2013 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TIMER_H -#define TIMER_H 1 - -#include - -#include "timeval.h" -#include "util.h" - -struct timer { - long long int t; -}; - -long long int timer_msecs_until_expired(const struct timer *); -void timer_wait_at(const struct timer *, const char *where); -#define timer_wait(timer) timer_wait_at(timer, OVS_SOURCE_LOCATOR) - -/* Causes 'timer' to expire when 'duration' milliseconds have passed. - * - * May be used to initialize 'timer'. */ -static inline void -timer_set_duration(struct timer *timer, long long int duration) -{ - timer->t = time_msec() + duration; -} - -/* Causes 'timer' never to expire. - * - * May be used to initialize 'timer'. */ -static inline void -timer_set_infinite(struct timer *timer) -{ - timer->t = LLONG_MAX; -} - -/* Causes 'timer' to expire immediately. - * - * May be used to initialize 'timer'. */ -static inline void -timer_set_expired(struct timer *timer) -{ - timer->t = LLONG_MIN; -} - -/* True if 'timer' has expired. */ -static inline bool -timer_expired(const struct timer *timer) -{ - return time_msec() >= timer->t; -} - -/* Returns ture if 'timer' will never expire. */ -static inline bool -timer_is_infinite(const struct timer *timer) -{ - return timer->t == LLONG_MAX; -} - -#endif /* timer.h */ Index: openvswitch-2.17.2/include/internal/timer.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/timer.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011, 2013 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TIMER_H +#define TIMER_H 1 + +#include + +#include "internal/timeval.h" +#include "internal/util.h" + +struct timer { + long long int t; +}; + +long long int timer_msecs_until_expired(const struct timer *); +void timer_wait_at(const struct timer *, const char *where); +#define timer_wait(timer) timer_wait_at(timer, OVS_SOURCE_LOCATOR) + +/* Causes 'timer' to expire when 'duration' milliseconds have passed. + * + * May be used to initialize 'timer'. */ +static inline void +timer_set_duration(struct timer *timer, long long int duration) +{ + timer->t = time_msec() + duration; +} + +/* Causes 'timer' never to expire. + * + * May be used to initialize 'timer'. */ +static inline void +timer_set_infinite(struct timer *timer) +{ + timer->t = LLONG_MAX; +} + +/* Causes 'timer' to expire immediately. + * + * May be used to initialize 'timer'. */ +static inline void +timer_set_expired(struct timer *timer) +{ + timer->t = LLONG_MIN; +} + +/* True if 'timer' has expired. */ +static inline bool +timer_expired(const struct timer *timer) +{ + return time_msec() >= timer->t; +} + +/* Returns ture if 'timer' will never expire. */ +static inline bool +timer_is_infinite(const struct timer *timer) +{ + return timer->t == LLONG_MAX; +} + +#endif /* timer.h */ Index: openvswitch-2.17.2/lib/timeval.h =================================================================== --- openvswitch-2.17.2.orig/lib/timeval.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TIMEVAL_H -#define TIMEVAL_H 1 - -#include -#include "openvswitch/type-props.h" -#include "util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct ds; -struct pollfd; -struct timespec; -struct timeval; - -/* POSIX allows floating-point time_t, but we don't support it. */ -BUILD_ASSERT_DECL(TYPE_IS_INTEGER(time_t)); - -/* We do try to cater to unsigned time_t, but I want to know about it if we - * ever encounter such a platform. */ -BUILD_ASSERT_DECL(TYPE_IS_SIGNED(time_t)); - -#define TIME_MAX TYPE_MAXIMUM(time_t) -#define TIME_MIN TYPE_MINIMUM(time_t) - -#ifdef _WIN32 -#define localtime_r(timep, result) localtime_s(result, timep) -#define gmtime_r(timep, result) gmtime_s(result, timep) -#endif /* _WIN32 */ - -struct tm_msec { - struct tm tm; - int msec; -}; - -time_t time_now(void); -time_t time_wall(void); -long long int time_msec(void); -long long int time_wall_msec(void); -long long int time_usec(void); -long long int time_wall_usec(void); -void time_timespec(struct timespec *); -void time_wall_timespec(struct timespec *); -void time_alarm(unsigned int secs); -int time_poll(struct pollfd *, int n_pollfds, HANDLE *handles, - long long int timeout_when, int *elapsed); - -long long int timespec_to_msec(const struct timespec *); -long long int timespec_to_usec(const struct timespec *); -long long int timeval_to_msec(const struct timeval *); -long long int timeval_to_usec(const struct timeval *); - -struct tm_msec *localtime_msec(long long int now, struct tm_msec *result); -struct tm_msec *gmtime_msec(long long int now, struct tm_msec *result); -size_t strftime_msec(char *s, size_t max, const char *format, - const struct tm_msec *); -void xgettimeofday(struct timeval *); -void xclock_gettime(clock_t, struct timespec *); -void nsec_to_timespec(long long int, struct timespec *); - -int get_cpu_usage(void); - -long long int time_boot_msec(void); - -void timewarp_run(void); - -#ifdef __cplusplus -} -#endif - -#endif /* timeval.h */ Index: openvswitch-2.17.2/include/internal/timeval.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/timeval.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TIMEVAL_H +#define TIMEVAL_H 1 + +#include +#include "openvswitch/type-props.h" +#include "internal/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ds; +struct pollfd; +struct timespec; +struct timeval; + +/* POSIX allows floating-point time_t, but we don't support it. */ +BUILD_ASSERT_DECL(TYPE_IS_INTEGER(time_t)); + +/* We do try to cater to unsigned time_t, but I want to know about it if we + * ever encounter such a platform. */ +BUILD_ASSERT_DECL(TYPE_IS_SIGNED(time_t)); + +#define TIME_MAX TYPE_MAXIMUM(time_t) +#define TIME_MIN TYPE_MINIMUM(time_t) + +#ifdef _WIN32 +#define localtime_r(timep, result) localtime_s(result, timep) +#define gmtime_r(timep, result) gmtime_s(result, timep) +#endif /* _WIN32 */ + +struct tm_msec { + struct tm tm; + int msec; +}; + +time_t time_now(void); +time_t time_wall(void); +long long int time_msec(void); +long long int time_wall_msec(void); +long long int time_usec(void); +long long int time_wall_usec(void); +void time_timespec(struct timespec *); +void time_wall_timespec(struct timespec *); +void time_alarm(unsigned int secs); +int time_poll(struct pollfd *, int n_pollfds, HANDLE *handles, + long long int timeout_when, int *elapsed); + +long long int timespec_to_msec(const struct timespec *); +long long int timespec_to_usec(const struct timespec *); +long long int timeval_to_msec(const struct timeval *); +long long int timeval_to_usec(const struct timeval *); + +struct tm_msec *localtime_msec(long long int now, struct tm_msec *result); +struct tm_msec *gmtime_msec(long long int now, struct tm_msec *result); +size_t strftime_msec(char *s, size_t max, const char *format, + const struct tm_msec *); +void xgettimeofday(struct timeval *); +void xclock_gettime(clock_t, struct timespec *); +void nsec_to_timespec(long long int, struct timespec *); + +int get_cpu_usage(void); + +long long int time_boot_msec(void); + +void timewarp_run(void); + +#ifdef __cplusplus +} +#endif + +#endif /* timeval.h */ Index: openvswitch-2.17.2/lib/tun-metadata.h =================================================================== --- openvswitch-2.17.2.orig/lib/tun-metadata.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2015 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TUN_METADATA_H -#define TUN_METADATA_H 1 - -#include - -#include "openvswitch/dynamic-string.h" -#include "netlink.h" -#include "openvswitch/ofpbuf.h" -#include "openflow/openflow.h" -#include "openvswitch/tun-metadata.h" - -struct flow_tnl; -struct match; -struct mf_field; -union mf_value; -struct ofputil_tlv_table_mod; -struct ofputil_tlv_table_reply; -struct tun_table; - -struct tun_table *tun_metadata_alloc(const struct tun_table *old_map); -void tun_metadata_free(struct tun_table *); -void tun_metadata_postpone_free(struct tun_table *); - -enum ofperr tun_metadata_table_mod(struct ofputil_tlv_table_mod *, - const struct tun_table *old_tab, - struct tun_table **new_tab); -void tun_metadata_table_request(const struct tun_table *, - struct ofputil_tlv_table_reply *); - -void tun_metadata_read(const struct flow_tnl *, - const struct mf_field *, union mf_value *); -void tun_metadata_write(struct flow_tnl *, - const struct mf_field *, const union mf_value *); -void tun_metadata_delete(struct flow_tnl *, const struct mf_field *); -void tun_metadata_set_match(const struct mf_field *, - const union mf_value *value, - const union mf_value *mask, struct match *, - char **err_str); -void tun_metadata_get_fmd(const struct flow_tnl *, struct match *flow_metadata); - -void tun_metadata_from_geneve_nlattr(const struct nlattr *attr, bool is_mask, - struct flow_tnl *tun); -void tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun, - const struct flow_tnl *flow, - const struct ofpbuf *key, - struct ofpbuf *); - -int tun_metadata_from_geneve_udpif(const struct tun_table *, - const struct flow_tnl *flow, - const struct flow_tnl *src, - struct flow_tnl *dst); -void tun_metadata_to_geneve_udpif_mask(const struct flow_tnl *flow_src, - const struct flow_tnl *mask_src, - const struct geneve_opt *flow_src_opt, - int opts_len, struct geneve_opt *dst); - -int tun_metadata_to_geneve_header(const struct flow_tnl *flow, - struct geneve_opt *, bool *crit_opt); - -void tun_metadata_to_nx_match(struct ofpbuf *b, enum ofp_version oxm, - const struct match *); -void tun_metadata_match_format(struct ds *, const struct match *); - -#endif /* tun-metadata.h */ Index: openvswitch-2.17.2/include/internal/tun-metadata-private.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/tun-metadata-private.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TUN_METADATA_H +#define TUN_METADATA_H 1 + +#include + +#include "openvswitch/dynamic-string.h" +#include "internal/netlink.h" +#include "openvswitch/ofpbuf.h" +#include "openflow/openflow.h" +#include "openvswitch/tun-metadata.h" + +struct flow_tnl; +struct match; +struct mf_field; +union mf_value; +struct ofputil_tlv_table_mod; +struct ofputil_tlv_table_reply; +struct tun_table; + +struct tun_table *tun_metadata_alloc(const struct tun_table *old_map); +void tun_metadata_free(struct tun_table *); +void tun_metadata_postpone_free(struct tun_table *); + +enum ofperr tun_metadata_table_mod(struct ofputil_tlv_table_mod *, + const struct tun_table *old_tab, + struct tun_table **new_tab); +void tun_metadata_table_request(const struct tun_table *, + struct ofputil_tlv_table_reply *); + +void tun_metadata_read(const struct flow_tnl *, + const struct mf_field *, union mf_value *); +void tun_metadata_write(struct flow_tnl *, + const struct mf_field *, const union mf_value *); +void tun_metadata_delete(struct flow_tnl *, const struct mf_field *); +void tun_metadata_set_match(const struct mf_field *, + const union mf_value *value, + const union mf_value *mask, struct match *, + char **err_str); +void tun_metadata_get_fmd(const struct flow_tnl *, struct match *flow_metadata); + +void tun_metadata_from_geneve_nlattr(const struct nlattr *attr, bool is_mask, + struct flow_tnl *tun); +void tun_metadata_to_geneve_nlattr(const struct flow_tnl *tun, + const struct flow_tnl *flow, + const struct ofpbuf *key, + struct ofpbuf *); + +int tun_metadata_from_geneve_udpif(const struct tun_table *, + const struct flow_tnl *flow, + const struct flow_tnl *src, + struct flow_tnl *dst); +void tun_metadata_to_geneve_udpif_mask(const struct flow_tnl *flow_src, + const struct flow_tnl *mask_src, + const struct geneve_opt *flow_src_opt, + int opts_len, struct geneve_opt *dst); + +int tun_metadata_to_geneve_header(const struct flow_tnl *flow, + struct geneve_opt *, bool *crit_opt); + +void tun_metadata_to_nx_match(struct ofpbuf *b, enum ofp_version oxm, + const struct match *); +void tun_metadata_match_format(struct ds *, const struct match *); + +#endif /* tun-metadata.h */ Index: openvswitch-2.17.2/lib/unaligned.h =================================================================== --- openvswitch-2.17.2.orig/lib/unaligned.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2010, 2011, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef UNALIGNED_H -#define UNALIGNED_H 1 - -#include -#include "byte-order.h" -#include "openvswitch/types.h" -#include "openvswitch/type-props.h" -#include "util.h" - -/* Public API. */ -static inline uint16_t get_unaligned_u16(const uint16_t *); -static inline uint32_t get_unaligned_u32(const uint32_t *); -static inline void put_unaligned_u16(uint16_t *, uint16_t); -static inline void put_unaligned_u32(uint32_t *, uint32_t); -static inline void put_unaligned_u64(uint64_t *, uint64_t); - -static inline ovs_be16 get_unaligned_be16(const ovs_be16 *); -static inline ovs_be32 get_unaligned_be32(const ovs_be32 *); -static inline ovs_be64 get_unaligned_be64(const ovs_be64 *); -static inline void put_unaligned_be16(ovs_be16 *, ovs_be16); -static inline void put_unaligned_be32(ovs_be32 *, ovs_be32); -static inline void put_unaligned_be64(ovs_be64 *, ovs_be64); - -/* uint64_t get_unaligned_u64(uint64_t *p); - * - * Returns the value of the possibly misaligned uint64_t at 'p'. 'p' may - * actually be any type that points to a 64-bit integer. That is, on Unix-like - * 32-bit ABIs, it may point to an "unsigned long long int", and on Unix-like - * 64-bit ABIs, it may point to an "unsigned long int" or an "unsigned long - * long int". - * - * This is special-cased because on some Linux targets, the kernel __u64 is - * unsigned long long int and the userspace uint64_t is unsigned long int, so - * that any single function prototype would fail to accept one or the other. - * - * Below, "sizeof (*(P) % 1)" verifies that *P has an integer type, since - * operands to % must be integers. - */ -#define get_unaligned_u64(P) \ - (BUILD_ASSERT(sizeof *(P) == 8), \ - BUILD_ASSERT_GCCONLY(!TYPE_IS_SIGNED(typeof(*(P)))), \ - (void) sizeof (*(P) % 1), \ - get_unaligned_u64__((const uint64_t *) (P))) - -#ifdef __GNUC__ -/* GCC implementations. */ -#define GCC_UNALIGNED_ACCESSORS(TYPE, ABBREV) \ -struct unaligned_##ABBREV { \ - TYPE x __attribute__((__packed__)); \ -}; \ -static inline struct unaligned_##ABBREV * \ -unaligned_##ABBREV(const TYPE *p) \ -{ \ - return (struct unaligned_##ABBREV *) p; \ -} \ - \ -static inline TYPE \ -get_unaligned_##ABBREV(const TYPE *p) \ -{ \ - return unaligned_##ABBREV(p)->x; \ -} \ - \ -static inline void \ -put_unaligned_##ABBREV(TYPE *p, TYPE x) \ -{ \ - unaligned_##ABBREV(p)->x = x; \ -} - -GCC_UNALIGNED_ACCESSORS(uint16_t, u16); -GCC_UNALIGNED_ACCESSORS(uint32_t, u32); -GCC_UNALIGNED_ACCESSORS(uint64_t, u64__); /* Special case: see below. */ - -GCC_UNALIGNED_ACCESSORS(ovs_be16, be16); -GCC_UNALIGNED_ACCESSORS(ovs_be32, be32); -GCC_UNALIGNED_ACCESSORS(ovs_be64, be64); -#else -/* Generic implementations. */ - -static inline uint16_t get_unaligned_u16(const uint16_t *p_) -{ - const uint8_t *p = (const uint8_t *) p_; - return ntohs((p[0] << 8) | p[1]); -} - -static inline void put_unaligned_u16(uint16_t *p_, uint16_t x_) -{ - uint8_t *p = (uint8_t *) p_; - uint16_t x = ntohs(x_); - - p[0] = x >> 8; - p[1] = x; -} - -static inline uint32_t get_unaligned_u32(const uint32_t *p_) -{ - const uint8_t *p = (const uint8_t *) p_; - return ntohl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); -} - -static inline void put_unaligned_u32(uint32_t *p_, uint32_t x_) -{ - uint8_t *p = (uint8_t *) p_; - uint32_t x = ntohl(x_); - - p[0] = x >> 24; - p[1] = x >> 16; - p[2] = x >> 8; - p[3] = x; -} - -static inline uint64_t get_unaligned_u64__(const uint64_t *p_) -{ - const uint8_t *p = (const uint8_t *) p_; - return ntohll(((uint64_t) p[0] << 56) - | ((uint64_t) p[1] << 48) - | ((uint64_t) p[2] << 40) - | ((uint64_t) p[3] << 32) - | (p[4] << 24) - | (p[5] << 16) - | (p[6] << 8) - | p[7]); -} - -static inline void put_unaligned_u64__(uint64_t *p_, uint64_t x_) -{ - uint8_t *p = (uint8_t *) p_; - uint64_t x = ntohll(x_); - - p[0] = x >> 56; - p[1] = x >> 48; - p[2] = x >> 40; - p[3] = x >> 32; - p[4] = x >> 24; - p[5] = x >> 16; - p[6] = x >> 8; - p[7] = x; -} - -/* Only sparse cares about the difference between uint_t and ovs_be, and - * that takes the GCC branch, so there's no point in working too hard on these - * accessors. */ -#define get_unaligned_be16 get_unaligned_u16 -#define get_unaligned_be32 get_unaligned_u32 -#define put_unaligned_be16 put_unaligned_u16 -#define put_unaligned_be32 put_unaligned_u32 -#define put_unaligned_be64 put_unaligned_u64 - -/* We do not #define get_unaligned_be64 as for the other be functions above, - * because such a definition would mean that get_unaligned_be64() would have a - * different interface in each branch of the #if: with GCC it would take a - * "ovs_be64 *", with other compilers any pointer-to-64-bit-type (but not void - * *). The latter means code like "get_unaligned_be64(ofpbuf_data(b))" would - * work with GCC but not with other compilers, which is surprising and - * undesirable. Hence this wrapper function. */ -static inline ovs_be64 -get_unaligned_be64(const ovs_be64 *p) -{ - return get_unaligned_u64(p); -} -#endif - -/* Stores 'x' at possibly misaligned address 'p'. - * - * put_unaligned_u64() could be overloaded in the same way as - * get_unaligned_u64(), but so far it has not proven necessary. - */ -static inline void -put_unaligned_u64(uint64_t *p, uint64_t x) -{ - put_unaligned_u64__(p, x); -} - -/* Returns the value in 'x'. */ -static inline uint32_t -get_16aligned_u32(const ovs_16aligned_u32 *x) -{ - return ((uint32_t) x->hi << 16) | x->lo; -} - -/* Stores 'value' in 'x'. */ -static inline void -put_16aligned_u32(ovs_16aligned_u32 *x, uint32_t value) -{ - x->hi = value >> 16; - x->lo = value; -} - -/* Returns the value in 'x'. */ -static inline uint64_t -get_32aligned_u64(const ovs_32aligned_u64 *x) -{ - return ((uint64_t) x->hi << 32) | x->lo; -} - -/* Stores 'value' in 'x'. */ -static inline void -put_32aligned_u64(ovs_32aligned_u64 *x, uint64_t value) -{ - x->hi = value >> 32; - x->lo = value; -} - -/* Returns the value in 'x'. */ -static inline ovs_u128 -get_32aligned_u128(const ovs_32aligned_u128 *x) -{ - ovs_u128 u; - u.u32[0] = x->u32[0]; - u.u32[1] = x->u32[1]; - u.u32[2] = x->u32[2]; - u.u32[3] = x->u32[3]; - return u; -} - -/* Stores 'value' in 'x'. */ -static inline void -put_32aligned_u128(ovs_32aligned_u128 *x, ovs_u128 value) -{ - x->u32[0] = value.u32[0]; - x->u32[1] = value.u32[1]; - x->u32[2] = value.u32[2]; - x->u32[3] = value.u32[3]; -} - -#ifndef __CHECKER__ -/* Returns the value of 'x'. */ -static inline ovs_be32 -get_16aligned_be32(const ovs_16aligned_be32 *x) -{ -#ifdef WORDS_BIGENDIAN - return ((ovs_be32) x->hi << 16) | x->lo; -#else - return ((ovs_be32) x->lo << 16) | x->hi; -#endif -} - -/* Stores network byte order 'value' into 'x'. */ -static inline void -put_16aligned_be32(ovs_16aligned_be32 *x, ovs_be32 value) -{ -#if WORDS_BIGENDIAN - x->hi = value >> 16; - x->lo = value; -#else - x->hi = value; - x->lo = value >> 16; -#endif -} - -/* Returns the value of 'x'. */ -static inline ovs_be64 -get_32aligned_be64(const ovs_32aligned_be64 *x) -{ -#ifdef WORDS_BIGENDIAN - return ((ovs_be64) x->hi << 32) | x->lo; -#else - return ((ovs_be64) x->lo << 32) | x->hi; -#endif -} - -/* Stores network byte order 'value' into 'x'. */ -static inline void -put_32aligned_be64(ovs_32aligned_be64 *x, ovs_be64 value) -{ -#if WORDS_BIGENDIAN - x->hi = value >> 32; - x->lo = value; -#else - x->hi = value; - x->lo = value >> 32; -#endif -} - -/* Returns the value of 'x'. */ -static inline ovs_be128 -get_32aligned_be128(const ovs_32aligned_be128 *x) -{ - ovs_be128 u; - u.be32[0] = x->be32[0]; - u.be32[1] = x->be32[1]; - u.be32[2] = x->be32[2]; - u.be32[3] = x->be32[3]; - return u; -} - -/* Stores network byte order 'value' into 'x'. */ -static inline void -put_32aligned_be128(ovs_32aligned_be128 *x, ovs_be128 value) -{ - x->be32[0] = value.be32[0]; - x->be32[1] = value.be32[1]; - x->be32[2] = value.be32[2]; - x->be32[3] = value.be32[3]; -} -#else /* __CHECKER__ */ -/* Making sparse happy with these functions also makes them unreadable, so - * don't bother to show it their implementations. */ -ovs_be32 get_16aligned_be32(const ovs_16aligned_be32 *); -void put_16aligned_be32(ovs_16aligned_be32 *, ovs_be32); -ovs_be64 get_32aligned_be64(const ovs_32aligned_be64 *); -void put_32aligned_be64(ovs_32aligned_be64 *, ovs_be64); -ovs_be128 get_32aligned_be128(const ovs_32aligned_be128 *); -void put_32aligned_be128(ovs_32aligned_be128 *, ovs_be128); -#endif - -#endif /* unaligned.h */ Index: openvswitch-2.17.2/include/internal/unaligned.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/unaligned.h @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2010, 2011, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UNALIGNED_H +#define UNALIGNED_H 1 + +#include +#include "internal/byte-order.h" +#include "openvswitch/types.h" +#include "openvswitch/type-props.h" +#include "internal/util.h" + +/* Public API. */ +static inline uint16_t get_unaligned_u16(const uint16_t *); +static inline uint32_t get_unaligned_u32(const uint32_t *); +static inline void put_unaligned_u16(uint16_t *, uint16_t); +static inline void put_unaligned_u32(uint32_t *, uint32_t); +static inline void put_unaligned_u64(uint64_t *, uint64_t); + +static inline ovs_be16 get_unaligned_be16(const ovs_be16 *); +static inline ovs_be32 get_unaligned_be32(const ovs_be32 *); +static inline ovs_be64 get_unaligned_be64(const ovs_be64 *); +static inline void put_unaligned_be16(ovs_be16 *, ovs_be16); +static inline void put_unaligned_be32(ovs_be32 *, ovs_be32); +static inline void put_unaligned_be64(ovs_be64 *, ovs_be64); + +/* uint64_t get_unaligned_u64(uint64_t *p); + * + * Returns the value of the possibly misaligned uint64_t at 'p'. 'p' may + * actually be any type that points to a 64-bit integer. That is, on Unix-like + * 32-bit ABIs, it may point to an "unsigned long long int", and on Unix-like + * 64-bit ABIs, it may point to an "unsigned long int" or an "unsigned long + * long int". + * + * This is special-cased because on some Linux targets, the kernel __u64 is + * unsigned long long int and the userspace uint64_t is unsigned long int, so + * that any single function prototype would fail to accept one or the other. + * + * Below, "sizeof (*(P) % 1)" verifies that *P has an integer type, since + * operands to % must be integers. + */ +#define get_unaligned_u64(P) \ + (BUILD_ASSERT(sizeof *(P) == 8), \ + BUILD_ASSERT_GCCONLY(!TYPE_IS_SIGNED(typeof(*(P)))), \ + (void) sizeof (*(P) % 1), \ + get_unaligned_u64__((const uint64_t *) (P))) + +#ifdef __GNUC__ +/* GCC implementations. */ +#define GCC_UNALIGNED_ACCESSORS(TYPE, ABBREV) \ +struct unaligned_##ABBREV { \ + TYPE x __attribute__((__packed__)); \ +}; \ +static inline struct unaligned_##ABBREV * \ +unaligned_##ABBREV(const TYPE *p) \ +{ \ + return (struct unaligned_##ABBREV *) p; \ +} \ + \ +static inline TYPE \ +get_unaligned_##ABBREV(const TYPE *p) \ +{ \ + return unaligned_##ABBREV(p)->x; \ +} \ + \ +static inline void \ +put_unaligned_##ABBREV(TYPE *p, TYPE x) \ +{ \ + unaligned_##ABBREV(p)->x = x; \ +} + +GCC_UNALIGNED_ACCESSORS(uint16_t, u16); +GCC_UNALIGNED_ACCESSORS(uint32_t, u32); +GCC_UNALIGNED_ACCESSORS(uint64_t, u64__); /* Special case: see below. */ + +GCC_UNALIGNED_ACCESSORS(ovs_be16, be16); +GCC_UNALIGNED_ACCESSORS(ovs_be32, be32); +GCC_UNALIGNED_ACCESSORS(ovs_be64, be64); +#else +/* Generic implementations. */ + +static inline uint16_t get_unaligned_u16(const uint16_t *p_) +{ + const uint8_t *p = (const uint8_t *) p_; + return ntohs((p[0] << 8) | p[1]); +} + +static inline void put_unaligned_u16(uint16_t *p_, uint16_t x_) +{ + uint8_t *p = (uint8_t *) p_; + uint16_t x = ntohs(x_); + + p[0] = x >> 8; + p[1] = x; +} + +static inline uint32_t get_unaligned_u32(const uint32_t *p_) +{ + const uint8_t *p = (const uint8_t *) p_; + return ntohl((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +} + +static inline void put_unaligned_u32(uint32_t *p_, uint32_t x_) +{ + uint8_t *p = (uint8_t *) p_; + uint32_t x = ntohl(x_); + + p[0] = x >> 24; + p[1] = x >> 16; + p[2] = x >> 8; + p[3] = x; +} + +static inline uint64_t get_unaligned_u64__(const uint64_t *p_) +{ + const uint8_t *p = (const uint8_t *) p_; + return ntohll(((uint64_t) p[0] << 56) + | ((uint64_t) p[1] << 48) + | ((uint64_t) p[2] << 40) + | ((uint64_t) p[3] << 32) + | (p[4] << 24) + | (p[5] << 16) + | (p[6] << 8) + | p[7]); +} + +static inline void put_unaligned_u64__(uint64_t *p_, uint64_t x_) +{ + uint8_t *p = (uint8_t *) p_; + uint64_t x = ntohll(x_); + + p[0] = x >> 56; + p[1] = x >> 48; + p[2] = x >> 40; + p[3] = x >> 32; + p[4] = x >> 24; + p[5] = x >> 16; + p[6] = x >> 8; + p[7] = x; +} + +/* Only sparse cares about the difference between uint_t and ovs_be, and + * that takes the GCC branch, so there's no point in working too hard on these + * accessors. */ +#define get_unaligned_be16 get_unaligned_u16 +#define get_unaligned_be32 get_unaligned_u32 +#define put_unaligned_be16 put_unaligned_u16 +#define put_unaligned_be32 put_unaligned_u32 +#define put_unaligned_be64 put_unaligned_u64 + +/* We do not #define get_unaligned_be64 as for the other be functions above, + * because such a definition would mean that get_unaligned_be64() would have a + * different interface in each branch of the #if: with GCC it would take a + * "ovs_be64 *", with other compilers any pointer-to-64-bit-type (but not void + * *). The latter means code like "get_unaligned_be64(ofpbuf_data(b))" would + * work with GCC but not with other compilers, which is surprising and + * undesirable. Hence this wrapper function. */ +static inline ovs_be64 +get_unaligned_be64(const ovs_be64 *p) +{ + return get_unaligned_u64(p); +} +#endif + +/* Stores 'x' at possibly misaligned address 'p'. + * + * put_unaligned_u64() could be overloaded in the same way as + * get_unaligned_u64(), but so far it has not proven necessary. + */ +static inline void +put_unaligned_u64(uint64_t *p, uint64_t x) +{ + put_unaligned_u64__(p, x); +} + +/* Returns the value in 'x'. */ +static inline uint32_t +get_16aligned_u32(const ovs_16aligned_u32 *x) +{ + return ((uint32_t) x->hi << 16) | x->lo; +} + +/* Stores 'value' in 'x'. */ +static inline void +put_16aligned_u32(ovs_16aligned_u32 *x, uint32_t value) +{ + x->hi = value >> 16; + x->lo = value; +} + +/* Returns the value in 'x'. */ +static inline uint64_t +get_32aligned_u64(const ovs_32aligned_u64 *x) +{ + return ((uint64_t) x->hi << 32) | x->lo; +} + +/* Stores 'value' in 'x'. */ +static inline void +put_32aligned_u64(ovs_32aligned_u64 *x, uint64_t value) +{ + x->hi = value >> 32; + x->lo = value; +} + +/* Returns the value in 'x'. */ +static inline ovs_u128 +get_32aligned_u128(const ovs_32aligned_u128 *x) +{ + ovs_u128 u; + u.u32[0] = x->u32[0]; + u.u32[1] = x->u32[1]; + u.u32[2] = x->u32[2]; + u.u32[3] = x->u32[3]; + return u; +} + +/* Stores 'value' in 'x'. */ +static inline void +put_32aligned_u128(ovs_32aligned_u128 *x, ovs_u128 value) +{ + x->u32[0] = value.u32[0]; + x->u32[1] = value.u32[1]; + x->u32[2] = value.u32[2]; + x->u32[3] = value.u32[3]; +} + +#ifndef __CHECKER__ +/* Returns the value of 'x'. */ +static inline ovs_be32 +get_16aligned_be32(const ovs_16aligned_be32 *x) +{ +#ifdef WORDS_BIGENDIAN + return ((ovs_be32) x->hi << 16) | x->lo; +#else + return ((ovs_be32) x->lo << 16) | x->hi; +#endif +} + +/* Stores network byte order 'value' into 'x'. */ +static inline void +put_16aligned_be32(ovs_16aligned_be32 *x, ovs_be32 value) +{ +#if WORDS_BIGENDIAN + x->hi = value >> 16; + x->lo = value; +#else + x->hi = value; + x->lo = value >> 16; +#endif +} + +/* Returns the value of 'x'. */ +static inline ovs_be64 +get_32aligned_be64(const ovs_32aligned_be64 *x) +{ +#ifdef WORDS_BIGENDIAN + return ((ovs_be64) x->hi << 32) | x->lo; +#else + return ((ovs_be64) x->lo << 32) | x->hi; +#endif +} + +/* Stores network byte order 'value' into 'x'. */ +static inline void +put_32aligned_be64(ovs_32aligned_be64 *x, ovs_be64 value) +{ +#if WORDS_BIGENDIAN + x->hi = value >> 32; + x->lo = value; +#else + x->hi = value; + x->lo = value >> 32; +#endif +} + +/* Returns the value of 'x'. */ +static inline ovs_be128 +get_32aligned_be128(const ovs_32aligned_be128 *x) +{ + ovs_be128 u; + u.be32[0] = x->be32[0]; + u.be32[1] = x->be32[1]; + u.be32[2] = x->be32[2]; + u.be32[3] = x->be32[3]; + return u; +} + +/* Stores network byte order 'value' into 'x'. */ +static inline void +put_32aligned_be128(ovs_32aligned_be128 *x, ovs_be128 value) +{ + x->be32[0] = value.be32[0]; + x->be32[1] = value.be32[1]; + x->be32[2] = value.be32[2]; + x->be32[3] = value.be32[3]; +} +#else /* __CHECKER__ */ +/* Making sparse happy with these functions also makes them unreadable, so + * don't bother to show it their implementations. */ +ovs_be32 get_16aligned_be32(const ovs_16aligned_be32 *); +void put_16aligned_be32(ovs_16aligned_be32 *, ovs_be32); +ovs_be64 get_32aligned_be64(const ovs_32aligned_be64 *); +void put_32aligned_be64(ovs_32aligned_be64 *, ovs_be64); +ovs_be128 get_32aligned_be128(const ovs_32aligned_be128 *); +void put_32aligned_be128(ovs_32aligned_be128 *, ovs_be128); +#endif + +#endif /* unaligned.h */ Index: openvswitch-2.17.2/include/internal/util.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/util.h @@ -0,0 +1,603 @@ +/* + * 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. + */ + +#ifndef UTIL_H +#define UTIL_H 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "openvswitch/compiler.h" +#include "openvswitch/util.h" +#if defined(__aarch64__) && __GNUC__ >= 6 +#include +#endif + +extern char *program_name; + +#define __ARRAY_SIZE_NOCHECK(ARRAY) (sizeof(ARRAY) / sizeof((ARRAY)[0])) +#if __GNUC__ && !defined(__cplusplus) +/* return 0 for array types, 1 otherwise */ +#define __ARRAY_CHECK(ARRAY) \ + !__builtin_types_compatible_p(typeof(ARRAY), typeof(&ARRAY[0])) + +/* compile-time fail if not array */ +#define __ARRAY_FAIL(ARRAY) (sizeof(char[-2*!__ARRAY_CHECK(ARRAY)])) +#define __ARRAY_SIZE(ARRAY) \ + __builtin_choose_expr(__ARRAY_CHECK(ARRAY), \ + __ARRAY_SIZE_NOCHECK(ARRAY), __ARRAY_FAIL(ARRAY)) +#elif defined(__cplusplus) +#define __ARRAY_SIZE(ARRAY) ( \ + 0 * sizeof(reinterpret_cast(ARRAY)) + \ + 0 * sizeof(::Bad_arg_to_ARRAY_SIZE::check_type((ARRAY), &(ARRAY))) + \ + sizeof(ARRAY) / sizeof((ARRAY)[0]) ) + +struct Bad_arg_to_ARRAY_SIZE { + class Is_pointer; + class Is_array {}; + template + static Is_pointer check_type(const T *, const T * const *); + static Is_array check_type(const void *, const void *); +}; +#else +#define __ARRAY_SIZE(ARRAY) __ARRAY_SIZE_NOCHECK(ARRAY) +#endif + + +/* This system's cache line size, in bytes. + * Being wrong hurts performance but not correctness. */ +#define CACHE_LINE_SIZE 64 +BUILD_ASSERT_DECL(IS_POW2(CACHE_LINE_SIZE)); + +/* Cacheline marking is typically done using zero-sized array. + * However MSVC doesn't like zero-sized array in struct/union. + * C4200: https://msdn.microsoft.com/en-us/library/79wf64bc.aspx + */ +typedef uint8_t OVS_CACHE_LINE_MARKER[1]; + +static inline void +ovs_prefetch_range(const void *start, size_t size) +{ + const char *addr = (const char *)start; + size_t ofs; + + for (ofs = 0; ofs < size; ofs += CACHE_LINE_SIZE) { + OVS_PREFETCH(addr + ofs); + } +} + +#ifndef MIN +#define MIN(X, Y) ((X) < (Y) ? (X) : (Y)) +#endif + +#ifndef MAX +#define MAX(X, Y) ((X) > (Y) ? (X) : (Y)) +#endif + +/* Comparisons for ints with modular arithmetic */ +#define INT_MOD_LT(a,b) ((int) ((a)-(b)) < 0) +#define INT_MOD_LEQ(a,b) ((int) ((a)-(b)) <= 0) +#define INT_MOD_GT(a,b) ((int) ((a)-(b)) > 0) +#define INT_MOD_GEQ(a,b) ((int) ((a)-(b)) >= 0) + +#define INT_MOD_MIN(a, b) ((INT_MOD_LT(a, b)) ? (a) : (b)) +#define INT_MOD_MAX(a, b) ((INT_MOD_GT(a, b)) ? (a) : (b)) + +#define OVS_NOT_REACHED() abort() + +/* Joins two token expanding the arguments if they are macros. + * + * For token concatenation the circumlocution is needed for the + * expansion. */ +#define OVS_JOIN2(X, Y) X##Y +#define OVS_JOIN(X, Y) OVS_JOIN2(X, Y) + +/* Use "%"PRIuSIZE to format size_t with printf(). */ +#ifdef _WIN32 +#define PRIdSIZE "Id" +#define PRIiSIZE "Ii" +#define PRIoSIZE "Io" +#define PRIuSIZE "Iu" +#define PRIxSIZE "Ix" +#define PRIXSIZE "IX" +#else +#define PRIdSIZE "zd" +#define PRIiSIZE "zi" +#define PRIoSIZE "zo" +#define PRIuSIZE "zu" +#define PRIxSIZE "zx" +#define PRIXSIZE "zX" +#endif + +#ifndef _WIN32 +typedef uint32_t HANDLE; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define set_program_name(name) \ + ovs_set_program_name(name, OVS_PACKAGE_VERSION) + +const char *get_subprogram_name(void); + void set_subprogram_name(const char *); + +unsigned int get_page_size(void); +long long int get_boot_time(void); + +void ctl_timeout_setup(unsigned int secs); + +void ovs_print_version(uint8_t min_ofp, uint8_t max_ofp); + +void set_memory_locked(void); +bool memory_locked(void); + +OVS_NO_RETURN void out_of_memory(void); + +/* Allocation wrappers that abort if memory is exhausted. */ +void *xmalloc(size_t) OVS_MALLOC_LIKE; +void *xcalloc(size_t, size_t) OVS_MALLOC_LIKE; +void *xzalloc(size_t) OVS_MALLOC_LIKE; +void *xrealloc(void *, size_t); +void *xmemdup(const void *, size_t) OVS_MALLOC_LIKE; +char *xmemdup0(const char *, size_t) OVS_MALLOC_LIKE; +char *xstrdup(const char *) OVS_MALLOC_LIKE; +char *nullable_xstrdup(const char *) OVS_MALLOC_LIKE; +bool nullable_string_is_equal(const char *a, const char *b); +char *xasprintf(const char *format, ...) OVS_PRINTF_FORMAT(1, 2) OVS_MALLOC_LIKE; +char *xvasprintf(const char *format, va_list) OVS_PRINTF_FORMAT(1, 0) OVS_MALLOC_LIKE; +void *x2nrealloc(void *p, size_t *n, size_t s); + +/* Allocation wrappers for specialized situations where coverage counters + * cannot be used. */ +void *xmalloc__(size_t) OVS_MALLOC_LIKE; +void *xcalloc__(size_t, size_t) OVS_MALLOC_LIKE; +void *xzalloc__(size_t) OVS_MALLOC_LIKE; +void *xrealloc__(void *, size_t); + +void *xmalloc_cacheline(size_t) OVS_MALLOC_LIKE; +void *xzalloc_cacheline(size_t) OVS_MALLOC_LIKE; +void free_cacheline(void *); + +void ovs_strlcpy(char *dst, const char *src, size_t size); +void ovs_strzcpy(char *dst, const char *src, size_t size); + +int string_ends_with(const char *str, const char *suffix); + +void *xmalloc_pagealign(size_t) OVS_MALLOC_LIKE; +void free_pagealign(void *); +void *xmalloc_size_align(size_t, size_t) OVS_MALLOC_LIKE; +void free_size_align(void *); + +/* The C standards say that neither the 'dst' nor 'src' argument to + * memcpy() may be null, even if 'n' is zero. This wrapper tolerates + * the null case. */ +static inline void +nullable_memcpy(void *dst, const void *src, size_t n) +{ + if (n) { + memcpy(dst, src, n); + } +} + +/* The C standards say that the 'dst' argument to memset may not be + * null, even if 'n' is zero. This wrapper tolerates the null case. */ +static inline void +nullable_memset(void *dst, int c, size_t n) +{ + if (n) { + memset(dst, c, n); + } +} + +/* Copy string SRC to DST, but no more bytes than the shorter of DST or SRC. + * DST and SRC must both be char arrays, not pointers, and with GNU C, this + * raises a compiler error if either DST or SRC is a pointer instead of an + * array. */ +#define ovs_strlcpy_arrays(DST, SRC) \ + ovs_strlcpy(DST, SRC, MIN(ARRAY_SIZE(DST), ARRAY_SIZE(SRC))) + +OVS_NO_RETURN void ovs_abort(int err_no, const char *format, ...) + OVS_PRINTF_FORMAT(2, 3); +OVS_NO_RETURN void ovs_abort_valist(int err_no, const char *format, va_list) + OVS_PRINTF_FORMAT(2, 0); +OVS_NO_RETURN void ovs_fatal(int err_no, const char *format, ...) + OVS_PRINTF_FORMAT(2, 3); +OVS_NO_RETURN void ovs_fatal_valist(int err_no, const char *format, va_list) + OVS_PRINTF_FORMAT(2, 0); +void ovs_error(int err_no, const char *format, ...) OVS_PRINTF_FORMAT(2, 3); +void ovs_error_valist(int err_no, const char *format, va_list) + OVS_PRINTF_FORMAT(2, 0); +const char *ovs_retval_to_string(int); +const char *ovs_strerror(int); +void ovs_hex_dump(FILE *, const void *, size_t, uintptr_t offset, bool ascii); + +bool str_to_int(const char *, int base, int *); +bool str_to_long(const char *, int base, long *); +bool str_to_llong(const char *, int base, long long *); +bool str_to_llong_with_tail(const char *, char **, int base, long long *); +bool str_to_uint(const char *, int base, unsigned int *); +bool str_to_ullong(const char *, int base, unsigned long long *); +bool str_to_llong_range(const char *, int base, long long *, long long *); + +bool ovs_scan(const char *s, const char *format, ...) OVS_SCANF_FORMAT(2, 3); +bool ovs_scan_len(const char *s, int *n, const char *format, ...); + +bool str_to_double(const char *, double *); + +int hexit_value(unsigned char c); +uintmax_t hexits_value(const char *s, size_t n, bool *ok); + +int parse_int_string(const char *s, uint8_t *valuep, int field_width, + char **tail); + +const char *english_list_delimiter(size_t index, size_t total); + +char *get_cwd(void); +#ifndef _WIN32 +char *dir_name(const char *file_name); +char *base_name(const char *file_name); +#endif +char *abs_file_name(const char *dir, const char *file_name); +bool is_file_name_absolute(const char *); + +char *follow_symlinks(const char *filename); + +void ignore(bool x OVS_UNUSED); + +/* Bitwise tests. */ + +/* Returns the number of trailing 0-bits in 'n'. Undefined if 'n' == 0. */ +#if __GNUC__ >= 4 +static inline int +raw_ctz(uint64_t n) +{ + /* With GCC 4.7 on 32-bit x86, if a 32-bit integer is passed as 'n', using + * a plain __builtin_ctzll() here always generates an out-of-line function + * call. The test below helps it to emit a single 'bsf' instruction. */ + return (__builtin_constant_p(n <= UINT32_MAX) && n <= UINT32_MAX + ? __builtin_ctz(n) + : __builtin_ctzll(n)); +} + +static inline int +raw_clz64(uint64_t n) +{ + return __builtin_clzll(n); +} +#elif _MSC_VER +static inline int +raw_ctz(uint64_t n) +{ +#ifdef _WIN64 + unsigned long r = 0; + _BitScanForward64(&r, n); + return r; +#else + unsigned long low = n, high, r = 0; + if (_BitScanForward(&r, low)) { + return r; + } + high = n >> 32; + _BitScanForward(&r, high); + return r + 32; +#endif +} + +static inline int +raw_clz64(uint64_t n) +{ +#ifdef _WIN64 + unsigned long r = 0; + _BitScanReverse64(&r, n); + return 63 - r; +#else + unsigned long low, high = n >> 32, r = 0; + if (_BitScanReverse(&r, high)) { + return 31 - r; + } + low = n; + _BitScanReverse(&r, low); + return 63 - r; +#endif +} +#else +/* Defined in util.c. */ +int raw_ctz(uint64_t n); +int raw_clz64(uint64_t n); +#endif + +/* Returns the number of trailing 0-bits in 'n', or 32 if 'n' is 0. */ +static inline int +ctz32(uint32_t n) +{ + return n ? raw_ctz(n) : 32; +} + +/* Returns the number of trailing 0-bits in 'n', or 64 if 'n' is 0. */ +static inline int +ctz64(uint64_t n) +{ + return n ? raw_ctz(n) : 64; +} + +/* Returns the number of leading 0-bits in 'n', or 32 if 'n' is 0. */ +static inline int +clz32(uint32_t n) +{ + return n ? raw_clz64(n) - 32 : 32; +} + +/* Returns the number of leading 0-bits in 'n', or 64 if 'n' is 0. */ +static inline int +clz64(uint64_t n) +{ + return n ? raw_clz64(n) : 64; +} + +/* Given a word 'n', calculates floor(log_2('n')). This is equivalent + * to finding the bit position of the most significant one bit in 'n'. It is + * an error to call this function with 'n' == 0. */ +static inline int +log_2_floor(uint64_t n) +{ + return 63 - raw_clz64(n); +} + +/* Given a word 'n', calculates ceil(log_2('n')). It is an error to + * call this function with 'n' == 0. */ +static inline int +log_2_ceil(uint64_t n) +{ + return log_2_floor(n) + !is_pow2(n); +} + +/* unsigned int count_1bits(uint64_t x): + * + * Returns the number of 1-bits in 'x', between 0 and 64 inclusive. */ +#if UINTPTR_MAX == UINT64_MAX +static inline unsigned int +count_1bits(uint64_t x) +{ +#if (__GNUC__ >= 4 && __POPCNT__) || (defined(__aarch64__) && __GNUC__ >= 7) + return __builtin_popcountll(x); +#elif defined(__aarch64__) && __GNUC__ >= 6 + return vaddv_u8(vcnt_u8(vcreate_u8(x))); +#else + /* This portable implementation is the fastest one we know of for 64 + * bits, and about 3x faster than GCC 4.7 __builtin_popcountll(). */ + const uint64_t h55 = UINT64_C(0x5555555555555555); + const uint64_t h33 = UINT64_C(0x3333333333333333); + const uint64_t h0F = UINT64_C(0x0F0F0F0F0F0F0F0F); + const uint64_t h01 = UINT64_C(0x0101010101010101); + x -= (x >> 1) & h55; /* Count of each 2 bits in-place. */ + x = (x & h33) + ((x >> 2) & h33); /* Count of each 4 bits in-place. */ + x = (x + (x >> 4)) & h0F; /* Count of each 8 bits in-place. */ + return (x * h01) >> 56; /* Sum of all bytes. */ +#endif +} +#else /* Not 64-bit. */ +#if __GNUC__ >= 4 && __POPCNT__ +static inline unsigned int +count_1bits_32__(uint32_t x) +{ + return __builtin_popcount(x); +} +#else +#define NEED_COUNT_1BITS_8 1 +extern const uint8_t count_1bits_8[256]; +static inline unsigned int +count_1bits_32__(uint32_t x) +{ + /* This portable implementation is the fastest one we know of for 32 bits, + * and faster than GCC __builtin_popcount(). */ + return (count_1bits_8[x & 0xff] + + count_1bits_8[(x >> 8) & 0xff] + + count_1bits_8[(x >> 16) & 0xff] + + count_1bits_8[x >> 24]); +} +#endif +static inline unsigned int +count_1bits(uint64_t x) +{ + return count_1bits_32__(x) + count_1bits_32__(x >> 32); +} +#endif + +/* Returns the rightmost 1-bit in 'x' (e.g. 01011000 => 00001000), or 0 if 'x' + * is 0. */ +static inline uintmax_t +rightmost_1bit(uintmax_t x) +{ + return x & -x; +} + +/* Returns 'x' with its rightmost 1-bit changed to a zero (e.g. 01011000 => + * 01010000), or 0 if 'x' is 0. */ +static inline uintmax_t +zero_rightmost_1bit(uintmax_t x) +{ + return x & (x - 1); +} + +/* Returns the index of the rightmost 1-bit in 'x' (e.g. 01011000 => 3), or an + * undefined value if 'x' is 0. */ +static inline int +rightmost_1bit_idx(uint64_t x) +{ + return ctz64(x); +} + +/* Returns the index of the leftmost 1-bit in 'x' (e.g. 01011000 => 6), or an + * undefined value if 'x' is 0. */ +static inline uint32_t +leftmost_1bit_idx(uint64_t x) +{ + return log_2_floor(x); +} + +/* Return a ovs_be32 prefix in network byte order with 'plen' highest bits set. + * Shift with 32 is undefined behavior, but we rather use 64-bit shift than + * compare. */ +static inline ovs_be32 be32_prefix_mask(int plen) +{ + return htonl((uint64_t)UINT32_MAX << (32 - plen)); +} + +/* Returns true if the 1-bits in 'super' are a superset of the 1-bits in 'sub', + * false otherwise. */ +static inline bool +uint_is_superset(uintmax_t super, uintmax_t sub) +{ + return (super & sub) == sub; +} + +/* Returns true if the 1-bits in 'super' are a superset of the 1-bits in 'sub', + * false otherwise. */ +static inline bool +be16_is_superset(ovs_be16 super, ovs_be16 sub) +{ + return (super & sub) == sub; +} + +/* Returns true if the 1-bits in 'super' are a superset of the 1-bits in 'sub', + * false otherwise. */ +static inline bool +be32_is_superset(ovs_be32 super, ovs_be32 sub) +{ + return (super & sub) == sub; +} + +/* Returns true if the 1-bits in 'super' are a superset of the 1-bits in 'sub', + * false otherwise. */ +static inline bool +be64_is_superset(ovs_be64 super, ovs_be64 sub) +{ + return (super & sub) == sub; +} + +bool is_all_zeros(const void *, size_t); +bool is_all_ones(const void *, size_t); +bool is_all_byte(const void *, size_t, uint8_t byte); +void or_bytes(void *dst, const void *src, size_t n); +void bitwise_copy(const void *src, unsigned int src_len, unsigned int src_ofs, + void *dst, unsigned int dst_len, unsigned int dst_ofs, + unsigned int n_bits); +void bitwise_zero(void *dst_, unsigned int dst_len, unsigned dst_ofs, + unsigned int n_bits); +void bitwise_one(void *dst_, unsigned int dst_len, unsigned dst_ofs, + unsigned int n_bits); +bool bitwise_is_all_zeros(const void *, unsigned int len, unsigned int ofs, + unsigned int n_bits); +unsigned int bitwise_scan(const void *, unsigned int len, + bool target, unsigned int start, unsigned int end); +int bitwise_rscan(const void *, unsigned int len, bool target, + int start, int end); +void bitwise_put(uint64_t value, + void *dst, unsigned int dst_len, unsigned int dst_ofs, + unsigned int n_bits); +uint64_t bitwise_get(const void *src, unsigned int src_len, + unsigned int src_ofs, unsigned int n_bits); +bool bitwise_get_bit(const void *src, unsigned int len, unsigned int ofs); +void bitwise_put0(void *dst, unsigned int len, unsigned int ofs); +void bitwise_put1(void *dst, unsigned int len, unsigned int ofs); +void bitwise_put_bit(void *dst, unsigned int len, unsigned int ofs, bool); +void bitwise_toggle_bit(void *dst, unsigned int len, unsigned int ofs); + +/* Returns non-zero if the parameters have equal value. */ +static inline int +ovs_u128_equals(const ovs_u128 a, const ovs_u128 b) +{ + return (a.u64.hi == b.u64.hi) && (a.u64.lo == b.u64.lo); +} + +/* Returns true if 'val' is 0. */ +static inline bool +ovs_u128_is_zero(const ovs_u128 val) +{ + return !(val.u64.hi || val.u64.lo); +} + +/* Returns true if 'val' is all ones. */ +static inline bool +ovs_u128_is_ones(const ovs_u128 val) +{ + return ovs_u128_equals(val, OVS_U128_MAX); +} + +/* Returns non-zero if the parameters have equal value. */ +static inline int +ovs_be128_equals(const ovs_be128 a, const ovs_be128 b) +{ + return (a.be64.hi == b.be64.hi) && (a.be64.lo == b.be64.lo); +} + +/* Returns true if 'val' is 0. */ +static inline bool +ovs_be128_is_zero(const ovs_be128 val) +{ + return !(val.be64.hi || val.be64.lo); +} + +static inline ovs_u128 +ovs_u128_and(const ovs_u128 a, const ovs_u128 b) +{ + ovs_u128 dst; + + dst.u64.hi = a.u64.hi & b.u64.hi; + dst.u64.lo = a.u64.lo & b.u64.lo; + + return dst; +} + +static inline bool +ovs_be128_is_superset(ovs_be128 super, ovs_be128 sub) +{ + return (be64_is_superset(super.be64.hi, sub.be64.hi) && + be64_is_superset(super.be64.lo, sub.be64.lo)); +} + +static inline bool +ovs_u128_is_superset(ovs_u128 super, ovs_u128 sub) +{ + return (uint_is_superset(super.u64.hi, sub.u64.hi) && + uint_is_superset(super.u64.lo, sub.u64.lo)); +} + +void xsleep(unsigned int seconds); +void xnanosleep(uint64_t nanoseconds); + +bool is_stdout_a_tty(void); + +#ifdef _WIN32 + +char *ovs_format_message(int error); +char *ovs_lasterror_to_string(void); +int ftruncate(int fd, off_t length); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* util.h */ Index: openvswitch-2.17.2/lib/versions.h =================================================================== --- openvswitch-2.17.2.orig/lib/versions.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016 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 VERSIONS_H -#define VERSIONS_H 1 - -#include "ovs-atomic.h" -#include "openvswitch/type-props.h" - -typedef uint64_t ovs_version_t; - -#define OVS_VERSION_MIN 0 /* Default version number to use. */ -#define OVS_VERSION_MAX (TYPE_MAXIMUM(ovs_version_t) - 1) -#define OVS_VERSION_NOT_REMOVED TYPE_MAXIMUM(ovs_version_t) - -/* - * OVS_VERSION_NOT_REMOVED has a special meaning for 'remove_version', - * meaning that the rule has been added but not yet removed. - */ -struct versions { - ovs_version_t add_version; /* Version object was added in. */ - ATOMIC(ovs_version_t) remove_version; /* Version object is removed in. */ -}; - -#define VERSIONS_INITIALIZER(ADD, REMOVE) \ - (struct versions){ ADD, ATOMIC_VAR_INIT(REMOVE) } - -static inline void -versions_set_remove_version(struct versions *versions, ovs_version_t version) -{ - atomic_store_relaxed(&versions->remove_version, version); -} - -static inline bool -versions_visible_in_version(const struct versions *versions, - ovs_version_t version) -{ - ovs_version_t remove_version; - - /* C11 does not want to access an atomic via a const object pointer. */ - atomic_read_relaxed(&CONST_CAST(struct versions *, - versions)->remove_version, - &remove_version); - - return versions->add_version <= version && version < remove_version; -} - -static inline bool -versions_is_eventually_invisible(const struct versions *versions) -{ - ovs_version_t remove_version; - - /* C11 does not want to access an atomic via a const object pointer. */ - atomic_read_relaxed(&CONST_CAST(struct versions *, - versions)->remove_version, - &remove_version); - - return remove_version < OVS_VERSION_NOT_REMOVED; -} - -#endif /* VERSIONS_H */ Index: openvswitch-2.17.2/include/internal/versions.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/versions.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 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 VERSIONS_H +#define VERSIONS_H 1 + +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/type-props.h" + +typedef uint64_t ovs_version_t; + +#define OVS_VERSION_MIN 0 /* Default version number to use. */ +#define OVS_VERSION_MAX (TYPE_MAXIMUM(ovs_version_t) - 1) +#define OVS_VERSION_NOT_REMOVED TYPE_MAXIMUM(ovs_version_t) + +/* + * OVS_VERSION_NOT_REMOVED has a special meaning for 'remove_version', + * meaning that the rule has been added but not yet removed. + */ +struct versions { + ovs_version_t add_version; /* Version object was added in. */ + ATOMIC(ovs_version_t) remove_version; /* Version object is removed in. */ +}; + +#define VERSIONS_INITIALIZER(ADD, REMOVE) \ + (struct versions){ ADD, ATOMIC_VAR_INIT(REMOVE) } + +static inline void +versions_set_remove_version(struct versions *versions, ovs_version_t version) +{ + atomic_store_relaxed(&versions->remove_version, version); +} + +static inline bool +versions_visible_in_version(const struct versions *versions, + ovs_version_t version) +{ + ovs_version_t remove_version; + + /* C11 does not want to access an atomic via a const object pointer. */ + atomic_read_relaxed(&CONST_CAST(struct versions *, + versions)->remove_version, + &remove_version); + + return versions->add_version <= version && version < remove_version; +} + +static inline bool +versions_is_eventually_invisible(const struct versions *versions) +{ + ovs_version_t remove_version; + + /* C11 does not want to access an atomic via a const object pointer. */ + atomic_read_relaxed(&CONST_CAST(struct versions *, + versions)->remove_version, + &remove_version); + + return remove_version < OVS_VERSION_NOT_REMOVED; +} + +#endif /* VERSIONS_H */ Index: openvswitch-2.17.2/include/openvswitch/automake.mk =================================================================== --- openvswitch-2.17.2.orig/include/openvswitch/automake.mk +++ openvswitch-2.17.2/include/openvswitch/automake.mk @@ -1,5 +1,7 @@ openvswitchincludedir = $(includedir)/openvswitch openvswitchinclude_HEADERS = \ + include/odp-netlink.h \ + include/odp-netlink-macros.h \ include/openvswitch/compiler.h \ include/openvswitch/dynamic-string.h \ include/openvswitch/hmap.h \ @@ -34,6 +36,20 @@ openvswitchinclude_HEADERS = \ include/openvswitch/ofp-switch.h \ include/openvswitch/ofp-table.h \ include/openvswitch/ofp-util.h \ + include/openvswitch/ovs-atomic.h \ + include/openvswitch/ovs-numa.h \ + include/openvswitch/ovs-rcu.h \ + include/openvswitch/ovs-thread.h \ + include/openvswitch/ovsdb-cs.h \ + include/openvswitch/ovsdb-condition.h \ + include/openvswitch/ovsdb-data.h \ + include/openvswitch/ovsdb-error.h \ + include/openvswitch/ovsdb-idl.h \ + include/openvswitch/ovsdb-idl-provider.h \ + include/openvswitch/ovsdb-map-op.h \ + include/openvswitch/ovsdb-set-op.h \ + include/openvswitch/ovsdb-parser.h \ + include/openvswitch/ovsdb-types.h \ include/openvswitch/packets.h \ include/openvswitch/poll-loop.h \ include/openvswitch/rconn.h \ Index: openvswitch-2.17.2/lib/ovs-atomic.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic.h +++ /dev/null @@ -1,671 +0,0 @@ -/* - * Copyright (c) 2013, 2014, 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. - */ - -#ifndef OVS_ATOMIC_H -#define OVS_ATOMIC_H 1 - -/* Atomic operations. - * - * This library implements atomic operations with an API based on the one - * defined in C11. It includes multiple implementations for compilers and - * libraries with varying degrees of built-in support for C11, including a - * fallback implementation for systems that have pthreads but no other support - * for atomics. - * - * This comment describes the common features of all the implementations. - * - * - * Types - * ===== - * - * The following atomic types are supported as typedefs for atomic versions of - * the listed ordinary types: - * - * ordinary type atomic version - * ------------------- ---------------------- - * bool atomic_bool - * - * char atomic_char - * signed char atomic_schar - * unsigned char atomic_uchar - * - * short atomic_short - * unsigned short atomic_ushort - * - * int atomic_int - * unsigned int atomic_uint - * - * long atomic_long - * unsigned long atomic_ulong - * - * long long atomic_llong - * unsigned long long atomic_ullong - * - * size_t atomic_size_t - * ptrdiff_t atomic_ptrdiff_t - * - * intmax_t atomic_intmax_t - * uintmax_t atomic_uintmax_t - * - * intptr_t atomic_intptr_t - * uintptr_t atomic_uintptr_t - * - * uint8_t atomic_uint8_t (*) - * uint16_t atomic_uint16_t (*) - * uint32_t atomic_uint32_t (*) - * int8_t atomic_int8_t (*) - * int16_t atomic_int16_t (*) - * int32_t atomic_int32_t (*) - * uint64_t atomic_uint64_t (*) - * int64_t atomic_int64_t (*) - * - * (*) Not specified by C11. - * - * Atomic types may also be obtained via ATOMIC(TYPE), e.g. ATOMIC(void *). - * Only basic integer types and pointer types can be made atomic this way, - * e.g. atomic structs are not supported. - * - * The atomic version of a type doesn't necessarily have the same size or - * representation as the ordinary version; for example, atomic_int might be a - * typedef for a struct. The range of an atomic type does match the range of - * the corresponding ordinary type. - * - * C11 says that one may use the _Atomic keyword in place of the typedef name, - * e.g. "_Atomic int" instead of "atomic_int". This library doesn't support - * that. - * - * - * Life Cycle - * ========== - * - * To initialize an atomic variable at its point of definition, use - * ATOMIC_VAR_INIT: - * - * static atomic_int ai = ATOMIC_VAR_INIT(123); - * - * To initialize an atomic variable in code, use atomic_init(): - * - * static atomic_int ai; - * ... - * atomic_init(&ai, 123); - * - * - * Barriers - * ======== - * - * enum memory_order specifies the strictness of a memory barrier. It has the - * following values: - * - * memory_order_relaxed: - * - * Only atomicity is provided, does not imply any memory ordering with - * respect to any other variable (atomic or not). Relaxed accesses to - * the same atomic variable will be performed in the program order. - * The compiler and CPU are free to move memory accesses to other - * variables past the atomic operation. - * - * memory_order_consume: - * - * Memory accesses with data dependency on the result of the consume - * operation (atomic_read_explicit, or a load operation preceding a - * atomic_thread_fence) will not be moved prior to the consume - * barrier. Non-data-dependent loads and stores can be reordered to - * happen before the consume barrier. - * - * RCU is the prime example of the use of the consume barrier: The - * consume barrier guarantees that reads from a RCU protected object - * are performed after the RCU protected pointer is read. A - * corresponding release barrier is used to store the modified RCU - * protected pointer after the RCU protected object has been fully - * constructed. The synchronization between these barriers prevents - * the RCU "consumer" from seeing uninitialized data. - * - * May not be used with atomic_store_explicit(), as consume semantics - * applies only to atomic loads. - * - * memory_order_acquire: - * - * Memory accesses after an acquire barrier cannot be moved before the - * barrier. Memory accesses before an acquire barrier *can* be moved - * after it. - * - * An atomic_thread_fence with memory_order_acquire does not have a - * load operation by itself; it prevents all following memory accesses - * from moving prior to preceding loads. - * - * May not be used with atomic_store_explicit(), as acquire semantics - * applies only to atomic loads. - * - * memory_order_release: - * - * Memory accesses before a release barrier cannot be moved after the - * barrier. Memory accesses after a release barrier *can* be moved - * before it. - * - * An atomic_thread_fence with memory_order_release does not have a - * store operation by itself; it prevents all preceding memory accesses - * from moving past subsequent stores. - * - * May not be used with atomic_read_explicit(), as release semantics - * applies only to atomic stores. - * - * memory_order_acq_rel: - * - * Memory accesses cannot be moved across an acquire-release barrier in - * either direction. - * - * May only be used with atomic read-modify-write operations, as both - * load and store operation is required for acquire-release semantics. - * - * An atomic_thread_fence with memory_order_acq_rel does not have - * either load or store operation by itself; it prevents all following - * memory accesses from moving prior to preceding loads and all - * preceding memory accesses from moving past subsequent stores. - * - * memory_order_seq_cst: - * - * Prevents movement of memory accesses like an acquire-release barrier, - * but whereas acquire-release synchronizes cooperating threads (using - * the same atomic variable), sequential-consistency synchronizes the - * whole system, providing a total order for stores on all atomic - * variables. - * - * OVS atomics require the memory_order to be passed as a compile-time constant - * value, as some compiler implementations may perform poorly if the memory - * order parameter is passed in as a run-time value. - * - * The following functions insert explicit barriers. Most of the other atomic - * functions also include barriers. - * - * void atomic_thread_fence(memory_order order); - * - * Inserts a barrier of the specified type. - * - * For memory_order_relaxed, this is a no-op. - * - * void atomic_signal_fence(memory_order order); - * - * Inserts a barrier of the specified type, but only with respect to - * signal handlers in the same thread as the barrier. This is - * basically a compiler optimization barrier, except for - * memory_order_relaxed, which is a no-op. - * - * - * Atomic Operations - * ================= - * - * In this section, A is an atomic type and C is the corresponding non-atomic - * type. - * - * The "store", "exchange", and "compare_exchange" primitives match C11: - * - * void atomic_store(A *object, C value); - * void atomic_store_explicit(A *object, C value, memory_order); - * - * Atomically stores 'value' into '*object', respecting the given - * memory order (or memory_order_seq_cst for atomic_store()). - * - * bool atomic_compare_exchange_strong(A *object, C *expected, C desired); - * bool atomic_compare_exchange_weak(A *object, C *expected, C desired); - * bool atomic_compare_exchange_strong_explicit(A *object, C *expected, - * C desired, - * memory_order success, - * memory_order failure); - * bool atomic_compare_exchange_weak_explicit(A *object, C *expected, - * C desired, - * memory_order success, - * memory_order failure); - * - * Atomically loads '*object' and compares it with '*expected' and if - * equal, stores 'desired' into '*object' (an atomic read-modify-write - * operation) and returns true, and if non-equal, stores the actual - * value of '*object' into '*expected' (an atomic load operation) and - * returns false. The memory order for the successful case (atomic - * read-modify-write operation) is 'success', and for the unsuccessful - * case (atomic load operation) 'failure'. 'failure' may not be - * stronger than 'success'. - * - * The weak forms may fail (returning false) also when '*object' equals - * '*expected'. The strong form can be implemented by the weak form in - * a loop. Some platforms can implement the weak form more - * efficiently, so it should be used if the application will need to - * loop anyway. - * - * C atomic_exchange(A *object, C desired); - * C atomic_exchange_explicit(A *object, C desired, memory_order); - * - * Atomically stores 'desired' into '*object', returning the value - * previously held. - * - * The following primitives differ from the C11 ones (and have different names) - * because there does not appear to be a way to implement the standard - * primitives in standard C: - * - * void atomic_read(A *src, C *dst); - * void atomic_read_explicit(A *src, C *dst, memory_order); - * - * Atomically loads a value from 'src', writing the value read into - * '*dst', respecting the given memory order (or memory_order_seq_cst - * for atomic_read()). - * - * void atomic_add(A *rmw, C arg, C *orig); - * void atomic_sub(A *rmw, C arg, C *orig); - * void atomic_or(A *rmw, C arg, C *orig); - * void atomic_xor(A *rmw, C arg, C *orig); - * void atomic_and(A *rmw, C arg, C *orig); - * void atomic_add_explicit(A *rmw, C arg, C *orig, memory_order); - * void atomic_sub_explicit(A *rmw, C arg, C *orig, memory_order); - * void atomic_or_explicit(A *rmw, C arg, C *orig, memory_order); - * void atomic_xor_explicit(A *rmw, C arg, C *orig, memory_order); - * void atomic_and_explicit(A *rmw, C arg, C *orig, memory_order); - * - * Atomically applies the given operation, with 'arg' as the second - * operand, to '*rmw', and stores the original value of '*rmw' into - * '*orig', respecting the given memory order (or memory_order_seq_cst - * if none is specified). - * - * The results are similar to those that would be obtained with +=, -=, - * |=, ^=, or |= on non-atomic types. - * - * - * atomic_flag - * =========== - * - * atomic_flag is a typedef for a type with two states, set and clear, that - * provides atomic test-and-set functionality. - * - * - * Life Cycle - * ---------- - * - * ATOMIC_FLAG_INIT is an initializer for atomic_flag. The initial state is - * "clear". - * - * An atomic_flag may also be initialized at runtime with atomic_flag_clear(). - * - * - * Operations - * ---------- - * - * The following functions are available. - * - * bool atomic_flag_test_and_set(atomic_flag *object) - * bool atomic_flag_test_and_set_explicit(atomic_flag *object, - * memory_order); - * - * Atomically sets '*object', respecting the given memory order (or - * memory_order_seq_cst for atomic_flag_test_and_set()). Returns the - * previous value of the flag (false for clear, true for set). - * - * void atomic_flag_clear(atomic_flag *object); - * void atomic_flag_clear_explicit(atomic_flag *object, memory_order); - * - * Atomically clears '*object', respecting the given memory order (or - * memory_order_seq_cst for atomic_flag_clear()). - */ - -#include -#include -#include -#include -#include -#include "openvswitch/compiler.h" -#include "util.h" - -#define IN_OVS_ATOMIC_H - #if __CHECKER__ - /* sparse doesn't understand some GCC extensions we use. */ - #include "ovs-atomic-pthreads.h" - #elif __has_extension(c_atomic) - #include "ovs-atomic-clang.h" - #elif HAVE_ATOMIC && __cplusplus >= 201103L - #include "ovs-atomic-c++.h" - #elif HAVE_STDATOMIC_H && !defined(__cplusplus) - #include "ovs-atomic-c11.h" - #elif __GNUC__ >= 5 && !defined(__cplusplus) - #error "GCC 5+ should have " - #elif __GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 7) - #include "ovs-atomic-gcc4.7+.h" - #elif __GNUC__ && defined(__x86_64__) - #include "ovs-atomic-x86_64.h" - #elif __GNUC__ && defined(__i386__) - #include "ovs-atomic-i586.h" - #elif HAVE_GCC4_ATOMICS - #include "ovs-atomic-gcc4+.h" - #elif _MSC_VER - #include "ovs-atomic-msvc.h" - #else - /* ovs-atomic-pthreads implementation is provided for portability. - * It might be too slow for real use because Open vSwitch is - * optimized for platforms where real atomic ops are available. */ - #include "ovs-atomic-pthreads.h" - #endif -#undef IN_OVS_ATOMIC_H - -#ifndef OMIT_STANDARD_ATOMIC_TYPES -typedef ATOMIC(bool) atomic_bool; - -typedef ATOMIC(char) atomic_char; -typedef ATOMIC(signed char) atomic_schar; -typedef ATOMIC(unsigned char) atomic_uchar; - -typedef ATOMIC(short) atomic_short; -typedef ATOMIC(unsigned short) atomic_ushort; - -typedef ATOMIC(int) atomic_int; -typedef ATOMIC(unsigned int) atomic_uint; - -typedef ATOMIC(long) atomic_long; -typedef ATOMIC(unsigned long) atomic_ulong; - -typedef ATOMIC(long long) atomic_llong; -typedef ATOMIC(unsigned long long) atomic_ullong; - -typedef ATOMIC(size_t) atomic_size_t; -typedef ATOMIC(ptrdiff_t) atomic_ptrdiff_t; - -typedef ATOMIC(intmax_t) atomic_intmax_t; -typedef ATOMIC(uintmax_t) atomic_uintmax_t; - -typedef ATOMIC(intptr_t) atomic_intptr_t; -typedef ATOMIC(uintptr_t) atomic_uintptr_t; -#endif /* !OMIT_STANDARD_ATOMIC_TYPES */ - -/* Nonstandard atomic types. */ -typedef ATOMIC(uint8_t) atomic_uint8_t; -typedef ATOMIC(uint16_t) atomic_uint16_t; -typedef ATOMIC(uint32_t) atomic_uint32_t; -typedef ATOMIC(uint64_t) atomic_uint64_t; - -typedef ATOMIC(int8_t) atomic_int8_t; -typedef ATOMIC(int16_t) atomic_int16_t; -typedef ATOMIC(int32_t) atomic_int32_t; -typedef ATOMIC(int64_t) atomic_int64_t; - -/* Relaxed atomic operations. - * - * When an operation on an atomic variable is not expected to synchronize - * with operations on other (atomic or non-atomic) variables, no memory - * barriers are needed and the relaxed memory ordering can be used. These - * macros make such uses less daunting, but not invisible. */ -#define atomic_store_relaxed(VAR, VALUE) \ - atomic_store_explicit(VAR, VALUE, memory_order_relaxed) -#define atomic_read_relaxed(VAR, DST) \ - atomic_read_explicit(VAR, DST, memory_order_relaxed) -#define atomic_compare_exchange_strong_relaxed(DST, EXP, SRC) \ - atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ - memory_order_relaxed, \ - memory_order_relaxed) -#define atomic_compare_exchange_weak_relaxed(DST, EXP, SRC) \ - atomic_compare_exchange_weak_explicit(DST, EXP, SRC, \ - memory_order_relaxed, \ - memory_order_relaxed) -#define atomic_add_relaxed(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, ARG, ORIG, memory_order_relaxed) -#define atomic_sub_relaxed(RMW, ARG, ORIG) \ - atomic_sub_explicit(RMW, ARG, ORIG, memory_order_relaxed) -#define atomic_or_relaxed(RMW, ARG, ORIG) \ - atomic_or_explicit(RMW, ARG, ORIG, memory_order_relaxed) -#define atomic_xor_relaxed(RMW, ARG, ORIG) \ - atomic_xor_explicit(RMW, ARG, ORIG, memory_order_relaxed) -#define atomic_and_relaxed(RMW, ARG, ORIG) \ - atomic_and_explicit(RMW, ARG, ORIG, memory_order_relaxed) -#define atomic_flag_test_and_set_relaxed(FLAG) \ - atomic_flag_test_and_set_explicit(FLAG, memory_order_relaxed) -#define atomic_flag_clear_relaxed(FLAG) \ - atomic_flag_clear_explicit(FLAG, memory_order_relaxed) - -/* A simplified atomic count. Does not provide any synchronization with any - * other variables. - * - * Typically a counter is not used to synchronize the state of any other - * variables (with the notable exception of reference count, below). - * This abstraction releaves the user from the memory order considerations, - * and may make the code easier to read. - * - * We only support the unsigned int counters, as those are the most common. */ -typedef struct atomic_count { - atomic_uint count; -} atomic_count; - -#define ATOMIC_COUNT_INIT(VALUE) { VALUE } - -static inline void -atomic_count_init(atomic_count *count, unsigned int value) -{ - atomic_init(&count->count, value); -} - -static inline unsigned int -atomic_count_inc(atomic_count *count) -{ - unsigned int old; - - atomic_add_relaxed(&count->count, 1u, &old); - - return old; -} - -static inline unsigned int -atomic_count_dec(atomic_count *count) -{ - unsigned int old; - - atomic_sub_relaxed(&count->count, 1u, &old); - - return old; -} - -static inline unsigned int -atomic_count_get(atomic_count *count) -{ - unsigned int value; - - atomic_read_relaxed(&count->count, &value); - - return value; -} - -static inline void -atomic_count_set(atomic_count *count, unsigned int value) -{ - atomic_store_relaxed(&count->count, value); -} - -static inline uint64_t -atomic_count_inc64(atomic_uint64_t *counter) -{ - uint64_t old; - - atomic_add_relaxed(counter, 1ull, &old); - - return old; -} - -static inline uint64_t -atomic_count_dec64(atomic_uint64_t *counter) -{ - uint64_t old; - - atomic_sub_relaxed(counter, 1ull, &old); - - return old; -} - -static inline uint64_t -atomic_count_get64(atomic_uint64_t *counter) -{ - uint64_t value; - - atomic_read_relaxed(counter, &value); - - return value; -} - -static inline void -atomic_count_set64(atomic_uint64_t *counter, uint64_t value) -{ - atomic_store_relaxed(counter, value); -} - -/* Reference count. */ -struct ovs_refcount { - atomic_uint count; -}; - -/* Initializes 'refcount'. The reference count is initially 1. */ -static inline void -ovs_refcount_init(struct ovs_refcount *refcount) -{ - atomic_init(&refcount->count, 1u); -} - -/* Increments 'refcount'. - * - * Does not provide a memory barrier, as the calling thread must have - * protected access to the object already. */ -static inline void -ovs_refcount_ref(struct ovs_refcount *refcount) -{ - unsigned int old_refcount; - - atomic_add_explicit(&refcount->count, 1u, &old_refcount, - memory_order_relaxed); - ovs_assert(old_refcount > 0); -} - -/* Decrements 'refcount' and returns the previous reference count. Often used - * in this form: - * - * if (ovs_refcount_unref(&object->ref_cnt) == 1) { - * ...uninitialize object... - * free(object); - * } - * - * Provides a release barrier making the preceding loads and stores to not be - * reordered after the unref, and in case of the last reference provides also - * an acquire barrier to keep all the following uninitialization from being - * reordered before the atomic decrement operation. Together these synchronize - * any concurrent unref operations between each other. */ -static inline unsigned int -ovs_refcount_unref(struct ovs_refcount *refcount) -{ - unsigned int old_refcount; - - atomic_sub_explicit(&refcount->count, 1u, &old_refcount, - memory_order_release); - ovs_assert(old_refcount > 0); - if (old_refcount == 1) { - /* 'memory_order_release' above means that there are no (reordered) - * accesses to the protected object from any thread at this point. - * An acquire barrier is needed to keep all subsequent access to the - * object's memory from being reordered before the atomic operation - * above. */ - atomic_thread_fence(memory_order_acquire); - } - return old_refcount; -} - -/* Reads and returns 'refcount_''s current reference count. - * - * Does not provide a memory barrier. - * - * Rarely useful. */ -static inline unsigned int -ovs_refcount_read(const struct ovs_refcount *refcount_) -{ - struct ovs_refcount *refcount - = CONST_CAST(struct ovs_refcount *, refcount_); - unsigned int count; - - atomic_read_explicit(&refcount->count, &count, memory_order_relaxed); - return count; -} - -/* Increments 'refcount', but only if it is non-zero. - * - * This may only be called for an object which is RCU protected during - * this call. This implies that its possible destruction is postponed - * until all current RCU threads quiesce. - * - * Returns false if the refcount was zero. In this case the object may - * be safely accessed until the current thread quiesces, but no additional - * references to the object may be taken. - * - * Does not provide a memory barrier, as the calling thread must have - * RCU protected access to the object already. - * - * It is critical that we never increment a zero refcount to a - * non-zero value, as whenever a refcount reaches the zero value, the - * protected object may be irrevocably scheduled for deletion. */ -static inline bool -ovs_refcount_try_ref_rcu(struct ovs_refcount *refcount) -{ - unsigned int count; - - atomic_read_explicit(&refcount->count, &count, memory_order_relaxed); - do { - if (count == 0) { - return false; - } - } while (!atomic_compare_exchange_weak_explicit(&refcount->count, &count, - count + 1, - memory_order_relaxed, - memory_order_relaxed)); - return true; -} - -/* Decrements 'refcount' and returns the previous reference count. To - * be used only when a memory barrier is already provided for the - * protected object independently. - * - * For example: - * - * if (ovs_refcount_unref_relaxed(&object->ref_cnt) == 1) { - * ovsrcu_postpone(destructor_function, object); - * } - * - * Here RCU quiescing already provides a full memory barrier. No additional - * barriers are needed here. - * - * Or: - * - * if (stp && ovs_refcount_unref_relaxed(&stp->ref_cnt) == 1) { - * ovs_mutex_lock(&mutex); - * ovs_list_remove(&stp->node); - * ovs_mutex_unlock(&mutex); - * free(stp->name); - * free(stp); - * } - * - * Here a mutex is used to guard access to all of 'stp' apart from - * 'ref_cnt'. Hence all changes to 'stp' by other threads must be - * visible when we get the mutex, and no access after the unlock can - * be reordered to happen prior the lock operation. No additional - * barriers are needed here. - */ -static inline unsigned int -ovs_refcount_unref_relaxed(struct ovs_refcount *refcount) -{ - unsigned int old_refcount; - - atomic_sub_explicit(&refcount->count, 1u, &old_refcount, - memory_order_relaxed); - ovs_assert(old_refcount > 0); - return old_refcount; -} - -#endif /* ovs-atomic.h */ Index: openvswitch-2.17.2/include/openvswitch/ovs-atomic.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovs-atomic.h @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2013, 2014, 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. + */ + +#ifndef OVS_ATOMIC_H +#define OVS_ATOMIC_H 1 + +/* Atomic operations. + * + * This library implements atomic operations with an API based on the one + * defined in C11. It includes multiple implementations for compilers and + * libraries with varying degrees of built-in support for C11, including a + * fallback implementation for systems that have pthreads but no other support + * for atomics. + * + * This comment describes the common features of all the implementations. + * + * + * Types + * ===== + * + * The following atomic types are supported as typedefs for atomic versions of + * the listed ordinary types: + * + * ordinary type atomic version + * ------------------- ---------------------- + * bool atomic_bool + * + * char atomic_char + * signed char atomic_schar + * unsigned char atomic_uchar + * + * short atomic_short + * unsigned short atomic_ushort + * + * int atomic_int + * unsigned int atomic_uint + * + * long atomic_long + * unsigned long atomic_ulong + * + * long long atomic_llong + * unsigned long long atomic_ullong + * + * size_t atomic_size_t + * ptrdiff_t atomic_ptrdiff_t + * + * intmax_t atomic_intmax_t + * uintmax_t atomic_uintmax_t + * + * intptr_t atomic_intptr_t + * uintptr_t atomic_uintptr_t + * + * uint8_t atomic_uint8_t (*) + * uint16_t atomic_uint16_t (*) + * uint32_t atomic_uint32_t (*) + * int8_t atomic_int8_t (*) + * int16_t atomic_int16_t (*) + * int32_t atomic_int32_t (*) + * uint64_t atomic_uint64_t (*) + * int64_t atomic_int64_t (*) + * + * (*) Not specified by C11. + * + * Atomic types may also be obtained via ATOMIC(TYPE), e.g. ATOMIC(void *). + * Only basic integer types and pointer types can be made atomic this way, + * e.g. atomic structs are not supported. + * + * The atomic version of a type doesn't necessarily have the same size or + * representation as the ordinary version; for example, atomic_int might be a + * typedef for a struct. The range of an atomic type does match the range of + * the corresponding ordinary type. + * + * C11 says that one may use the _Atomic keyword in place of the typedef name, + * e.g. "_Atomic int" instead of "atomic_int". This library doesn't support + * that. + * + * + * Life Cycle + * ========== + * + * To initialize an atomic variable at its point of definition, use + * ATOMIC_VAR_INIT: + * + * static atomic_int ai = ATOMIC_VAR_INIT(123); + * + * To initialize an atomic variable in code, use atomic_init(): + * + * static atomic_int ai; + * ... + * atomic_init(&ai, 123); + * + * + * Barriers + * ======== + * + * enum memory_order specifies the strictness of a memory barrier. It has the + * following values: + * + * memory_order_relaxed: + * + * Only atomicity is provided, does not imply any memory ordering with + * respect to any other variable (atomic or not). Relaxed accesses to + * the same atomic variable will be performed in the program order. + * The compiler and CPU are free to move memory accesses to other + * variables past the atomic operation. + * + * memory_order_consume: + * + * Memory accesses with data dependency on the result of the consume + * operation (atomic_read_explicit, or a load operation preceding a + * atomic_thread_fence) will not be moved prior to the consume + * barrier. Non-data-dependent loads and stores can be reordered to + * happen before the consume barrier. + * + * RCU is the prime example of the use of the consume barrier: The + * consume barrier guarantees that reads from a RCU protected object + * are performed after the RCU protected pointer is read. A + * corresponding release barrier is used to store the modified RCU + * protected pointer after the RCU protected object has been fully + * constructed. The synchronization between these barriers prevents + * the RCU "consumer" from seeing uninitialized data. + * + * May not be used with atomic_store_explicit(), as consume semantics + * applies only to atomic loads. + * + * memory_order_acquire: + * + * Memory accesses after an acquire barrier cannot be moved before the + * barrier. Memory accesses before an acquire barrier *can* be moved + * after it. + * + * An atomic_thread_fence with memory_order_acquire does not have a + * load operation by itself; it prevents all following memory accesses + * from moving prior to preceding loads. + * + * May not be used with atomic_store_explicit(), as acquire semantics + * applies only to atomic loads. + * + * memory_order_release: + * + * Memory accesses before a release barrier cannot be moved after the + * barrier. Memory accesses after a release barrier *can* be moved + * before it. + * + * An atomic_thread_fence with memory_order_release does not have a + * store operation by itself; it prevents all preceding memory accesses + * from moving past subsequent stores. + * + * May not be used with atomic_read_explicit(), as release semantics + * applies only to atomic stores. + * + * memory_order_acq_rel: + * + * Memory accesses cannot be moved across an acquire-release barrier in + * either direction. + * + * May only be used with atomic read-modify-write operations, as both + * load and store operation is required for acquire-release semantics. + * + * An atomic_thread_fence with memory_order_acq_rel does not have + * either load or store operation by itself; it prevents all following + * memory accesses from moving prior to preceding loads and all + * preceding memory accesses from moving past subsequent stores. + * + * memory_order_seq_cst: + * + * Prevents movement of memory accesses like an acquire-release barrier, + * but whereas acquire-release synchronizes cooperating threads (using + * the same atomic variable), sequential-consistency synchronizes the + * whole system, providing a total order for stores on all atomic + * variables. + * + * OVS atomics require the memory_order to be passed as a compile-time constant + * value, as some compiler implementations may perform poorly if the memory + * order parameter is passed in as a run-time value. + * + * The following functions insert explicit barriers. Most of the other atomic + * functions also include barriers. + * + * void atomic_thread_fence(memory_order order); + * + * Inserts a barrier of the specified type. + * + * For memory_order_relaxed, this is a no-op. + * + * void atomic_signal_fence(memory_order order); + * + * Inserts a barrier of the specified type, but only with respect to + * signal handlers in the same thread as the barrier. This is + * basically a compiler optimization barrier, except for + * memory_order_relaxed, which is a no-op. + * + * + * Atomic Operations + * ================= + * + * In this section, A is an atomic type and C is the corresponding non-atomic + * type. + * + * The "store", "exchange", and "compare_exchange" primitives match C11: + * + * void atomic_store(A *object, C value); + * void atomic_store_explicit(A *object, C value, memory_order); + * + * Atomically stores 'value' into '*object', respecting the given + * memory order (or memory_order_seq_cst for atomic_store()). + * + * bool atomic_compare_exchange_strong(A *object, C *expected, C desired); + * bool atomic_compare_exchange_weak(A *object, C *expected, C desired); + * bool atomic_compare_exchange_strong_explicit(A *object, C *expected, + * C desired, + * memory_order success, + * memory_order failure); + * bool atomic_compare_exchange_weak_explicit(A *object, C *expected, + * C desired, + * memory_order success, + * memory_order failure); + * + * Atomically loads '*object' and compares it with '*expected' and if + * equal, stores 'desired' into '*object' (an atomic read-modify-write + * operation) and returns true, and if non-equal, stores the actual + * value of '*object' into '*expected' (an atomic load operation) and + * returns false. The memory order for the successful case (atomic + * read-modify-write operation) is 'success', and for the unsuccessful + * case (atomic load operation) 'failure'. 'failure' may not be + * stronger than 'success'. + * + * The weak forms may fail (returning false) also when '*object' equals + * '*expected'. The strong form can be implemented by the weak form in + * a loop. Some platforms can implement the weak form more + * efficiently, so it should be used if the application will need to + * loop anyway. + * + * C atomic_exchange(A *object, C desired); + * C atomic_exchange_explicit(A *object, C desired, memory_order); + * + * Atomically stores 'desired' into '*object', returning the value + * previously held. + * + * The following primitives differ from the C11 ones (and have different names) + * because there does not appear to be a way to implement the standard + * primitives in standard C: + * + * void atomic_read(A *src, C *dst); + * void atomic_read_explicit(A *src, C *dst, memory_order); + * + * Atomically loads a value from 'src', writing the value read into + * '*dst', respecting the given memory order (or memory_order_seq_cst + * for atomic_read()). + * + * void atomic_add(A *rmw, C arg, C *orig); + * void atomic_sub(A *rmw, C arg, C *orig); + * void atomic_or(A *rmw, C arg, C *orig); + * void atomic_xor(A *rmw, C arg, C *orig); + * void atomic_and(A *rmw, C arg, C *orig); + * void atomic_add_explicit(A *rmw, C arg, C *orig, memory_order); + * void atomic_sub_explicit(A *rmw, C arg, C *orig, memory_order); + * void atomic_or_explicit(A *rmw, C arg, C *orig, memory_order); + * void atomic_xor_explicit(A *rmw, C arg, C *orig, memory_order); + * void atomic_and_explicit(A *rmw, C arg, C *orig, memory_order); + * + * Atomically applies the given operation, with 'arg' as the second + * operand, to '*rmw', and stores the original value of '*rmw' into + * '*orig', respecting the given memory order (or memory_order_seq_cst + * if none is specified). + * + * The results are similar to those that would be obtained with +=, -=, + * |=, ^=, or |= on non-atomic types. + * + * + * atomic_flag + * =========== + * + * atomic_flag is a typedef for a type with two states, set and clear, that + * provides atomic test-and-set functionality. + * + * + * Life Cycle + * ---------- + * + * ATOMIC_FLAG_INIT is an initializer for atomic_flag. The initial state is + * "clear". + * + * An atomic_flag may also be initialized at runtime with atomic_flag_clear(). + * + * + * Operations + * ---------- + * + * The following functions are available. + * + * bool atomic_flag_test_and_set(atomic_flag *object) + * bool atomic_flag_test_and_set_explicit(atomic_flag *object, + * memory_order); + * + * Atomically sets '*object', respecting the given memory order (or + * memory_order_seq_cst for atomic_flag_test_and_set()). Returns the + * previous value of the flag (false for clear, true for set). + * + * void atomic_flag_clear(atomic_flag *object); + * void atomic_flag_clear_explicit(atomic_flag *object, memory_order); + * + * Atomically clears '*object', respecting the given memory order (or + * memory_order_seq_cst for atomic_flag_clear()). + */ + +#include +#include +#include +#include +#include +#include "openvswitch/compiler.h" +#include "internal/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define IN_OVS_ATOMIC_H + #if __CHECKER__ + /* sparse doesn't understand some GCC extensions we use. */ + #include "internal/ovs-atomic-pthreads.h" + #elif __has_extension(c_atomic) + #include "internal/ovs-atomic-clang.h" + #elif HAVE_ATOMIC && __cplusplus >= 201103L + #include "internal/ovs-atomic-c++.h" + #elif HAVE_STDATOMIC_H && !defined(__cplusplus) + #include "internal/ovs-atomic-c11.h" + #elif __GNUC__ >= 5 && !defined(__cplusplus) + #error "GCC 5+ should have " + #elif __GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 7) + #include "internal/ovs-atomic-gcc4.7+.h" + #elif __GNUC__ && defined(__x86_64__) + #include "internal/ovs-atomic-x86_64.h" + #elif __GNUC__ && defined(__i386__) + #include "internal/ovs-atomic-i586.h" + #elif HAVE_GCC4_ATOMICS + #include "internal/ovs-atomic-gcc4+.h" + #elif _MSC_VER + #include "internal/ovs-atomic-msvc.h" + #else + /* ovs-atomic-pthreads implementation is provided for portability. + * It might be too slow for real use because Open vSwitch is + * optimized for platforms where real atomic ops are available. */ + #include "internal/ovs-atomic-pthreads.h" + #endif +#undef IN_OVS_ATOMIC_H + +#ifndef OMIT_STANDARD_ATOMIC_TYPES +typedef ATOMIC(bool) atomic_bool; + +typedef ATOMIC(char) atomic_char; +typedef ATOMIC(signed char) atomic_schar; +typedef ATOMIC(unsigned char) atomic_uchar; + +typedef ATOMIC(short) atomic_short; +typedef ATOMIC(unsigned short) atomic_ushort; + +typedef ATOMIC(int) atomic_int; +typedef ATOMIC(unsigned int) atomic_uint; + +typedef ATOMIC(long) atomic_long; +typedef ATOMIC(unsigned long) atomic_ulong; + +typedef ATOMIC(long long) atomic_llong; +typedef ATOMIC(unsigned long long) atomic_ullong; + +typedef ATOMIC(size_t) atomic_size_t; +typedef ATOMIC(ptrdiff_t) atomic_ptrdiff_t; + +typedef ATOMIC(intmax_t) atomic_intmax_t; +typedef ATOMIC(uintmax_t) atomic_uintmax_t; + +typedef ATOMIC(intptr_t) atomic_intptr_t; +typedef ATOMIC(uintptr_t) atomic_uintptr_t; +#endif /* !OMIT_STANDARD_ATOMIC_TYPES */ + +/* Nonstandard atomic types. */ +typedef ATOMIC(uint8_t) atomic_uint8_t; +typedef ATOMIC(uint16_t) atomic_uint16_t; +typedef ATOMIC(uint32_t) atomic_uint32_t; +typedef ATOMIC(uint64_t) atomic_uint64_t; + +typedef ATOMIC(int8_t) atomic_int8_t; +typedef ATOMIC(int16_t) atomic_int16_t; +typedef ATOMIC(int32_t) atomic_int32_t; +typedef ATOMIC(int64_t) atomic_int64_t; + +/* Relaxed atomic operations. + * + * When an operation on an atomic variable is not expected to synchronize + * with operations on other (atomic or non-atomic) variables, no memory + * barriers are needed and the relaxed memory ordering can be used. These + * macros make such uses less daunting, but not invisible. */ +#define atomic_store_relaxed(VAR, VALUE) \ + atomic_store_explicit(VAR, VALUE, memory_order_relaxed) +#define atomic_read_relaxed(VAR, DST) \ + atomic_read_explicit(VAR, DST, memory_order_relaxed) +#define atomic_compare_exchange_strong_relaxed(DST, EXP, SRC) \ + atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ + memory_order_relaxed, \ + memory_order_relaxed) +#define atomic_compare_exchange_weak_relaxed(DST, EXP, SRC) \ + atomic_compare_exchange_weak_explicit(DST, EXP, SRC, \ + memory_order_relaxed, \ + memory_order_relaxed) +#define atomic_add_relaxed(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, ARG, ORIG, memory_order_relaxed) +#define atomic_sub_relaxed(RMW, ARG, ORIG) \ + atomic_sub_explicit(RMW, ARG, ORIG, memory_order_relaxed) +#define atomic_or_relaxed(RMW, ARG, ORIG) \ + atomic_or_explicit(RMW, ARG, ORIG, memory_order_relaxed) +#define atomic_xor_relaxed(RMW, ARG, ORIG) \ + atomic_xor_explicit(RMW, ARG, ORIG, memory_order_relaxed) +#define atomic_and_relaxed(RMW, ARG, ORIG) \ + atomic_and_explicit(RMW, ARG, ORIG, memory_order_relaxed) +#define atomic_flag_test_and_set_relaxed(FLAG) \ + atomic_flag_test_and_set_explicit(FLAG, memory_order_relaxed) +#define atomic_flag_clear_relaxed(FLAG) \ + atomic_flag_clear_explicit(FLAG, memory_order_relaxed) + +/* A simplified atomic count. Does not provide any synchronization with any + * other variables. + * + * Typically a counter is not used to synchronize the state of any other + * variables (with the notable exception of reference count, below). + * This abstraction releaves the user from the memory order considerations, + * and may make the code easier to read. + * + * We only support the unsigned int counters, as those are the most common. */ +typedef struct atomic_count { + atomic_uint count; +} atomic_count; + +#define ATOMIC_COUNT_INIT(VALUE) { VALUE } + +static inline void +atomic_count_init(atomic_count *count, unsigned int value) +{ + atomic_init(&count->count, value); +} + +static inline unsigned int +atomic_count_inc(atomic_count *count) +{ + unsigned int old; + + atomic_add_relaxed(&count->count, 1u, &old); + + return old; +} + +static inline unsigned int +atomic_count_dec(atomic_count *count) +{ + unsigned int old; + + atomic_sub_relaxed(&count->count, 1u, &old); + + return old; +} + +static inline unsigned int +atomic_count_get(atomic_count *count) +{ + unsigned int value; + + atomic_read_relaxed(&count->count, &value); + + return value; +} + +static inline void +atomic_count_set(atomic_count *count, unsigned int value) +{ + atomic_store_relaxed(&count->count, value); +} + +static inline uint64_t +atomic_count_inc64(atomic_uint64_t *counter) +{ + uint64_t old; + + atomic_add_relaxed(counter, 1ull, &old); + + return old; +} + +static inline uint64_t +atomic_count_dec64(atomic_uint64_t *counter) +{ + uint64_t old; + + atomic_sub_relaxed(counter, 1ull, &old); + + return old; +} + +static inline uint64_t +atomic_count_get64(atomic_uint64_t *counter) +{ + uint64_t value; + + atomic_read_relaxed(counter, &value); + + return value; +} + +static inline void +atomic_count_set64(atomic_uint64_t *counter, uint64_t value) +{ + atomic_store_relaxed(counter, value); +} + +/* Reference count. */ +struct ovs_refcount { + atomic_uint count; +}; + +/* Initializes 'refcount'. The reference count is initially 1. */ +static inline void +ovs_refcount_init(struct ovs_refcount *refcount) +{ + atomic_init(&refcount->count, 1u); +} + +/* Increments 'refcount'. + * + * Does not provide a memory barrier, as the calling thread must have + * protected access to the object already. */ +static inline void +ovs_refcount_ref(struct ovs_refcount *refcount) +{ + unsigned int old_refcount; + + atomic_add_explicit(&refcount->count, 1u, &old_refcount, + memory_order_relaxed); + ovs_assert(old_refcount > 0); +} + +/* Decrements 'refcount' and returns the previous reference count. Often used + * in this form: + * + * if (ovs_refcount_unref(&object->ref_cnt) == 1) { + * ...uninitialize object... + * free(object); + * } + * + * Provides a release barrier making the preceding loads and stores to not be + * reordered after the unref, and in case of the last reference provides also + * an acquire barrier to keep all the following uninitialization from being + * reordered before the atomic decrement operation. Together these synchronize + * any concurrent unref operations between each other. */ +static inline unsigned int +ovs_refcount_unref(struct ovs_refcount *refcount) +{ + unsigned int old_refcount; + + atomic_sub_explicit(&refcount->count, 1u, &old_refcount, + memory_order_release); + ovs_assert(old_refcount > 0); + if (old_refcount == 1) { + /* 'memory_order_release' above means that there are no (reordered) + * accesses to the protected object from any thread at this point. + * An acquire barrier is needed to keep all subsequent access to the + * object's memory from being reordered before the atomic operation + * above. */ + atomic_thread_fence(memory_order_acquire); + } + return old_refcount; +} + +/* Reads and returns 'refcount_''s current reference count. + * + * Does not provide a memory barrier. + * + * Rarely useful. */ +static inline unsigned int +ovs_refcount_read(const struct ovs_refcount *refcount_) +{ + struct ovs_refcount *refcount + = CONST_CAST(struct ovs_refcount *, refcount_); + unsigned int count; + + atomic_read_explicit(&refcount->count, &count, memory_order_relaxed); + return count; +} + +/* Increments 'refcount', but only if it is non-zero. + * + * This may only be called for an object which is RCU protected during + * this call. This implies that its possible destruction is postponed + * until all current RCU threads quiesce. + * + * Returns false if the refcount was zero. In this case the object may + * be safely accessed until the current thread quiesces, but no additional + * references to the object may be taken. + * + * Does not provide a memory barrier, as the calling thread must have + * RCU protected access to the object already. + * + * It is critical that we never increment a zero refcount to a + * non-zero value, as whenever a refcount reaches the zero value, the + * protected object may be irrevocably scheduled for deletion. */ +static inline bool +ovs_refcount_try_ref_rcu(struct ovs_refcount *refcount) +{ + unsigned int count; + + atomic_read_explicit(&refcount->count, &count, memory_order_relaxed); + do { + if (count == 0) { + return false; + } + } while (!atomic_compare_exchange_weak_explicit(&refcount->count, &count, + count + 1, + memory_order_relaxed, + memory_order_relaxed)); + return true; +} + +/* Decrements 'refcount' and returns the previous reference count. To + * be used only when a memory barrier is already provided for the + * protected object independently. + * + * For example: + * + * if (ovs_refcount_unref_relaxed(&object->ref_cnt) == 1) { + * ovsrcu_postpone(destructor_function, object); + * } + * + * Here RCU quiescing already provides a full memory barrier. No additional + * barriers are needed here. + * + * Or: + * + * if (stp && ovs_refcount_unref_relaxed(&stp->ref_cnt) == 1) { + * ovs_mutex_lock(&mutex); + * ovs_list_remove(&stp->node); + * ovs_mutex_unlock(&mutex); + * free(stp->name); + * free(stp); + * } + * + * Here a mutex is used to guard access to all of 'stp' apart from + * 'ref_cnt'. Hence all changes to 'stp' by other threads must be + * visible when we get the mutex, and no access after the unlock can + * be reordered to happen prior the lock operation. No additional + * barriers are needed here. + */ +static inline unsigned int +ovs_refcount_unref_relaxed(struct ovs_refcount *refcount) +{ + unsigned int old_refcount; + + atomic_sub_explicit(&refcount->count, 1u, &old_refcount, + memory_order_relaxed); + ovs_assert(old_refcount > 0); + return old_refcount; +} + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ovs-atomic.h */ Index: openvswitch-2.17.2/lib/ovs-numa.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-numa.h +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 OVS_NUMA_H -#define OVS_NUMA_H 1 - -#include -#include - -#include "openvswitch/compiler.h" -#include "openvswitch/hmap.h" - -#define OVS_CORE_UNSPEC INT_MAX -#define OVS_NUMA_UNSPEC INT_MAX - -#define MAX_NUMA_NODES 128 - -/* Dump of a list of 'struct ovs_numa_info'. */ -struct ovs_numa_dump { - struct hmap cores; - struct hmap numas; -}; - -/* A numa_id - core_id pair. */ -struct ovs_numa_info_core { - struct hmap_node hmap_node; - int numa_id; - unsigned core_id; -}; - -/* A numa node. */ -struct ovs_numa_info_numa { - struct hmap_node hmap_node; - int numa_id; - size_t n_cores; -}; - -void ovs_numa_init(void); -void ovs_numa_set_dummy(const char *config); -bool ovs_numa_numa_id_is_valid(int numa_id); -bool ovs_numa_core_id_is_valid(unsigned core_id); -int ovs_numa_get_n_numas(void); -int ovs_numa_get_n_cores(void); -int ovs_numa_get_numa_id(unsigned core_id); -int ovs_numa_get_n_cores_on_numa(int numa_id); -struct ovs_numa_dump *ovs_numa_dump_cores_on_numa(int numa_id); -struct ovs_numa_dump *ovs_numa_dump_cores_with_cmask(const char *cmask); -struct ovs_numa_dump *ovs_numa_dump_n_cores_per_numa(int n); -bool ovs_numa_dump_contains_core(const struct ovs_numa_dump *, - int numa_id, unsigned core_id); -size_t ovs_numa_dump_count(const struct ovs_numa_dump *); -struct ovs_numa_dump * ovs_numa_thread_getaffinity_dump(void); -int ovs_numa_thread_setaffinity_dump(const struct ovs_numa_dump *); -void ovs_numa_dump_destroy(struct ovs_numa_dump *); -int ovs_numa_thread_setaffinity_core(unsigned core_id); - -#define FOR_EACH_CORE_ON_DUMP(ITER, DUMP) \ - HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->cores) - -#define FOR_EACH_NUMA_ON_DUMP(ITER, DUMP) \ - HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->numas) - -#endif /* ovs-numa.h */ Index: openvswitch-2.17.2/include/openvswitch/ovs-numa.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovs-numa.h @@ -0,0 +1,84 @@ +/* + * 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 OVS_NUMA_H +#define OVS_NUMA_H 1 + +#include +#include + +#include "openvswitch/compiler.h" +#include "openvswitch/hmap.h" + +#define OVS_CORE_UNSPEC INT_MAX +#define OVS_NUMA_UNSPEC INT_MAX + +#define MAX_NUMA_NODES 128 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Dump of a list of 'struct ovs_numa_info'. */ +struct ovs_numa_dump { + struct hmap cores; + struct hmap numas; +}; + +/* A numa_id - core_id pair. */ +struct ovs_numa_info_core { + struct hmap_node hmap_node; + int numa_id; + unsigned core_id; +}; + +/* A numa node. */ +struct ovs_numa_info_numa { + struct hmap_node hmap_node; + int numa_id; + size_t n_cores; +}; + +void ovs_numa_init(void); +void ovs_numa_set_dummy(const char *config); +bool ovs_numa_numa_id_is_valid(int numa_id); +bool ovs_numa_core_id_is_valid(unsigned core_id); +int ovs_numa_get_n_numas(void); +int ovs_numa_get_n_cores(void); +int ovs_numa_get_numa_id(unsigned core_id); +int ovs_numa_get_n_cores_on_numa(int numa_id); +struct ovs_numa_dump *ovs_numa_dump_cores_on_numa(int numa_id); +struct ovs_numa_dump *ovs_numa_dump_cores_with_cmask(const char *cmask); +struct ovs_numa_dump *ovs_numa_dump_n_cores_per_numa(int n); +bool ovs_numa_dump_contains_core(const struct ovs_numa_dump *, + int numa_id, unsigned core_id); +size_t ovs_numa_dump_count(const struct ovs_numa_dump *); +struct ovs_numa_dump * ovs_numa_thread_getaffinity_dump(void); +int ovs_numa_thread_setaffinity_dump(const struct ovs_numa_dump *); +void ovs_numa_dump_destroy(struct ovs_numa_dump *); +int ovs_numa_thread_setaffinity_core(unsigned core_id); + +#define FOR_EACH_CORE_ON_DUMP(ITER, DUMP) \ + HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->cores) + +#define FOR_EACH_NUMA_ON_DUMP(ITER, DUMP) \ + HMAP_FOR_EACH (ITER, hmap_node, &(DUMP)->numas) + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ovs-numa.h */ Index: openvswitch-2.17.2/lib/ovs-rcu.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-rcu.h +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 2016 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 OVS_RCU_H -#define OVS_RCU_H 1 - -/* Read-Copy-Update (RCU) - * ====================== - * - * Introduction - * ------------ - * - * Atomic pointer access makes it pretty easy to implement lock-free - * algorithms. There is one big problem, though: when a writer updates a - * pointer to point to a new data structure, some thread might be reading the - * old version, and there's no convenient way to free the old version when all - * threads are done with the old version. - * - * The function ovsrcu_postpone() solves that problem. The function pointer - * passed in as its argument is called only after all threads are done with old - * versions of data structures. The function callback frees an old version of - * data no longer in use. This technique is called "read-copy-update", or RCU - * for short. - * - * - * Details - * ------- - * - * A "quiescent state" is a time at which a thread holds no pointers to memory - * that is managed by RCU; that is, when the thread is known not to reference - * memory that might be an old version of some object freed via RCU. For - * example, poll_block() includes a quiescent state. - * - * The following functions manage the recognition of quiescent states: - * - * void ovsrcu_quiesce(void) - * - * Recognizes a momentary quiescent state in the current thread. - * - * void ovsrcu_quiesce_start(void) - * void ovsrcu_quiesce_end(void) - * - * Brackets a time period during which the current thread is quiescent. - * - * A newly created thread is initially active, not quiescent. When a process - * becomes multithreaded, the main thread becomes active, not quiescent. - * - * When a quiescient state has occurred in every thread, we say that a "grace - * period" has occurred. Following a grace period, all of the callbacks - * postponed before the start of the grace period MAY be invoked. OVS takes - * care of this automatically through the RCU mechanism: while a process still - * has only a single thread, it invokes the postponed callbacks directly from - * ovsrcu_quiesce() and ovsrcu_quiesce_start(); after additional threads have - * been created, it creates an extra helper thread to invoke callbacks. - * - * Please note that while a postponed function call is guaranteed to happen - * after the next time all participating threads have quiesced at least once, - * there is no quarantee that all postponed functions are called as early as - * possible, or that the functions postponed by different threads would be - * called in the order the registrations took place. In particular, even if - * two threads provably postpone a function each in a specific order, the - * postponed functions may still be called in the opposite order, depending on - * the timing of when the threads call ovsrcu_quiesce(), how many functions - * they postpone, and when the ovs-rcu thread happens to grab the functions to - * be called. - * - * All functions postponed by a single thread are guaranteed to execute in the - * order they were postponed, however. - * - * Usage - * ----- - * - * Use OVSRCU_TYPE(TYPE) to declare a pointer to RCU-protected data, e.g. the - * following declares an RCU-protected "struct flow *" named flowp: - * - * OVSRCU_TYPE(struct flow *) flowp; - * - * Use ovsrcu_get(TYPE, VAR) to read an RCU-protected pointer, e.g. to read the - * pointer variable declared above: - * - * struct flow *flow = ovsrcu_get(struct flow *, &flowp); - * - * If the pointer variable is currently protected against change (because - * the current thread holds a mutex that protects it), ovsrcu_get_protected() - * may be used instead. Only on the Alpha architecture is this likely to - * generate different code, but it may be useful documentation. - * - * (With GNU C or Clang, you get a compiler error if TYPE is wrong; other - * compilers will merrily carry along accepting the wrong type.) - * - * Use ovsrcu_set() to write an RCU-protected pointer and ovsrcu_postpone() to - * free the previous data. ovsrcu_set_hidden() can be used on RCU protected - * data not visible to any readers yet, but will be made visible by a later - * ovsrcu_set(). ovsrcu_init() can be used to initialize RCU pointers when - * no readers are yet executing. If more than one thread can write the - * pointer, then some form of external synchronization, e.g. a mutex, is - * needed to prevent writers from interfering with one another. For example, - * to write the pointer variable declared above while safely freeing the old - * value: - * - * static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; - * - * OVSRCU_TYPE(struct flow *) flowp; - * - * void - * change_flow(struct flow *new_flow) - * { - * ovs_mutex_lock(&mutex); - * ovsrcu_postpone(free, - * ovsrcu_get_protected(struct flow *, &flowp)); - * ovsrcu_set(&flowp, new_flow); - * ovs_mutex_unlock(&mutex); - * } - * - * In some rare cases an object may not be addressable with a pointer, but only - * through an array index (e.g. because it's provided by another library). It - * is still possible to have RCU semantics by using the ovsrcu_index type. - * - * static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; - * - * ovsrcu_index port_id; - * - * void tx() - * { - * int id = ovsrcu_index_get(&port_id); - * if (id == -1) { - * return; - * } - * port_tx(id); - * } - * - * void delete() - * { - * int id; - * - * ovs_mutex_lock(&mutex); - * id = ovsrcu_index_get_protected(&port_id); - * ovsrcu_index_set(&port_id, -1); - * ovs_mutex_unlock(&mutex); - * - * ovsrcu_synchronize(); - * port_delete(id); - * } - * - * Use ovsrcu_barrier() to wait for all the outstanding RCU callbacks to - * finish. This is useful when you have to destroy some resources however - * these resources are referenced in the outstanding RCU callbacks. - * - * void rcu_cb(void *A) { - * do_something(A); - * } - * - * void destroy_A() { - * ovsrcu_postpone(rcu_cb, A); // will use A later - * ovsrcu_barrier(); // wait for rcu_cb done - * do_destroy_A(); // free A - * } - */ - -#include "openvswitch/compiler.h" -#include "ovs-atomic.h" - -#if __GNUC__ -#define OVSRCU_TYPE(TYPE) struct { ATOMIC(TYPE) p; } -#define OVSRCU_INITIALIZER(VALUE) { ATOMIC_VAR_INIT(VALUE) } -#define ovsrcu_get__(TYPE, VAR, ORDER) \ - ({ \ - TYPE value__; \ - typeof(VAR) ovsrcu_var = (VAR); \ - \ - atomic_read_explicit(CONST_CAST(ATOMIC(TYPE) *, &ovsrcu_var->p), \ - &value__, ORDER); \ - \ - value__; \ - }) -#define ovsrcu_get(TYPE, VAR) \ - ovsrcu_get__(TYPE, VAR, memory_order_consume) -#define ovsrcu_get_protected(TYPE, VAR) \ - ovsrcu_get__(TYPE, VAR, memory_order_relaxed) - -/* 'VALUE' may be an atomic operation, which must be evaluated before - * any of the body of the atomic_store_explicit. Since the type of - * 'VAR' is not fixed, we cannot use an inline function to get - * function semantics for this. */ -#define ovsrcu_set__(VAR, VALUE, ORDER) \ - ({ \ - typeof(VAR) ovsrcu_var = (VAR); \ - typeof(VALUE) ovsrcu_value = (VALUE); \ - memory_order ovsrcu_order = (ORDER); \ - \ - atomic_store_explicit(&ovsrcu_var->p, ovsrcu_value, ovsrcu_order); \ - (void *) 0; \ - }) -#else /* not GNU C */ -struct ovsrcu_pointer { ATOMIC(void *) p; }; -#define OVSRCU_TYPE(TYPE) struct ovsrcu_pointer -#define OVSRCU_INITIALIZER(VALUE) { ATOMIC_VAR_INIT(VALUE) } -static inline void * -ovsrcu_get__(const struct ovsrcu_pointer *pointer, memory_order order) -{ - void *value; - atomic_read_explicit(&CONST_CAST(struct ovsrcu_pointer *, pointer)->p, - &value, order); - return value; -} -#define ovsrcu_get(TYPE, VAR) \ - CONST_CAST(TYPE, ovsrcu_get__(VAR, memory_order_consume)) -#define ovsrcu_get_protected(TYPE, VAR) \ - CONST_CAST(TYPE, ovsrcu_get__(VAR, memory_order_relaxed)) - -static inline void ovsrcu_set__(struct ovsrcu_pointer *pointer, - const void *value, - memory_order order) -{ - atomic_store_explicit(&pointer->p, CONST_CAST(void *, value), order); -} -#endif - -/* Writes VALUE to the RCU-protected pointer whose address is VAR. - * - * Users require external synchronization (e.g. a mutex). See "Usage" above - * for an example. */ -#define ovsrcu_set(VAR, VALUE) \ - ovsrcu_set__(VAR, VALUE, memory_order_release) - -/* This can be used for initializing RCU pointers before any readers can - * see them. A later ovsrcu_set() needs to make the bigger structure this - * is part of visible to the readers. */ -#define ovsrcu_set_hidden(VAR, VALUE) \ - ovsrcu_set__(VAR, VALUE, memory_order_relaxed) - -/* This can be used for initializing RCU pointers before any readers are - * executing. */ -#define ovsrcu_init(VAR, VALUE) atomic_init(&(VAR)->p, VALUE) - -/* Calls FUNCTION passing ARG as its pointer-type argument following the next - * grace period. See "Usage" above for an example. */ -void ovsrcu_postpone__(void (*function)(void *aux), void *aux); -#define ovsrcu_postpone(FUNCTION, ARG) \ - (/* Verify that ARG is appropriate for FUNCTION. */ \ - (void) sizeof((FUNCTION)(ARG), 1), \ - /* Verify that ARG is a pointer type. */ \ - (void) sizeof(*(ARG)), \ - ovsrcu_postpone__((void (*)(void *))(FUNCTION), ARG)) - -/* An array index protected by RCU semantics. This is an easier alternative to - * an RCU protected pointer to a malloc'd int. */ -typedef struct { atomic_int v; } ovsrcu_index; - -static inline int ovsrcu_index_get__(const ovsrcu_index *i, memory_order order) -{ - int ret; - atomic_read_explicit(CONST_CAST(atomic_int *, &i->v), &ret, order); - return ret; -} - -/* Returns the index contained in 'i'. The returned value can be used until - * the next grace period. */ -static inline int ovsrcu_index_get(const ovsrcu_index *i) -{ - return ovsrcu_index_get__(i, memory_order_consume); -} - -/* Returns the index contained in 'i'. This is an alternative to - * ovsrcu_index_get() that can be used when there's no possible concurrent - * writer. */ -static inline int ovsrcu_index_get_protected(const ovsrcu_index *i) -{ - return ovsrcu_index_get__(i, memory_order_relaxed); -} - -static inline void ovsrcu_index_set__(ovsrcu_index *i, int value, - memory_order order) -{ - atomic_store_explicit(&i->v, value, order); -} - -/* Writes the index 'value' in 'i'. The previous value of 'i' may still be - * used by readers until the next grace period. */ -static inline void ovsrcu_index_set(ovsrcu_index *i, int value) -{ - ovsrcu_index_set__(i, value, memory_order_release); -} - -/* Writes the index 'value' in 'i'. This is an alternative to - * ovsrcu_index_set() that can be used when there's no possible concurrent - * reader. */ -static inline void ovsrcu_index_set_hidden(ovsrcu_index *i, int value) -{ - ovsrcu_index_set__(i, value, memory_order_relaxed); -} - -/* Initializes 'i' with 'value'. This is safe to call as long as there are no - * concurrent readers. */ -static inline void ovsrcu_index_init(ovsrcu_index *i, int value) -{ - atomic_init(&i->v, value); -} - -/* Quiescent states. */ -void ovsrcu_quiesce_start(void); -void ovsrcu_quiesce_end(void); -void ovsrcu_quiesce(void); -int ovsrcu_try_quiesce(void); -bool ovsrcu_is_quiescent(void); - -/* Synchronization. Waits for all non-quiescent threads to quiesce at least - * once. This can block for a relatively long time. */ -void ovsrcu_synchronize(void); - -void ovsrcu_exit(void); - -void ovsrcu_barrier(void); - -#endif /* ovs-rcu.h */ Index: openvswitch-2.17.2/include/openvswitch/ovs-rcu.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovs-rcu.h @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2014, 2015, 2016 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 OVS_RCU_H +#define OVS_RCU_H 1 + +/* Read-Copy-Update (RCU) + * ====================== + * + * Introduction + * ------------ + * + * Atomic pointer access makes it pretty easy to implement lock-free + * algorithms. There is one big problem, though: when a writer updates a + * pointer to point to a new data structure, some thread might be reading the + * old version, and there's no convenient way to free the old version when all + * threads are done with the old version. + * + * The function ovsrcu_postpone() solves that problem. The function pointer + * passed in as its argument is called only after all threads are done with old + * versions of data structures. The function callback frees an old version of + * data no longer in use. This technique is called "read-copy-update", or RCU + * for short. + * + * + * Details + * ------- + * + * A "quiescent state" is a time at which a thread holds no pointers to memory + * that is managed by RCU; that is, when the thread is known not to reference + * memory that might be an old version of some object freed via RCU. For + * example, poll_block() includes a quiescent state. + * + * The following functions manage the recognition of quiescent states: + * + * void ovsrcu_quiesce(void) + * + * Recognizes a momentary quiescent state in the current thread. + * + * void ovsrcu_quiesce_start(void) + * void ovsrcu_quiesce_end(void) + * + * Brackets a time period during which the current thread is quiescent. + * + * A newly created thread is initially active, not quiescent. When a process + * becomes multithreaded, the main thread becomes active, not quiescent. + * + * When a quiescient state has occurred in every thread, we say that a "grace + * period" has occurred. Following a grace period, all of the callbacks + * postponed before the start of the grace period MAY be invoked. OVS takes + * care of this automatically through the RCU mechanism: while a process still + * has only a single thread, it invokes the postponed callbacks directly from + * ovsrcu_quiesce() and ovsrcu_quiesce_start(); after additional threads have + * been created, it creates an extra helper thread to invoke callbacks. + * + * Please note that while a postponed function call is guaranteed to happen + * after the next time all participating threads have quiesced at least once, + * there is no quarantee that all postponed functions are called as early as + * possible, or that the functions postponed by different threads would be + * called in the order the registrations took place. In particular, even if + * two threads provably postpone a function each in a specific order, the + * postponed functions may still be called in the opposite order, depending on + * the timing of when the threads call ovsrcu_quiesce(), how many functions + * they postpone, and when the ovs-rcu thread happens to grab the functions to + * be called. + * + * All functions postponed by a single thread are guaranteed to execute in the + * order they were postponed, however. + * + * Usage + * ----- + * + * Use OVSRCU_TYPE(TYPE) to declare a pointer to RCU-protected data, e.g. the + * following declares an RCU-protected "struct flow *" named flowp: + * + * OVSRCU_TYPE(struct flow *) flowp; + * + * Use ovsrcu_get(TYPE, VAR) to read an RCU-protected pointer, e.g. to read the + * pointer variable declared above: + * + * struct flow *flow = ovsrcu_get(struct flow *, &flowp); + * + * If the pointer variable is currently protected against change (because + * the current thread holds a mutex that protects it), ovsrcu_get_protected() + * may be used instead. Only on the Alpha architecture is this likely to + * generate different code, but it may be useful documentation. + * + * (With GNU C or Clang, you get a compiler error if TYPE is wrong; other + * compilers will merrily carry along accepting the wrong type.) + * + * Use ovsrcu_set() to write an RCU-protected pointer and ovsrcu_postpone() to + * free the previous data. ovsrcu_set_hidden() can be used on RCU protected + * data not visible to any readers yet, but will be made visible by a later + * ovsrcu_set(). ovsrcu_init() can be used to initialize RCU pointers when + * no readers are yet executing. If more than one thread can write the + * pointer, then some form of external synchronization, e.g. a mutex, is + * needed to prevent writers from interfering with one another. For example, + * to write the pointer variable declared above while safely freeing the old + * value: + * + * static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; + * + * OVSRCU_TYPE(struct flow *) flowp; + * + * void + * change_flow(struct flow *new_flow) + * { + * ovs_mutex_lock(&mutex); + * ovsrcu_postpone(free, + * ovsrcu_get_protected(struct flow *, &flowp)); + * ovsrcu_set(&flowp, new_flow); + * ovs_mutex_unlock(&mutex); + * } + * + * In some rare cases an object may not be addressable with a pointer, but only + * through an array index (e.g. because it's provided by another library). It + * is still possible to have RCU semantics by using the ovsrcu_index type. + * + * static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; + * + * ovsrcu_index port_id; + * + * void tx() + * { + * int id = ovsrcu_index_get(&port_id); + * if (id == -1) { + * return; + * } + * port_tx(id); + * } + * + * void delete() + * { + * int id; + * + * ovs_mutex_lock(&mutex); + * id = ovsrcu_index_get_protected(&port_id); + * ovsrcu_index_set(&port_id, -1); + * ovs_mutex_unlock(&mutex); + * + * ovsrcu_synchronize(); + * port_delete(id); + * } + * + * Use ovsrcu_barrier() to wait for all the outstanding RCU callbacks to + * finish. This is useful when you have to destroy some resources however + * these resources are referenced in the outstanding RCU callbacks. + * + * void rcu_cb(void *A) { + * do_something(A); + * } + * + * void destroy_A() { + * ovsrcu_postpone(rcu_cb, A); // will use A later + * ovsrcu_barrier(); // wait for rcu_cb done + * do_destroy_A(); // free A + * } + */ + +#include "openvswitch/compiler.h" +#include "openvswitch/ovs-atomic.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if __GNUC__ +#define OVSRCU_TYPE(TYPE) struct { ATOMIC(TYPE) p; } +#define OVSRCU_INITIALIZER(VALUE) { ATOMIC_VAR_INIT(VALUE) } +#define ovsrcu_get__(TYPE, VAR, ORDER) \ + ({ \ + TYPE value__; \ + typeof(VAR) ovsrcu_var = (VAR); \ + \ + atomic_read_explicit(CONST_CAST(ATOMIC(TYPE) *, &ovsrcu_var->p), \ + &value__, ORDER); \ + \ + value__; \ + }) +#define ovsrcu_get(TYPE, VAR) \ + ovsrcu_get__(TYPE, VAR, memory_order_consume) +#define ovsrcu_get_protected(TYPE, VAR) \ + ovsrcu_get__(TYPE, VAR, memory_order_relaxed) + +/* 'VALUE' may be an atomic operation, which must be evaluated before + * any of the body of the atomic_store_explicit. Since the type of + * 'VAR' is not fixed, we cannot use an inline function to get + * function semantics for this. */ +#define ovsrcu_set__(VAR, VALUE, ORDER) \ + ({ \ + typeof(VAR) ovsrcu_var = (VAR); \ + typeof(VALUE) ovsrcu_value = (VALUE); \ + memory_order ovsrcu_order = (ORDER); \ + \ + atomic_store_explicit(&ovsrcu_var->p, ovsrcu_value, ovsrcu_order); \ + (void *) 0; \ + }) +#else /* not GNU C */ +struct ovsrcu_pointer { ATOMIC(void *) p; }; +#define OVSRCU_TYPE(TYPE) struct ovsrcu_pointer +#define OVSRCU_INITIALIZER(VALUE) { ATOMIC_VAR_INIT(VALUE) } +static inline void * +ovsrcu_get__(const struct ovsrcu_pointer *pointer, memory_order order) +{ + void *value; + atomic_read_explicit(&CONST_CAST(struct ovsrcu_pointer *, pointer)->p, + &value, order); + return value; +} +#define ovsrcu_get(TYPE, VAR) \ + CONST_CAST(TYPE, ovsrcu_get__(VAR, memory_order_consume)) +#define ovsrcu_get_protected(TYPE, VAR) \ + CONST_CAST(TYPE, ovsrcu_get__(VAR, memory_order_relaxed)) + +static inline void ovsrcu_set__(struct ovsrcu_pointer *pointer, + const void *value, + memory_order order) +{ + atomic_store_explicit(&pointer->p, CONST_CAST(void *, value), order); +} +#endif + +/* Writes VALUE to the RCU-protected pointer whose address is VAR. + * + * Users require external synchronization (e.g. a mutex). See "Usage" above + * for an example. */ +#define ovsrcu_set(VAR, VALUE) \ + ovsrcu_set__(VAR, VALUE, memory_order_release) + +/* This can be used for initializing RCU pointers before any readers can + * see them. A later ovsrcu_set() needs to make the bigger structure this + * is part of visible to the readers. */ +#define ovsrcu_set_hidden(VAR, VALUE) \ + ovsrcu_set__(VAR, VALUE, memory_order_relaxed) + +/* This can be used for initializing RCU pointers before any readers are + * executing. */ +#define ovsrcu_init(VAR, VALUE) atomic_init(&(VAR)->p, VALUE) + +/* Calls FUNCTION passing ARG as its pointer-type argument following the next + * grace period. See "Usage" above for an example. */ +void ovsrcu_postpone__(void (*function)(void *aux), void *aux); +#define ovsrcu_postpone(FUNCTION, ARG) \ + (/* Verify that ARG is appropriate for FUNCTION. */ \ + (void) sizeof((FUNCTION)(ARG), 1), \ + /* Verify that ARG is a pointer type. */ \ + (void) sizeof(*(ARG)), \ + ovsrcu_postpone__((void (*)(void *))(FUNCTION), ARG)) + +/* An array index protected by RCU semantics. This is an easier alternative to + * an RCU protected pointer to a malloc'd int. */ +typedef struct { atomic_int v; } ovsrcu_index; + +static inline int ovsrcu_index_get__(const ovsrcu_index *i, memory_order order) +{ + int ret; + atomic_read_explicit(CONST_CAST(atomic_int *, &i->v), &ret, order); + return ret; +} + +/* Returns the index contained in 'i'. The returned value can be used until + * the next grace period. */ +static inline int ovsrcu_index_get(const ovsrcu_index *i) +{ + return ovsrcu_index_get__(i, memory_order_consume); +} + +/* Returns the index contained in 'i'. This is an alternative to + * ovsrcu_index_get() that can be used when there's no possible concurrent + * writer. */ +static inline int ovsrcu_index_get_protected(const ovsrcu_index *i) +{ + return ovsrcu_index_get__(i, memory_order_relaxed); +} + +static inline void ovsrcu_index_set__(ovsrcu_index *i, int value, + memory_order order) +{ + atomic_store_explicit(&i->v, value, order); +} + +/* Writes the index 'value' in 'i'. The previous value of 'i' may still be + * used by readers until the next grace period. */ +static inline void ovsrcu_index_set(ovsrcu_index *i, int value) +{ + ovsrcu_index_set__(i, value, memory_order_release); +} + +/* Writes the index 'value' in 'i'. This is an alternative to + * ovsrcu_index_set() that can be used when there's no possible concurrent + * reader. */ +static inline void ovsrcu_index_set_hidden(ovsrcu_index *i, int value) +{ + ovsrcu_index_set__(i, value, memory_order_relaxed); +} + +/* Initializes 'i' with 'value'. This is safe to call as long as there are no + * concurrent readers. */ +static inline void ovsrcu_index_init(ovsrcu_index *i, int value) +{ + atomic_init(&i->v, value); +} + +/* Quiescent states. */ +void ovsrcu_quiesce_start(void); +void ovsrcu_quiesce_end(void); +void ovsrcu_quiesce(void); +int ovsrcu_try_quiesce(void); +bool ovsrcu_is_quiescent(void); + +/* Synchronization. Waits for all non-quiescent threads to quiesce at least + * once. This can block for a relatively long time. */ +void ovsrcu_synchronize(void); + +void ovsrcu_exit(void); + +void ovsrcu_barrier(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ovs-rcu.h */ Index: openvswitch-2.17.2/lib/ovs-thread.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-thread.h +++ /dev/null @@ -1,527 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OVS_THREAD_H -#define OVS_THREAD_H 1 - -#include -#include -#include -#include "ovs-atomic.h" -#include "ovs-rcu.h" -#include "openvswitch/thread.h" -#include "util.h" - -struct seq; - -/* Poll-block()-able barrier similar to pthread_barrier_t. */ -struct ovs_barrier_impl; -struct ovs_barrier { - OVSRCU_TYPE(struct ovs_barrier_impl *) impl; -}; - -/* Wrappers for pthread_mutexattr_*() that abort the process on any error. */ -void xpthread_mutexattr_init(pthread_mutexattr_t *); -void xpthread_mutexattr_destroy(pthread_mutexattr_t *); -void xpthread_mutexattr_settype(pthread_mutexattr_t *, int type); -void xpthread_mutexattr_gettype(pthread_mutexattr_t *, int *typep); - -/* Read-write lock. - * - * An ovs_rwlock does not support recursive readers, because POSIX allows - * taking the reader lock recursively to deadlock when a thread is waiting on - * the write-lock. (NetBSD does deadlock.) glibc rwlocks in their default - * configuration do not deadlock, but ovs_rwlock_init() initializes rwlocks as - * non-recursive (which will deadlock) for two reasons: - * - * - glibc only provides fairness to writers in this mode. - * - * - It's better to find bugs in the primary Open vSwitch target rather - * than exposing them only to porters. */ -struct OVS_LOCKABLE ovs_rwlock { - pthread_rwlock_t lock; - const char *where; /* NULL if and only if uninitialized. */ -}; - -/* Initializer. */ -#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP -#define OVS_RWLOCK_INITIALIZER \ - { PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, "" } -#else -#define OVS_RWLOCK_INITIALIZER { PTHREAD_RWLOCK_INITIALIZER, "" } -#endif - -/* ovs_rwlock functions analogous to pthread_rwlock_*() functions. - * - * Most of these functions abort the process with an error message on any - * error. The "trylock" functions are exception: they pass through a 0 or - * EBUSY return value to the caller and abort on any other error. */ -void ovs_rwlock_init(const struct ovs_rwlock *); -void ovs_rwlock_destroy(const struct ovs_rwlock *); -void ovs_rwlock_unlock(const struct ovs_rwlock *rwlock) OVS_RELEASES(rwlock); - -/* Wrappers for pthread_rwlockattr_*() that abort the process on any error. */ -void xpthread_rwlockattr_init(pthread_rwlockattr_t *); -void xpthread_rwlockattr_destroy(pthread_rwlockattr_t *); -#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP -void xpthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int kind); -#endif - -void ovs_rwlock_wrlock_at(const struct ovs_rwlock *rwlock, const char *where) - OVS_ACQ_WRLOCK(rwlock); -#define ovs_rwlock_wrlock(rwlock) \ - ovs_rwlock_wrlock_at(rwlock, OVS_SOURCE_LOCATOR) - -int ovs_rwlock_trywrlock_at(const struct ovs_rwlock *rwlock, const char *where) - OVS_TRY_WRLOCK(0, rwlock); -#define ovs_rwlock_trywrlock(rwlock) \ - ovs_rwlock_trywrlock_at(rwlock, OVS_SOURCE_LOCATOR) - -void ovs_rwlock_rdlock_at(const struct ovs_rwlock *rwlock, const char *where) - OVS_ACQ_RDLOCK(rwlock); -#define ovs_rwlock_rdlock(rwlock) \ - ovs_rwlock_rdlock_at(rwlock, OVS_SOURCE_LOCATOR) - -int ovs_rwlock_tryrdlock_at(const struct ovs_rwlock *rwlock, const char *where) - OVS_TRY_RDLOCK(0, rwlock); -#define ovs_rwlock_tryrdlock(rwlock) \ - ovs_rwlock_tryrdlock_at(rwlock, OVS_SOURCE_LOCATOR) - -/* ovs_barrier functions analogous to pthread_barrier_*() functions. */ -void ovs_barrier_init(struct ovs_barrier *, uint32_t count); -void ovs_barrier_destroy(struct ovs_barrier *); -void ovs_barrier_block(struct ovs_barrier *); - -/* Wrappers for xpthread_cond_*() that abort the process on any error. - * - * Use ovs_mutex_cond_wait() to wait for a condition. */ -void xpthread_cond_init(pthread_cond_t *, pthread_condattr_t *); -void xpthread_cond_destroy(pthread_cond_t *); -void xpthread_cond_signal(pthread_cond_t *); -void xpthread_cond_broadcast(pthread_cond_t *); - -void xpthread_key_create(pthread_key_t *, void (*destructor)(void *)); -void xpthread_key_delete(pthread_key_t); -void xpthread_setspecific(pthread_key_t, const void *); - -#ifndef _WIN32 -void xpthread_sigmask(int, const sigset_t *, sigset_t *); -#endif - -pthread_t ovs_thread_create(const char *name, void *(*)(void *), void *); -void xpthread_join(pthread_t, void **); - -/* Per-thread data. - * - * - * Standard Forms - * ============== - * - * Multiple forms of standard per-thread data exist, each with its own pluses - * and minuses. In general, if one of these forms is appropriate, then it's a - * good idea to use it: - * - * - POSIX per-thread data via pthread_key_t is portable to any pthreads - * implementation, and allows a destructor function to be defined. It - * only (directly) supports per-thread pointers, which are always - * initialized to NULL. It requires once-only allocation of a - * pthread_key_t value. It is relatively slow. Typically few - * "pthread_key_t"s are available (POSIX requires only at least 128, - * glibc supplies only 1024). - * - * - The thread_local feature newly defined in C11 works with - * any data type and initializer, and it is fast. thread_local does not - * require once-only initialization like pthread_key_t. C11 does not - * define what happens if one attempts to access a thread_local object - * from a thread other than the one to which that object belongs. There - * is no provision to call a user-specified destructor when a thread - * ends. Typical implementations allow for an arbitrary amount of - * thread_local storage, but statically allocated only. - * - * - The __thread keyword is a GCC extension similar to thread_local but - * with a longer history. __thread is not portable to every GCC version - * or environment. __thread does not restrict the use of a thread-local - * object outside its own thread. - * - * Here's a handy summary: - * - * pthread_key_t thread_local __thread - * ------------- ------------ ------------- - * portability high low medium - * speed low high high - * supports destructors? yes no no - * needs key allocation? yes no no - * arbitrary initializer? no yes yes - * cross-thread access? yes no yes - * amount available? few arbitrary arbitrary - * dynamically allocated? yes no no - * - * - * Extensions - * ========== - * - * OVS provides some extensions and wrappers: - * - * - In a situation where the performance of thread_local or __thread is - * desirable, but portability is required, DEFINE_STATIC_PER_THREAD_DATA - * and DECLARE_EXTERN_PER_THREAD_DATA/DEFINE_EXTERN_PER_THREAD_DATA may - * be appropriate (see below). - * - * - DEFINE_PER_THREAD_MALLOCED_DATA can be convenient for simple - * per-thread malloc()'d buffers. - * - * - struct ovs_tsd provides an alternative to pthread_key_t that isn't - * limited to a small number of keys. - */ - -/* For static data, use this macro in a source file: - * - * DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, INITIALIZER). - * - * For global data, "declare" the data in the header and "define" it in - * the source file, with: - * - * DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME). - * DEFINE_EXTERN_PER_THREAD_DATA(NAME, INITIALIZER). - * - * One should prefer to use POSIX per-thread data, via pthread_key_t, when its - * performance is acceptable, because of its portability (see the table above). - * This macro is an alternatives that takes advantage of thread_local (and - * __thread), for its performance, when it is available, and falls back to - * POSIX per-thread data otherwise. - * - * Defines per-thread variable NAME with the given TYPE, initialized to - * INITIALIZER (which must be valid as an initializer for a variable with - * static lifetime). - * - * The public interface to the variable is: - * - * TYPE *NAME_get(void) - * TYPE *NAME_get_unsafe(void) - * - * Returns the address of this thread's instance of NAME. - * - * Use NAME_get() in a context where this might be the first use of the - * per-thread variable in the program. Use NAME_get_unsafe(), which - * avoids a conditional test and is thus slightly faster, in a context - * where one knows that NAME_get() has already been called previously. - * - * There is no "NAME_set()" (or "NAME_set_unsafe()") function. To set the - * value of the per-thread variable, dereference the pointer returned by - * TYPE_get() or TYPE_get_unsafe(), e.g. *TYPE_get() = 0. - */ -#if HAVE_THREAD_LOCAL || HAVE___THREAD - -#if HAVE_THREAD_LOCAL -#include -#elif HAVE___THREAD -#define thread_local __thread -#else -#error -#endif - -#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ - typedef TYPE NAME##_type; \ - \ - static NAME##_type * \ - NAME##_get_unsafe(void) \ - { \ - static thread_local NAME##_type var = __VA_ARGS__; \ - return &var; \ - } \ - \ - static NAME##_type * \ - NAME##_get(void) \ - { \ - return NAME##_get_unsafe(); \ - } -#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ - typedef TYPE NAME##_type; \ - extern thread_local NAME##_type NAME##_var; \ - \ - static inline NAME##_type * \ - NAME##_get_unsafe(void) \ - { \ - return (NAME##_type *)&NAME##_var; \ - } \ - \ - static inline NAME##_type * \ - NAME##_get(void) \ - { \ - return NAME##_get_unsafe(); \ - } -#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ - thread_local NAME##_type NAME##_var = __VA_ARGS__; -#else /* no C implementation support for thread-local storage */ -#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ - typedef TYPE NAME##_type; \ - static pthread_key_t NAME##_key; \ - \ - static NAME##_type * \ - NAME##_get_unsafe(void) \ - { \ - return pthread_getspecific(NAME##_key); \ - } \ - \ - static void \ - NAME##_once_init(void) \ - { \ - if (pthread_key_create(&NAME##_key, free)) { \ - abort(); \ - } \ - } \ - \ - static NAME##_type * \ - NAME##_get(void) \ - { \ - static pthread_once_t once = PTHREAD_ONCE_INIT; \ - NAME##_type *value; \ - \ - pthread_once(&once, NAME##_once_init); \ - value = NAME##_get_unsafe(); \ - if (!value) { \ - static const NAME##_type initial_value = __VA_ARGS__; \ - \ - value = xmalloc__(sizeof *value); \ - *value = initial_value; \ - xpthread_setspecific(NAME##_key, value); \ - } \ - return value; \ - } -#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ - typedef TYPE NAME##_type; \ - static pthread_key_t NAME##_key; \ - \ - static inline NAME##_type * \ - NAME##_get_unsafe(void) \ - { \ - return (NAME##_type *)pthread_getspecific(NAME##_key); \ - } \ - \ - NAME##_type *NAME##_get(void); -#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ - static void \ - NAME##_once_init(void) \ - { \ - if (pthread_key_create(&NAME##_key, free)) { \ - abort(); \ - } \ - } \ - \ - NAME##_type * \ - NAME##_get(void) \ - { \ - static pthread_once_t once = PTHREAD_ONCE_INIT; \ - NAME##_type *value; \ - \ - pthread_once(&once, NAME##_once_init); \ - value = NAME##_get_unsafe(); \ - if (!value) { \ - static const NAME##_type initial_value = __VA_ARGS__; \ - \ - value = xmalloc__(sizeof *value); \ - *value = initial_value; \ - xpthread_setspecific(NAME##_key, value); \ - } \ - return value; \ - } -#endif - -/* DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME). - * - * This is a simple wrapper around POSIX per-thread data primitives. It - * defines per-thread variable NAME with the given TYPE, which must be a - * pointer type. In each thread, the per-thread variable is initialized to - * NULL. When a thread terminates, the variable is freed with free(). - * - * The public interface to the variable is: - * - * TYPE NAME_get(void) - * TYPE NAME_get_unsafe(void) - * - * Returns the value of per-thread variable NAME in this thread. - * - * Use NAME_get() in a context where this might be the first use of the - * per-thread variable in the program. Use NAME_get_unsafe(), which - * avoids a conditional test and is thus slightly faster, in a context - * where one knows that NAME_get() has already been called previously. - * - * TYPE NAME_set(TYPE new_value) - * TYPE NAME_set_unsafe(TYPE new_value) - * - * Sets the value of per-thread variable NAME to 'new_value' in this - * thread, and returns its previous value. - * - * Use NAME_set() in a context where this might be the first use of the - * per-thread variable in the program. Use NAME_set_unsafe(), which - * avoids a conditional test and is thus slightly faster, in a context - * where one knows that NAME_set() has already been called previously. - */ -#define DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME) \ - static pthread_key_t NAME##_key; \ - \ - static void \ - NAME##_once_init(void) \ - { \ - if (pthread_key_create(&NAME##_key, free)) { \ - abort(); \ - } \ - } \ - \ - static void \ - NAME##_init(void) \ - { \ - static pthread_once_t once = PTHREAD_ONCE_INIT; \ - pthread_once(&once, NAME##_once_init); \ - } \ - \ - static TYPE \ - NAME##_get_unsafe(void) \ - { \ - return pthread_getspecific(NAME##_key); \ - } \ - \ - static OVS_UNUSED TYPE \ - NAME##_get(void) \ - { \ - NAME##_init(); \ - return NAME##_get_unsafe(); \ - } \ - \ - static TYPE \ - NAME##_set_unsafe(TYPE value) \ - { \ - TYPE old_value = NAME##_get_unsafe(); \ - xpthread_setspecific(NAME##_key, value); \ - return old_value; \ - } \ - \ - static OVS_UNUSED TYPE \ - NAME##_set(TYPE value) \ - { \ - NAME##_init(); \ - return NAME##_set_unsafe(value); \ - } - -/* Dynamically allocated thread-specific data with lots of slots. - * - * pthread_key_t can provide as few as 128 pieces of thread-specific data (even - * glibc is limited to 1,024). Thus, one must be careful to allocate only a - * few keys globally. One cannot, for example, allocate a key for every - * instance of a data structure if there might be an arbitrary number of those - * data structures. - * - * This API is similar to the pthread one (simply search and replace pthread_ - * by ovsthread_) but it a much larger limit that can be raised if necessary - * (by recompiling). Thus, one may more freely use this form of - * thread-specific data. - * - * ovsthread_key_t also differs from pthread_key_t in the following ways: - * - * - Destructors must not access thread-specific data (via ovsthread_key). - * - * - The pthread_key_t API allows concurrently exiting threads to start - * executing the destructor after pthread_key_delete() returns. The - * ovsthread_key_t API guarantees that, when ovsthread_key_delete() - * returns, all destructors have returned and no new ones will start - * execution. - */ -typedef struct ovsthread_key *ovsthread_key_t; - -void ovsthread_key_create(ovsthread_key_t *, void (*destructor)(void *)); -void ovsthread_key_delete(ovsthread_key_t); - -void ovsthread_setspecific(ovsthread_key_t, const void *); -void *ovsthread_getspecific(ovsthread_key_t); - -/* Thread ID. - * - * pthread_t isn't so nice for some purposes. Its size and representation are - * implementation dependent, which means that there is no way to hash it. - * This thread ID avoids the problem. - */ - -#define OVSTHREAD_ID_UNSET UINT_MAX -DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, ovsthread_id); - -/* Initializes the unique per thread identifier */ -unsigned int ovsthread_id_init(void); - -/* Returns a per-thread identifier unique within the lifetime of the - * process. */ -static inline unsigned int -ovsthread_id_self(void) -{ - unsigned int id = *ovsthread_id_get(); - - if (OVS_UNLIKELY(id == OVSTHREAD_ID_UNSET)) { - id = ovsthread_id_init(); - } - - return id; -} - -/* Simulated global counter. - * - * Incrementing such a counter is meant to be cheaper than incrementing a - * global counter protected by a lock. It is probably more expensive than - * incrementing a truly thread-local variable, but such a variable has no - * straightforward way to get the sum. - * - * - * Thread-safety - * ============= - * - * Fully thread-safe. */ - -struct ovsthread_stats { - struct ovs_mutex mutex; - void *volatile buckets[16]; -}; - -void ovsthread_stats_init(struct ovsthread_stats *); -void ovsthread_stats_destroy(struct ovsthread_stats *); - -void *ovsthread_stats_bucket_get(struct ovsthread_stats *, - void *(*new_bucket)(void)); - -#define OVSTHREAD_STATS_FOR_EACH_BUCKET(BUCKET, IDX, STATS) \ - for ((IDX) = ovs_thread_stats_next_bucket(STATS, 0); \ - ((IDX) < ARRAY_SIZE((STATS)->buckets) \ - ? ((BUCKET) = (STATS)->buckets[IDX], true) \ - : false); \ - (IDX) = ovs_thread_stats_next_bucket(STATS, (IDX) + 1)) -size_t ovs_thread_stats_next_bucket(const struct ovsthread_stats *, size_t); - -bool single_threaded(void); - -void assert_single_threaded_at(const char *where); -#define assert_single_threaded() assert_single_threaded_at(OVS_SOURCE_LOCATOR) - -#ifndef _WIN32 -pid_t xfork_at(const char *where); -#define xfork() xfork_at(OVS_SOURCE_LOCATOR) -#endif - -void forbid_forking(const char *reason); -bool may_fork(void); - -/* Useful functions related to threading. */ - -int count_cpu_cores(void); -bool thread_is_pmd(void); - -#endif /* ovs-thread.h */ Index: openvswitch-2.17.2/include/openvswitch/ovs-thread.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovs-thread.h @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OVS_THREAD_H +#define OVS_THREAD_H 1 + +#include +#include +#include +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/thread.h" +#include "internal/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct seq; + +/* Poll-block()-able barrier similar to pthread_barrier_t. */ +struct ovs_barrier_impl; +struct ovs_barrier { + OVSRCU_TYPE(struct ovs_barrier_impl *) impl; +}; + +/* Wrappers for pthread_mutexattr_*() that abort the process on any error. */ +void xpthread_mutexattr_init(pthread_mutexattr_t *); +void xpthread_mutexattr_destroy(pthread_mutexattr_t *); +void xpthread_mutexattr_settype(pthread_mutexattr_t *, int type); +void xpthread_mutexattr_gettype(pthread_mutexattr_t *, int *typep); + +/* Read-write lock. + * + * An ovs_rwlock does not support recursive readers, because POSIX allows + * taking the reader lock recursively to deadlock when a thread is waiting on + * the write-lock. (NetBSD does deadlock.) glibc rwlocks in their default + * configuration do not deadlock, but ovs_rwlock_init() initializes rwlocks as + * non-recursive (which will deadlock) for two reasons: + * + * - glibc only provides fairness to writers in this mode. + * + * - It's better to find bugs in the primary Open vSwitch target rather + * than exposing them only to porters. */ +struct OVS_LOCKABLE ovs_rwlock { + pthread_rwlock_t lock; + const char *where; /* NULL if and only if uninitialized. */ +}; + +/* Initializer. */ +#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP +#define OVS_RWLOCK_INITIALIZER \ + { PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP, "" } +#else +#define OVS_RWLOCK_INITIALIZER { PTHREAD_RWLOCK_INITIALIZER, "" } +#endif + +/* ovs_rwlock functions analogous to pthread_rwlock_*() functions. + * + * Most of these functions abort the process with an error message on any + * error. The "trylock" functions are exception: they pass through a 0 or + * EBUSY return value to the caller and abort on any other error. */ +void ovs_rwlock_init(const struct ovs_rwlock *); +void ovs_rwlock_destroy(const struct ovs_rwlock *); +void ovs_rwlock_unlock(const struct ovs_rwlock *rwlock) OVS_RELEASES(rwlock); + +/* Wrappers for pthread_rwlockattr_*() that abort the process on any error. */ +void xpthread_rwlockattr_init(pthread_rwlockattr_t *); +void xpthread_rwlockattr_destroy(pthread_rwlockattr_t *); +#ifdef PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP +void xpthread_rwlockattr_setkind_np(pthread_rwlockattr_t *, int kind); +#endif + +void ovs_rwlock_wrlock_at(const struct ovs_rwlock *rwlock, const char *where) + OVS_ACQ_WRLOCK(rwlock); +#define ovs_rwlock_wrlock(rwlock) \ + ovs_rwlock_wrlock_at(rwlock, OVS_SOURCE_LOCATOR) + +int ovs_rwlock_trywrlock_at(const struct ovs_rwlock *rwlock, const char *where) + OVS_TRY_WRLOCK(0, rwlock); +#define ovs_rwlock_trywrlock(rwlock) \ + ovs_rwlock_trywrlock_at(rwlock, OVS_SOURCE_LOCATOR) + +void ovs_rwlock_rdlock_at(const struct ovs_rwlock *rwlock, const char *where) + OVS_ACQ_RDLOCK(rwlock); +#define ovs_rwlock_rdlock(rwlock) \ + ovs_rwlock_rdlock_at(rwlock, OVS_SOURCE_LOCATOR) + +int ovs_rwlock_tryrdlock_at(const struct ovs_rwlock *rwlock, const char *where) + OVS_TRY_RDLOCK(0, rwlock); +#define ovs_rwlock_tryrdlock(rwlock) \ + ovs_rwlock_tryrdlock_at(rwlock, OVS_SOURCE_LOCATOR) + +/* ovs_barrier functions analogous to pthread_barrier_*() functions. */ +void ovs_barrier_init(struct ovs_barrier *, uint32_t count); +void ovs_barrier_destroy(struct ovs_barrier *); +void ovs_barrier_block(struct ovs_barrier *); + +/* Wrappers for xpthread_cond_*() that abort the process on any error. + * + * Use ovs_mutex_cond_wait() to wait for a condition. */ +void xpthread_cond_init(pthread_cond_t *, pthread_condattr_t *); +void xpthread_cond_destroy(pthread_cond_t *); +void xpthread_cond_signal(pthread_cond_t *); +void xpthread_cond_broadcast(pthread_cond_t *); + +void xpthread_key_create(pthread_key_t *, void (*destructor)(void *)); +void xpthread_key_delete(pthread_key_t); +void xpthread_setspecific(pthread_key_t, const void *); + +#ifndef _WIN32 +void xpthread_sigmask(int, const sigset_t *, sigset_t *); +#endif + +pthread_t ovs_thread_create(const char *name, void *(*)(void *), void *); +void xpthread_join(pthread_t, void **); + +/* Per-thread data. + * + * + * Standard Forms + * ============== + * + * Multiple forms of standard per-thread data exist, each with its own pluses + * and minuses. In general, if one of these forms is appropriate, then it's a + * good idea to use it: + * + * - POSIX per-thread data via pthread_key_t is portable to any pthreads + * implementation, and allows a destructor function to be defined. It + * only (directly) supports per-thread pointers, which are always + * initialized to NULL. It requires once-only allocation of a + * pthread_key_t value. It is relatively slow. Typically few + * "pthread_key_t"s are available (POSIX requires only at least 128, + * glibc supplies only 1024). + * + * - The thread_local feature newly defined in C11 works with + * any data type and initializer, and it is fast. thread_local does not + * require once-only initialization like pthread_key_t. C11 does not + * define what happens if one attempts to access a thread_local object + * from a thread other than the one to which that object belongs. There + * is no provision to call a user-specified destructor when a thread + * ends. Typical implementations allow for an arbitrary amount of + * thread_local storage, but statically allocated only. + * + * - The __thread keyword is a GCC extension similar to thread_local but + * with a longer history. __thread is not portable to every GCC version + * or environment. __thread does not restrict the use of a thread-local + * object outside its own thread. + * + * Here's a handy summary: + * + * pthread_key_t thread_local __thread + * ------------- ------------ ------------- + * portability high low medium + * speed low high high + * supports destructors? yes no no + * needs key allocation? yes no no + * arbitrary initializer? no yes yes + * cross-thread access? yes no yes + * amount available? few arbitrary arbitrary + * dynamically allocated? yes no no + * + * + * Extensions + * ========== + * + * OVS provides some extensions and wrappers: + * + * - In a situation where the performance of thread_local or __thread is + * desirable, but portability is required, DEFINE_STATIC_PER_THREAD_DATA + * and DECLARE_EXTERN_PER_THREAD_DATA/DEFINE_EXTERN_PER_THREAD_DATA may + * be appropriate (see below). + * + * - DEFINE_PER_THREAD_MALLOCED_DATA can be convenient for simple + * per-thread malloc()'d buffers. + * + * - struct ovs_tsd provides an alternative to pthread_key_t that isn't + * limited to a small number of keys. + */ + +/* For static data, use this macro in a source file: + * + * DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, INITIALIZER). + * + * For global data, "declare" the data in the header and "define" it in + * the source file, with: + * + * DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME). + * DEFINE_EXTERN_PER_THREAD_DATA(NAME, INITIALIZER). + * + * One should prefer to use POSIX per-thread data, via pthread_key_t, when its + * performance is acceptable, because of its portability (see the table above). + * This macro is an alternatives that takes advantage of thread_local (and + * __thread), for its performance, when it is available, and falls back to + * POSIX per-thread data otherwise. + * + * Defines per-thread variable NAME with the given TYPE, initialized to + * INITIALIZER (which must be valid as an initializer for a variable with + * static lifetime). + * + * The public interface to the variable is: + * + * TYPE *NAME_get(void) + * TYPE *NAME_get_unsafe(void) + * + * Returns the address of this thread's instance of NAME. + * + * Use NAME_get() in a context where this might be the first use of the + * per-thread variable in the program. Use NAME_get_unsafe(), which + * avoids a conditional test and is thus slightly faster, in a context + * where one knows that NAME_get() has already been called previously. + * + * There is no "NAME_set()" (or "NAME_set_unsafe()") function. To set the + * value of the per-thread variable, dereference the pointer returned by + * TYPE_get() or TYPE_get_unsafe(), e.g. *TYPE_get() = 0. + */ +#if HAVE_THREAD_LOCAL || HAVE___THREAD + +#if HAVE_THREAD_LOCAL +#include +#elif HAVE___THREAD +#define thread_local __thread +#else +#error +#endif + +#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ + typedef TYPE NAME##_type; \ + \ + static NAME##_type * \ + NAME##_get_unsafe(void) \ + { \ + static thread_local NAME##_type var = __VA_ARGS__; \ + return &var; \ + } \ + \ + static NAME##_type * \ + NAME##_get(void) \ + { \ + return NAME##_get_unsafe(); \ + } +#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ + typedef TYPE NAME##_type; \ + extern thread_local NAME##_type NAME##_var; \ + \ + static inline NAME##_type * \ + NAME##_get_unsafe(void) \ + { \ + return (NAME##_type *)&NAME##_var; \ + } \ + \ + static inline NAME##_type * \ + NAME##_get(void) \ + { \ + return NAME##_get_unsafe(); \ + } +#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ + thread_local NAME##_type NAME##_var = __VA_ARGS__; +#else /* no C implementation support for thread-local storage */ +#define DEFINE_STATIC_PER_THREAD_DATA(TYPE, NAME, ...) \ + typedef TYPE NAME##_type; \ + static pthread_key_t NAME##_key; \ + \ + static NAME##_type * \ + NAME##_get_unsafe(void) \ + { \ + return pthread_getspecific(NAME##_key); \ + } \ + \ + static void \ + NAME##_once_init(void) \ + { \ + if (pthread_key_create(&NAME##_key, free)) { \ + abort(); \ + } \ + } \ + \ + static NAME##_type * \ + NAME##_get(void) \ + { \ + static pthread_once_t once = PTHREAD_ONCE_INIT; \ + NAME##_type *value; \ + \ + pthread_once(&once, NAME##_once_init); \ + value = NAME##_get_unsafe(); \ + if (!value) { \ + static const NAME##_type initial_value = __VA_ARGS__; \ + \ + value = xmalloc__(sizeof *value); \ + *value = initial_value; \ + xpthread_setspecific(NAME##_key, value); \ + } \ + return value; \ + } +#define DECLARE_EXTERN_PER_THREAD_DATA(TYPE, NAME) \ + typedef TYPE NAME##_type; \ + static pthread_key_t NAME##_key; \ + \ + static inline NAME##_type * \ + NAME##_get_unsafe(void) \ + { \ + return (NAME##_type *)pthread_getspecific(NAME##_key); \ + } \ + \ + NAME##_type *NAME##_get(void); +#define DEFINE_EXTERN_PER_THREAD_DATA(NAME, ...) \ + static void \ + NAME##_once_init(void) \ + { \ + if (pthread_key_create(&NAME##_key, free)) { \ + abort(); \ + } \ + } \ + \ + NAME##_type * \ + NAME##_get(void) \ + { \ + static pthread_once_t once = PTHREAD_ONCE_INIT; \ + NAME##_type *value; \ + \ + pthread_once(&once, NAME##_once_init); \ + value = NAME##_get_unsafe(); \ + if (!value) { \ + static const NAME##_type initial_value = __VA_ARGS__; \ + \ + value = xmalloc__(sizeof *value); \ + *value = initial_value; \ + xpthread_setspecific(NAME##_key, value); \ + } \ + return value; \ + } +#endif + +/* DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME). + * + * This is a simple wrapper around POSIX per-thread data primitives. It + * defines per-thread variable NAME with the given TYPE, which must be a + * pointer type. In each thread, the per-thread variable is initialized to + * NULL. When a thread terminates, the variable is freed with free(). + * + * The public interface to the variable is: + * + * TYPE NAME_get(void) + * TYPE NAME_get_unsafe(void) + * + * Returns the value of per-thread variable NAME in this thread. + * + * Use NAME_get() in a context where this might be the first use of the + * per-thread variable in the program. Use NAME_get_unsafe(), which + * avoids a conditional test and is thus slightly faster, in a context + * where one knows that NAME_get() has already been called previously. + * + * TYPE NAME_set(TYPE new_value) + * TYPE NAME_set_unsafe(TYPE new_value) + * + * Sets the value of per-thread variable NAME to 'new_value' in this + * thread, and returns its previous value. + * + * Use NAME_set() in a context where this might be the first use of the + * per-thread variable in the program. Use NAME_set_unsafe(), which + * avoids a conditional test and is thus slightly faster, in a context + * where one knows that NAME_set() has already been called previously. + */ +#define DEFINE_PER_THREAD_MALLOCED_DATA(TYPE, NAME) \ + static pthread_key_t NAME##_key; \ + \ + static void \ + NAME##_once_init(void) \ + { \ + if (pthread_key_create(&NAME##_key, free)) { \ + abort(); \ + } \ + } \ + \ + static void \ + NAME##_init(void) \ + { \ + static pthread_once_t once = PTHREAD_ONCE_INIT; \ + pthread_once(&once, NAME##_once_init); \ + } \ + \ + static TYPE \ + NAME##_get_unsafe(void) \ + { \ + return pthread_getspecific(NAME##_key); \ + } \ + \ + static OVS_UNUSED TYPE \ + NAME##_get(void) \ + { \ + NAME##_init(); \ + return NAME##_get_unsafe(); \ + } \ + \ + static TYPE \ + NAME##_set_unsafe(TYPE value) \ + { \ + TYPE old_value = NAME##_get_unsafe(); \ + xpthread_setspecific(NAME##_key, value); \ + return old_value; \ + } \ + \ + static OVS_UNUSED TYPE \ + NAME##_set(TYPE value) \ + { \ + NAME##_init(); \ + return NAME##_set_unsafe(value); \ + } + +/* Dynamically allocated thread-specific data with lots of slots. + * + * pthread_key_t can provide as few as 128 pieces of thread-specific data (even + * glibc is limited to 1,024). Thus, one must be careful to allocate only a + * few keys globally. One cannot, for example, allocate a key for every + * instance of a data structure if there might be an arbitrary number of those + * data structures. + * + * This API is similar to the pthread one (simply search and replace pthread_ + * by ovsthread_) but it a much larger limit that can be raised if necessary + * (by recompiling). Thus, one may more freely use this form of + * thread-specific data. + * + * ovsthread_key_t also differs from pthread_key_t in the following ways: + * + * - Destructors must not access thread-specific data (via ovsthread_key). + * + * - The pthread_key_t API allows concurrently exiting threads to start + * executing the destructor after pthread_key_delete() returns. The + * ovsthread_key_t API guarantees that, when ovsthread_key_delete() + * returns, all destructors have returned and no new ones will start + * execution. + */ +typedef struct ovsthread_key *ovsthread_key_t; + +void ovsthread_key_create(ovsthread_key_t *, void (*destructor)(void *)); +void ovsthread_key_delete(ovsthread_key_t); + +void ovsthread_setspecific(ovsthread_key_t, const void *); +void *ovsthread_getspecific(ovsthread_key_t); + +/* Thread ID. + * + * pthread_t isn't so nice for some purposes. Its size and representation are + * implementation dependent, which means that there is no way to hash it. + * This thread ID avoids the problem. + */ + +#define OVSTHREAD_ID_UNSET UINT_MAX +DECLARE_EXTERN_PER_THREAD_DATA(unsigned int, ovsthread_id); + +/* Initializes the unique per thread identifier */ +unsigned int ovsthread_id_init(void); + +/* Returns a per-thread identifier unique within the lifetime of the + * process. */ +static inline unsigned int +ovsthread_id_self(void) +{ + unsigned int id = *ovsthread_id_get(); + + if (OVS_UNLIKELY(id == OVSTHREAD_ID_UNSET)) { + id = ovsthread_id_init(); + } + + return id; +} + +/* Simulated global counter. + * + * Incrementing such a counter is meant to be cheaper than incrementing a + * global counter protected by a lock. It is probably more expensive than + * incrementing a truly thread-local variable, but such a variable has no + * straightforward way to get the sum. + * + * + * Thread-safety + * ============= + * + * Fully thread-safe. */ + +struct ovsthread_stats { + struct ovs_mutex mutex; + void *volatile buckets[16]; +}; + +void ovsthread_stats_init(struct ovsthread_stats *); +void ovsthread_stats_destroy(struct ovsthread_stats *); + +void *ovsthread_stats_bucket_get(struct ovsthread_stats *, + void *(*new_bucket)(void)); + +#define OVSTHREAD_STATS_FOR_EACH_BUCKET(BUCKET, IDX, STATS) \ + for ((IDX) = ovs_thread_stats_next_bucket(STATS, 0); \ + ((IDX) < ARRAY_SIZE((STATS)->buckets) \ + ? ((BUCKET) = (STATS)->buckets[IDX], true) \ + : false); \ + (IDX) = ovs_thread_stats_next_bucket(STATS, (IDX) + 1)) +size_t ovs_thread_stats_next_bucket(const struct ovsthread_stats *, size_t); + +bool single_threaded(void); + +void assert_single_threaded_at(const char *where); +#define assert_single_threaded() assert_single_threaded_at(OVS_SOURCE_LOCATOR) + +#ifndef _WIN32 +pid_t xfork_at(const char *where); +#define xfork() xfork_at(OVS_SOURCE_LOCATOR) +#endif + +void forbid_forking(const char *reason); +bool may_fork(void); + +/* Useful functions related to threading. */ + +int count_cpu_cores(void); +bool thread_is_pmd(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ovs-thread.h */ Index: openvswitch-2.17.2/lib/ovsdb-condition.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-condition.h +++ /dev/null @@ -1,45 +0,0 @@ -/* 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. - */ - -#ifndef OVSDB_LIB_CONDITION_H -#define OVSDB_LIB_CONDITION_H 1 - -/* These list is ordered first with boolean functions and then in - * ascending order of the fraction of tables row that they are - * (heuristically) expected to leave in query results. */ -#define OVSDB_FUNCTIONS \ - OVSDB_FUNCTION(OVSDB_F_FALSE, "false") \ - OVSDB_FUNCTION(OVSDB_F_TRUE, "true") \ - OVSDB_FUNCTION(OVSDB_F_EQ, "==") \ - OVSDB_FUNCTION(OVSDB_F_INCLUDES, "includes") \ - OVSDB_FUNCTION(OVSDB_F_LE, "<=") \ - OVSDB_FUNCTION(OVSDB_F_LT, "<") \ - OVSDB_FUNCTION(OVSDB_F_GE, ">=") \ - OVSDB_FUNCTION(OVSDB_F_GT, ">") \ - OVSDB_FUNCTION(OVSDB_F_EXCLUDES, "excludes") \ - OVSDB_FUNCTION(OVSDB_F_NE, "!=") - -enum ovsdb_function { -#define OVSDB_FUNCTION(ENUM, NAME) ENUM, - OVSDB_FUNCTIONS -#undef OVSDB_FUNCTION - OVSDB_F_LAST = OVSDB_F_NE -}; - -struct ovsdb_error * ovsdb_function_from_string(const char *name, - enum ovsdb_function *function); -const char * ovsdb_function_to_string(enum ovsdb_function function); - -#endif /* ovsdb-condition.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-condition.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-condition.h @@ -0,0 +1,53 @@ +/* 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. + */ + +#ifndef OVSDB_LIB_CONDITION_H +#define OVSDB_LIB_CONDITION_H 1 + +/* These list is ordered first with boolean functions and then in + * ascending order of the fraction of tables row that they are + * (heuristically) expected to leave in query results. */ +#define OVSDB_FUNCTIONS \ + OVSDB_FUNCTION(OVSDB_F_FALSE, "false") \ + OVSDB_FUNCTION(OVSDB_F_TRUE, "true") \ + OVSDB_FUNCTION(OVSDB_F_EQ, "==") \ + OVSDB_FUNCTION(OVSDB_F_INCLUDES, "includes") \ + OVSDB_FUNCTION(OVSDB_F_LE, "<=") \ + OVSDB_FUNCTION(OVSDB_F_LT, "<") \ + OVSDB_FUNCTION(OVSDB_F_GE, ">=") \ + OVSDB_FUNCTION(OVSDB_F_GT, ">") \ + OVSDB_FUNCTION(OVSDB_F_EXCLUDES, "excludes") \ + OVSDB_FUNCTION(OVSDB_F_NE, "!=") + +#ifdef __cplusplus +extern "C" { +#endif + +enum ovsdb_function { +#define OVSDB_FUNCTION(ENUM, NAME) ENUM, + OVSDB_FUNCTIONS +#undef OVSDB_FUNCTION + OVSDB_F_LAST = OVSDB_F_NE +}; + +struct ovsdb_error * ovsdb_function_from_string(const char *name, + enum ovsdb_function *function); +const char * ovsdb_function_to_string(enum ovsdb_function function); + +#ifdef __cplusplus +} // extern "C" { +#endif + +#endif /* ovsdb-condition.h */ Index: openvswitch-2.17.2/lib/ovsdb-cs.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-cs.h +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc. - * Copyright (C) 2016 Hewlett Packard Enterprise Development LP - * - * 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 OVSDB_CS_H -#define OVSDB_CS_H 1 - -/* Open vSwitch Database client synchronization layer. - * - * This is a base layer for maintaining an in-memory replica of a database. It - * issues RPC requests to an OVSDB database server and passes the semantically - * meaningful parts of the stream up to a higher layer. The OVSDB IDL uses - * this as a base layer, as well as OVN's DDlog-based northd implementation. - */ - -#include -#include "openvswitch/hmap.h" -#include "openvswitch/list.h" -#include "openvswitch/shash.h" -#include "openvswitch/uuid.h" - -struct json; -struct ovsdb_cs; - -struct ovsdb_cs_ops { - /* Returns to use for the specified . The - * implementation might find ovsdb_cs_parse_table_updates() to be a useful - * helper. - * - * The caller might actually use "monitor_cond" or "monitor_cond_since", - * rather than plain "monitor". If so, this function's implementation - * doesn't need to worry about that, because the caller will add the - * conditions itself. */ - struct json *(*compose_monitor_requests)(const struct json *schema, - void *aux); -}; - -/* An event is a happening that is worth reporting to the CS client. - * - * Currently there are three kinds of events: - * - * - "Reconnect": The connection to the database was lost and it is now - * being reconnected. This means that any transactions submitted by the - * client will never receive a reply (although it's possible that some of - * them were actually committed). This event has no associated data. - * - * - "Locked": The server granted the lock we requested. - * - * - "Update": The server sent an update to one or more monitored tables. - * The client can use the associated data to update its idea of the - * snapshot. - * - * - "Transaction reply": The server sent a reply to a transaction sent by - * the client using ovsdb_cs_send_transaction(). - */ -struct ovsdb_cs_event { - struct ovs_list list_node; - - enum ovsdb_cs_event_type { - OVSDB_CS_EVENT_TYPE_RECONNECT, /* Connection lost. */ - OVSDB_CS_EVENT_TYPE_LOCKED, /* Got the lock we wanted. */ - OVSDB_CS_EVENT_TYPE_UPDATE, /* Received update notification. */ - OVSDB_CS_EVENT_TYPE_TXN_REPLY, /* Received reply to transaction. */ - } type; - - union { - /* Represents a or that contains - * either the initial data in a monitor reply or a delta received in an - * update notification. The client can use this to update its database - * replica. - * - * If 'clear' is true, then the client should first clear its idea of - * what's in the replica before applying the update; otherwise, it's an - * incremental update. - * - * If 'monitor_reply' is true, then this comes from a monitor reply. - * This doesn't have real semantic meaning, but it allows the caller - * to imitate the exact behavior of previous versions of code that - * behaved differently on updates from monitor replies vs. updates. - * - * 'table-updates' is a if 'version' if 1, otherwise a - * . The client can use ovsdb_cs_parse_table_updates() - * to parse the update. - */ - struct ovsdb_cs_update_event { - bool clear; - bool monitor_reply; - struct json *table_updates; - int version; - } update; - - /* The "result" member from a transaction reply. The transaction is - * one sent by the client using ovsdb_cs_send_transaction(). The - * client can match 'txn_reply->id' against the ID in a transaction it - * sent. */ - struct jsonrpc_msg *txn_reply; - }; -}; -void ovsdb_cs_event_destroy(struct ovsdb_cs_event *); - -/* Lifecycle. */ -struct ovsdb_cs *ovsdb_cs_create(const char *database, int max_version, - const struct ovsdb_cs_ops *ops, - void *ops_aux); -void ovsdb_cs_destroy(struct ovsdb_cs *); - -void ovsdb_cs_run(struct ovsdb_cs *, struct ovs_list *events); -void ovsdb_cs_wait(struct ovsdb_cs *); - -/* Network connection. */ -void ovsdb_cs_set_remote(struct ovsdb_cs *, const char *remote, bool retry); - -void ovsdb_cs_enable_reconnect(struct ovsdb_cs *); -void ovsdb_cs_force_reconnect(struct ovsdb_cs *); -void ovsdb_cs_flag_inconsistency(struct ovsdb_cs *); - -bool ovsdb_cs_is_alive(const struct ovsdb_cs *); -bool ovsdb_cs_is_connected(const struct ovsdb_cs *); -int ovsdb_cs_get_last_error(const struct ovsdb_cs *); - -void ovsdb_cs_set_probe_interval(const struct ovsdb_cs *, int probe_interval); - -/* Conditional monitoring (specifying that only rows matching particular - * criteria should be monitored). - * - * Some database servers don't support conditional monitoring; in that case, - * the client will get all the rows. */ -unsigned int ovsdb_cs_set_condition(struct ovsdb_cs *, const char *table, - const struct json *condition); -unsigned int ovsdb_cs_get_condition_seqno(const struct ovsdb_cs *); - -/* Clustered servers. */ -void ovsdb_cs_set_leader_only(struct ovsdb_cs *, bool leader_only); -void ovsdb_cs_set_shuffle_remotes(struct ovsdb_cs *, bool shuffle); -void ovsdb_cs_reset_min_index(struct ovsdb_cs *); - -/* Database locks. */ -void ovsdb_cs_set_lock(struct ovsdb_cs *, const char *lock_name); -const char *ovsdb_cs_get_lock(const struct ovsdb_cs *); -bool ovsdb_cs_has_lock(const struct ovsdb_cs *); -bool ovsdb_cs_is_lock_contended(const struct ovsdb_cs *); - -/* Transactions. */ -bool ovsdb_cs_may_send_transaction(const struct ovsdb_cs *); -struct json *ovsdb_cs_send_transaction(struct ovsdb_cs *, struct json *ops) - OVS_WARN_UNUSED_RESULT; -bool ovsdb_cs_forget_transaction(struct ovsdb_cs *, const struct json *); - -/* Helper for partially parsing the or that - * appear in struct ovsdb_cs_update_event. The helper leaves the data in JSON - * format, so it doesn't need to know column types. */ - -/* The kind of change to a row. */ -enum ovsdb_cs_row_update_type { - OVSDB_CS_ROW_DELETE, /* Row deletion. */ - OVSDB_CS_ROW_INSERT, /* Row insertion. */ - OVSDB_CS_ROW_UPDATE, /* Replacement of data within a row. */ - OVSDB_CS_ROW_XOR /* diff application. */ -}; - -/* Partially parsed or . */ -struct ovsdb_cs_row_update { - struct uuid row_uuid; /* Row's _uuid. */ - enum ovsdb_cs_row_update_type type; /* Type of change. */ - const struct shash *columns; /* Map from column name to json data. */ -}; - -/* Partially parsed or . */ -struct ovsdb_cs_table_update { - const char *table_name; - struct ovsdb_cs_row_update *row_updates; - size_t n; -}; - -struct ovsdb_cs_db_update { - struct ovsdb_cs_table_update *table_updates; - size_t n; -}; - -struct ovsdb_error *ovsdb_cs_parse_db_update( - const struct json *table_updates, int version, - struct ovsdb_cs_db_update **db_updatep) - OVS_WARN_UNUSED_RESULT; -void ovsdb_cs_db_update_destroy(struct ovsdb_cs_db_update *); -const struct ovsdb_cs_table_update *ovsdb_cs_db_update_find_table( - const struct ovsdb_cs_db_update *, const char *table_name); - -/* Simple parsing of OVSDB schemas for use by ovsdb_cs clients. */ - -struct shash *ovsdb_cs_parse_schema(const struct json *schema_json); -void ovsdb_cs_free_schema(struct shash *schema); - -#endif /* ovsdb-cs.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-cs.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-cs.h @@ -0,0 +1,213 @@ +/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 Nicira, Inc. + * Copyright (C) 2016 Hewlett Packard Enterprise Development LP + * + * 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 OVSDB_CS_H +#define OVSDB_CS_H 1 + +/* Open vSwitch Database client synchronization layer. + * + * This is a base layer for maintaining an in-memory replica of a database. It + * issues RPC requests to an OVSDB database server and passes the semantically + * meaningful parts of the stream up to a higher layer. The OVSDB IDL uses + * this as a base layer, as well as OVN's DDlog-based northd implementation. + */ + +#include +#include "openvswitch/hmap.h" +#include "openvswitch/list.h" +#include "openvswitch/shash.h" +#include "openvswitch/uuid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct json; +struct ovsdb_cs; + +struct ovsdb_cs_ops { + /* Returns to use for the specified . The + * implementation might find ovsdb_cs_parse_table_updates() to be a useful + * helper. + * + * The caller might actually use "monitor_cond" or "monitor_cond_since", + * rather than plain "monitor". If so, this function's implementation + * doesn't need to worry about that, because the caller will add the + * conditions itself. */ + struct json *(*compose_monitor_requests)(const struct json *schema, + void *aux); +}; + +/* An event is a happening that is worth reporting to the CS client. + * + * Currently there are three kinds of events: + * + * - "Reconnect": The connection to the database was lost and it is now + * being reconnected. This means that any transactions submitted by the + * client will never receive a reply (although it's possible that some of + * them were actually committed). This event has no associated data. + * + * - "Locked": The server granted the lock we requested. + * + * - "Update": The server sent an update to one or more monitored tables. + * The client can use the associated data to update its idea of the + * snapshot. + * + * - "Transaction reply": The server sent a reply to a transaction sent by + * the client using ovsdb_cs_send_transaction(). + */ +struct ovsdb_cs_event { + struct ovs_list list_node; + + enum ovsdb_cs_event_type { + OVSDB_CS_EVENT_TYPE_RECONNECT, /* Connection lost. */ + OVSDB_CS_EVENT_TYPE_LOCKED, /* Got the lock we wanted. */ + OVSDB_CS_EVENT_TYPE_UPDATE, /* Received update notification. */ + OVSDB_CS_EVENT_TYPE_TXN_REPLY, /* Received reply to transaction. */ + } type; + + union { + /* Represents a or that contains + * either the initial data in a monitor reply or a delta received in an + * update notification. The client can use this to update its database + * replica. + * + * If 'clear' is true, then the client should first clear its idea of + * what's in the replica before applying the update; otherwise, it's an + * incremental update. + * + * If 'monitor_reply' is true, then this comes from a monitor reply. + * This doesn't have real semantic meaning, but it allows the caller + * to imitate the exact behavior of previous versions of code that + * behaved differently on updates from monitor replies vs. updates. + * + * 'table-updates' is a if 'version' if 1, otherwise a + * . The client can use ovsdb_cs_parse_table_updates() + * to parse the update. + */ + struct ovsdb_cs_update_event { + bool clear; + bool monitor_reply; + struct json *table_updates; + int version; + } update; + + /* The "result" member from a transaction reply. The transaction is + * one sent by the client using ovsdb_cs_send_transaction(). The + * client can match 'txn_reply->id' against the ID in a transaction it + * sent. */ + struct jsonrpc_msg *txn_reply; + }; +}; +void ovsdb_cs_event_destroy(struct ovsdb_cs_event *); + +/* Lifecycle. */ +struct ovsdb_cs *ovsdb_cs_create(const char *database, int max_version, + const struct ovsdb_cs_ops *ops, + void *ops_aux); +void ovsdb_cs_destroy(struct ovsdb_cs *); + +void ovsdb_cs_run(struct ovsdb_cs *, struct ovs_list *events); +void ovsdb_cs_wait(struct ovsdb_cs *); + +/* Network connection. */ +void ovsdb_cs_set_remote(struct ovsdb_cs *, const char *remote, bool retry); + +void ovsdb_cs_enable_reconnect(struct ovsdb_cs *); +void ovsdb_cs_force_reconnect(struct ovsdb_cs *); +void ovsdb_cs_flag_inconsistency(struct ovsdb_cs *); + +bool ovsdb_cs_is_alive(const struct ovsdb_cs *); +bool ovsdb_cs_is_connected(const struct ovsdb_cs *); +int ovsdb_cs_get_last_error(const struct ovsdb_cs *); + +void ovsdb_cs_set_probe_interval(const struct ovsdb_cs *, int probe_interval); + +/* Conditional monitoring (specifying that only rows matching particular + * criteria should be monitored). + * + * Some database servers don't support conditional monitoring; in that case, + * the client will get all the rows. */ +unsigned int ovsdb_cs_set_condition(struct ovsdb_cs *, const char *table, + const struct json *condition); +unsigned int ovsdb_cs_get_condition_seqno(const struct ovsdb_cs *); + +/* Clustered servers. */ +void ovsdb_cs_set_leader_only(struct ovsdb_cs *, bool leader_only); +void ovsdb_cs_set_shuffle_remotes(struct ovsdb_cs *, bool shuffle); +void ovsdb_cs_reset_min_index(struct ovsdb_cs *); + +/* Database locks. */ +void ovsdb_cs_set_lock(struct ovsdb_cs *, const char *lock_name); +const char *ovsdb_cs_get_lock(const struct ovsdb_cs *); +bool ovsdb_cs_has_lock(const struct ovsdb_cs *); +bool ovsdb_cs_is_lock_contended(const struct ovsdb_cs *); + +/* Transactions. */ +bool ovsdb_cs_may_send_transaction(const struct ovsdb_cs *); +struct json *ovsdb_cs_send_transaction(struct ovsdb_cs *, struct json *ops) + OVS_WARN_UNUSED_RESULT; +bool ovsdb_cs_forget_transaction(struct ovsdb_cs *, const struct json *); + +/* Helper for partially parsing the or that + * appear in struct ovsdb_cs_update_event. The helper leaves the data in JSON + * format, so it doesn't need to know column types. */ + +/* The kind of change to a row. */ +enum ovsdb_cs_row_update_type { + OVSDB_CS_ROW_DELETE, /* Row deletion. */ + OVSDB_CS_ROW_INSERT, /* Row insertion. */ + OVSDB_CS_ROW_UPDATE, /* Replacement of data within a row. */ + OVSDB_CS_ROW_XOR /* diff application. */ +}; + +/* Partially parsed or . */ +struct ovsdb_cs_row_update { + struct uuid row_uuid; /* Row's _uuid. */ + enum ovsdb_cs_row_update_type type; /* Type of change. */ + const struct shash *columns; /* Map from column name to json data. */ +}; + +/* Partially parsed or . */ +struct ovsdb_cs_table_update { + const char *table_name; + struct ovsdb_cs_row_update *row_updates; + size_t n; +}; + +struct ovsdb_cs_db_update { + struct ovsdb_cs_table_update *table_updates; + size_t n; +}; + +struct ovsdb_error *ovsdb_cs_parse_db_update( + const struct json *table_updates, int version, + struct ovsdb_cs_db_update **db_updatep) + OVS_WARN_UNUSED_RESULT; +void ovsdb_cs_db_update_destroy(struct ovsdb_cs_db_update *); +const struct ovsdb_cs_table_update *ovsdb_cs_db_update_find_table( + const struct ovsdb_cs_db_update *, const char *table_name); + +/* Simple parsing of OVSDB schemas for use by ovsdb_cs clients. */ + +struct shash *ovsdb_cs_parse_schema(const struct json *schema_json); +void ovsdb_cs_free_schema(struct shash *schema); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ovsdb-cs.h */ Index: openvswitch-2.17.2/lib/ovsdb-data.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-data.h +++ /dev/null @@ -1,339 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 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. - */ - -#ifndef OVSDB_DATA_H -#define OVSDB_DATA_H 1 - -#include -#include "openvswitch/compiler.h" -#include "ovsdb-types.h" -#include "openvswitch/json.h" -#include "openvswitch/shash.h" -#include "util.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define MAX_OVSDB_ATOM_RANGE_SIZE 4096 - -struct ds; -struct ovsdb_symbol_table; -struct smap; - -static inline struct json * -ovsdb_atom_string_create_nocopy(char *str) -{ - return json_string_create_nocopy(str); -} - -static inline struct json * -ovsdb_atom_string_create(const char *str) -{ - return json_string_create(str); -} - -/* One value of an atomic type (given by enum ovs_atomic_type). */ -union ovsdb_atom { - int64_t integer; - double real; - bool boolean; - struct json *s; - struct uuid uuid; -}; - -void ovsdb_atom_init_default(union ovsdb_atom *, enum ovsdb_atomic_type); -const union ovsdb_atom *ovsdb_atom_default(enum ovsdb_atomic_type); -bool ovsdb_atom_is_default(const union ovsdb_atom *, enum ovsdb_atomic_type); -void ovsdb_atom_clone(union ovsdb_atom *, const union ovsdb_atom *, - enum ovsdb_atomic_type); -void ovsdb_atom_swap(union ovsdb_atom *, union ovsdb_atom *); - -/* Returns false if ovsdb_atom_destroy() is a no-op when it is applied to an - * initialized atom of the given 'type', true if ovsdb_atom_destroy() actually - * does something. - * - * This can be used to avoid calling ovsdb_atom_destroy() for each element in - * an array of homogeneous atoms. (It's not worthwhile for a single atom.) */ -static inline bool -ovsdb_atom_needs_destruction(enum ovsdb_atomic_type type) -{ - return type == OVSDB_TYPE_STRING; -} - -/* Frees the contents of 'atom', which must have the specified 'type'. - * - * This does not actually call free(atom). If necessary, the caller must be - * responsible for that. */ -static inline void -ovsdb_atom_destroy(union ovsdb_atom *atom, enum ovsdb_atomic_type type) -{ - if (type == OVSDB_TYPE_STRING) { - json_destroy(atom->s); - } -} - -uint32_t ovsdb_atom_hash(const union ovsdb_atom *, enum ovsdb_atomic_type, - uint32_t basis); - -int ovsdb_atom_compare_3way(const union ovsdb_atom *, - const union ovsdb_atom *, - enum ovsdb_atomic_type); - -/* Returns true if 'a' and 'b', which are both of type 'type', has the same - * contents, false if their contents differ. */ -static inline bool ovsdb_atom_equals(const union ovsdb_atom *a, - const union ovsdb_atom *b, - enum ovsdb_atomic_type type) -{ - return !ovsdb_atom_compare_3way(a, b, type); -} - -struct ovsdb_error *ovsdb_atom_from_json(union ovsdb_atom *, - const struct ovsdb_base_type *, - const struct json *, - struct ovsdb_symbol_table *) - OVS_WARN_UNUSED_RESULT; -struct json *ovsdb_atom_to_json(const union ovsdb_atom *, - enum ovsdb_atomic_type); - -char *ovsdb_atom_from_string(union ovsdb_atom *, union ovsdb_atom **, - const struct ovsdb_base_type *, const char *, - struct ovsdb_symbol_table *) - OVS_WARN_UNUSED_RESULT; -void ovsdb_atom_to_string(const union ovsdb_atom *, enum ovsdb_atomic_type, - struct ds *); -void ovsdb_atom_to_bare(const union ovsdb_atom *, enum ovsdb_atomic_type, - struct ds *); - -struct ovsdb_error *ovsdb_atom_check_constraints( - const union ovsdb_atom *, const struct ovsdb_base_type *) - OVS_WARN_UNUSED_RESULT; - -/* An instance of an OVSDB type (given by struct ovsdb_type). - * - * - The 'keys' must be unique and in sorted order. Most functions that modify - * an ovsdb_datum maintain these invariants. Functions that don't maintain - * the invariants have names that end in "_unsafe". Use ovsdb_datum_sort() - * to check and restore these invariants. - * - * - 'n' is constrained by the ovsdb_type's 'n_min' and 'n_max'. - * - * If 'n' is nonzero, then 'keys' points to an array of 'n' atoms of the type - * specified by the ovsdb_type's 'key_type'. (Otherwise, 'keys' should be - * null.) - * - * If 'n' is nonzero and the ovsdb_type's 'value_type' is not - * OVSDB_TYPE_VOID, then 'values' points to an array of 'n' atoms of the type - * specified by the 'value_type'. (Otherwise, 'values' should be null.) - * - * Thus, for 'n' > 0, 'keys' will always be nonnull and 'values' will be - * nonnull only for "map" types. - */ -struct ovsdb_datum { - unsigned int n; /* Number of 'keys' and 'values'. */ - union ovsdb_atom *keys; /* Each of the ovsdb_type's 'key_type'. */ - union ovsdb_atom *values; /* Each of the ovsdb_type's 'value_type'. */ -}; -#define OVSDB_DATUM_INITIALIZER { 0, NULL, NULL } - -/* Basics. */ -void ovsdb_datum_init_empty(struct ovsdb_datum *); -void ovsdb_datum_init_default(struct ovsdb_datum *, const struct ovsdb_type *); -bool ovsdb_datum_is_default(const struct ovsdb_datum *, - const struct ovsdb_type *); -const struct ovsdb_datum *ovsdb_datum_default(const struct ovsdb_type *); -void ovsdb_datum_clone(struct ovsdb_datum *, const struct ovsdb_datum *, - const struct ovsdb_type *); -void ovsdb_datum_destroy(struct ovsdb_datum *, const struct ovsdb_type *); -void ovsdb_datum_swap(struct ovsdb_datum *, struct ovsdb_datum *); - -/* Checking and maintaining invariants. */ -struct ovsdb_error *ovsdb_datum_sort(struct ovsdb_datum *, - enum ovsdb_atomic_type key_type) - OVS_WARN_UNUSED_RESULT; - -void ovsdb_datum_sort_assert(struct ovsdb_datum *, - enum ovsdb_atomic_type key_type); - -size_t ovsdb_datum_sort_unique(struct ovsdb_datum *, - enum ovsdb_atomic_type key_type, - enum ovsdb_atomic_type value_type); - -struct ovsdb_error *ovsdb_datum_check_constraints( - const struct ovsdb_datum *, const struct ovsdb_type *) - OVS_WARN_UNUSED_RESULT; - -/* Type conversion. */ -struct ovsdb_error *ovsdb_datum_from_json(struct ovsdb_datum *, - const struct ovsdb_type *, - const struct json *, - struct ovsdb_symbol_table *) - OVS_WARN_UNUSED_RESULT; -struct ovsdb_error *ovsdb_transient_datum_from_json( - struct ovsdb_datum *, - const struct ovsdb_type *, - const struct json *) - OVS_WARN_UNUSED_RESULT; -struct ovsdb_error * -ovsdb_unconstrained_datum_from_json(struct ovsdb_datum *, - const struct ovsdb_type *, - const struct json *) - OVS_WARN_UNUSED_RESULT; -struct json *ovsdb_datum_to_json(const struct ovsdb_datum *, - const struct ovsdb_type *); - -char *ovsdb_datum_from_string(struct ovsdb_datum *, - const struct ovsdb_type *, const char *, - struct ovsdb_symbol_table *) - OVS_WARN_UNUSED_RESULT; -void ovsdb_datum_to_string(const struct ovsdb_datum *, - const struct ovsdb_type *, struct ds *); -void ovsdb_datum_to_bare(const struct ovsdb_datum *, - const struct ovsdb_type *, struct ds *); - -void ovsdb_datum_from_smap(struct ovsdb_datum *, const struct smap *); - -struct ovsdb_error *ovsdb_datum_convert(struct ovsdb_datum *dst, - const struct ovsdb_type *dst_type, - const struct ovsdb_datum *src, - const struct ovsdb_type *src_type) - OVS_WARN_UNUSED_RESULT; - -/* Comparison. */ -uint32_t ovsdb_datum_hash(const struct ovsdb_datum *, - const struct ovsdb_type *, uint32_t basis); -int ovsdb_datum_compare_3way(const struct ovsdb_datum *, - const struct ovsdb_datum *, - const struct ovsdb_type *); -bool ovsdb_datum_equals(const struct ovsdb_datum *, - const struct ovsdb_datum *, - const struct ovsdb_type *); - -/* Search. */ -bool ovsdb_datum_find_key(const struct ovsdb_datum *, - const union ovsdb_atom *key, - enum ovsdb_atomic_type key_type, - unsigned int *pos); -unsigned int ovsdb_datum_find_key_value(const struct ovsdb_datum *, - const union ovsdb_atom *key, - enum ovsdb_atomic_type key_type, - const union ovsdb_atom *value, - enum ovsdb_atomic_type value_type); - -/* Set operations. */ -bool ovsdb_datum_includes_all(const struct ovsdb_datum *, - const struct ovsdb_datum *, - const struct ovsdb_type *); -bool ovsdb_datum_excludes_all(const struct ovsdb_datum *, - const struct ovsdb_datum *, - const struct ovsdb_type *); -void ovsdb_datum_union(struct ovsdb_datum *, - const struct ovsdb_datum *, - const struct ovsdb_type *); -void ovsdb_datum_subtract(struct ovsdb_datum *a, - const struct ovsdb_type *a_type, - const struct ovsdb_datum *b, - const struct ovsdb_type *b_type); - -/* Generate and apply diffs */ -void ovsdb_datum_added_removed(struct ovsdb_datum *added, - struct ovsdb_datum *removed, - const struct ovsdb_datum *old, - const struct ovsdb_datum *new, - const struct ovsdb_type *type); - -void ovsdb_datum_diff(struct ovsdb_datum *diff, - const struct ovsdb_datum *old_datum, - const struct ovsdb_datum *new_datum, - const struct ovsdb_type *type); - -struct ovsdb_error *ovsdb_datum_apply_diff(struct ovsdb_datum *new_datum, - const struct ovsdb_datum *old_datum, - const struct ovsdb_datum *diff, - const struct ovsdb_type *type) -OVS_WARN_UNUSED_RESULT; - -struct ovsdb_error * ovsdb_datum_apply_diff_in_place( - struct ovsdb_datum *a, - const struct ovsdb_datum *diff, - const struct ovsdb_type *type) -OVS_WARN_UNUSED_RESULT; - -/* Raw operations that may not maintain the invariants. */ -void ovsdb_datum_remove_unsafe(struct ovsdb_datum *, size_t idx, - const struct ovsdb_type *); -void ovsdb_datum_add_unsafe(struct ovsdb_datum *, - const union ovsdb_atom *key, - const union ovsdb_atom *value, - const struct ovsdb_type *, - const union ovsdb_atom *range_end_atom); -void ovsdb_datum_add_from_index_unsafe(struct ovsdb_datum *dst, - const struct ovsdb_datum *src, - size_t idx, - const struct ovsdb_type *type); - -/* Transactions with named-uuid row names. */ -struct json *ovsdb_datum_to_json_with_row_names(const struct ovsdb_datum *, - const struct ovsdb_type *); -char *ovsdb_data_row_name(const struct uuid *); - -/* Type checking. */ -static inline bool -ovsdb_datum_conforms_to_type(const struct ovsdb_datum *datum, - const struct ovsdb_type *type) -{ - return datum->n >= type->n_min && datum->n <= type->n_max; -} - -/* A table mapping from names to data items. Currently the data items are - * always UUIDs; perhaps this will be expanded in the future. */ - -struct ovsdb_symbol_table { - struct shash sh; /* Maps from name to struct ovsdb_symbol *. */ -}; - -struct ovsdb_symbol { - struct uuid uuid; /* The UUID that the symbol represents. */ - bool created; /* Already used to create row? */ - bool strong_ref; /* Parsed a strong reference to this row? */ - bool weak_ref; /* Parsed a weak reference to this row? */ -}; - -struct ovsdb_symbol_table *ovsdb_symbol_table_create(void); -void ovsdb_symbol_table_destroy(struct ovsdb_symbol_table *); -struct ovsdb_symbol *ovsdb_symbol_table_get(const struct ovsdb_symbol_table *, - const char *name); -struct ovsdb_symbol *ovsdb_symbol_table_put(struct ovsdb_symbol_table *, - const char *name, - const struct uuid *, bool used); -struct ovsdb_symbol *ovsdb_symbol_table_insert(struct ovsdb_symbol_table *, - const char *name); - -/* Tokenization - * - * Used by ovsdb_atom_from_string() and ovsdb_datum_from_string(). */ - -char *ovsdb_token_parse(const char **, char **outp) OVS_WARN_UNUSED_RESULT; -bool ovsdb_token_is_delim(unsigned char); - -struct ovsdb_error *ovsdb_atom_range_check_size(int64_t range_start, - int64_t range_end); - -#ifdef __cplusplus -} -#endif - -#endif /* ovsdb-data.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-data.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-data.h @@ -0,0 +1,339 @@ +/* Copyright (c) 2009, 2010, 2011, 2012, 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. + */ + +#ifndef OVSDB_DATA_H +#define OVSDB_DATA_H 1 + +#include +#include "openvswitch/compiler.h" +#include "openvswitch/ovsdb-types.h" +#include "openvswitch/json.h" +#include "openvswitch/shash.h" +#include "internal/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MAX_OVSDB_ATOM_RANGE_SIZE 4096 + +struct ds; +struct ovsdb_symbol_table; +struct smap; + +static inline struct json * +ovsdb_atom_string_create_nocopy(char *str) +{ + return json_string_create_nocopy(str); +} + +static inline struct json * +ovsdb_atom_string_create(const char *str) +{ + return json_string_create(str); +} + +/* One value of an atomic type (given by enum ovs_atomic_type). */ +union ovsdb_atom { + int64_t integer; + double real; + bool boolean; + struct json *s; + struct uuid uuid; +}; + +void ovsdb_atom_init_default(union ovsdb_atom *, enum ovsdb_atomic_type); +const union ovsdb_atom *ovsdb_atom_default(enum ovsdb_atomic_type); +bool ovsdb_atom_is_default(const union ovsdb_atom *, enum ovsdb_atomic_type); +void ovsdb_atom_clone(union ovsdb_atom *, const union ovsdb_atom *, + enum ovsdb_atomic_type); +void ovsdb_atom_swap(union ovsdb_atom *, union ovsdb_atom *); + +/* Returns false if ovsdb_atom_destroy() is a no-op when it is applied to an + * initialized atom of the given 'type', true if ovsdb_atom_destroy() actually + * does something. + * + * This can be used to avoid calling ovsdb_atom_destroy() for each element in + * an array of homogeneous atoms. (It's not worthwhile for a single atom.) */ +static inline bool +ovsdb_atom_needs_destruction(enum ovsdb_atomic_type type) +{ + return type == OVSDB_TYPE_STRING; +} + +/* Frees the contents of 'atom', which must have the specified 'type'. + * + * This does not actually call free(atom). If necessary, the caller must be + * responsible for that. */ +static inline void +ovsdb_atom_destroy(union ovsdb_atom *atom, enum ovsdb_atomic_type type) +{ + if (type == OVSDB_TYPE_STRING) { + json_destroy(atom->s); + } +} + +uint32_t ovsdb_atom_hash(const union ovsdb_atom *, enum ovsdb_atomic_type, + uint32_t basis); + +int ovsdb_atom_compare_3way(const union ovsdb_atom *, + const union ovsdb_atom *, + enum ovsdb_atomic_type); + +/* Returns true if 'a' and 'b', which are both of type 'type', has the same + * contents, false if their contents differ. */ +static inline bool ovsdb_atom_equals(const union ovsdb_atom *a, + const union ovsdb_atom *b, + enum ovsdb_atomic_type type) +{ + return !ovsdb_atom_compare_3way(a, b, type); +} + +struct ovsdb_error *ovsdb_atom_from_json(union ovsdb_atom *, + const struct ovsdb_base_type *, + const struct json *, + struct ovsdb_symbol_table *) + OVS_WARN_UNUSED_RESULT; +struct json *ovsdb_atom_to_json(const union ovsdb_atom *, + enum ovsdb_atomic_type); + +char *ovsdb_atom_from_string(union ovsdb_atom *, union ovsdb_atom **, + const struct ovsdb_base_type *, const char *, + struct ovsdb_symbol_table *) + OVS_WARN_UNUSED_RESULT; +void ovsdb_atom_to_string(const union ovsdb_atom *, enum ovsdb_atomic_type, + struct ds *); +void ovsdb_atom_to_bare(const union ovsdb_atom *, enum ovsdb_atomic_type, + struct ds *); + +struct ovsdb_error *ovsdb_atom_check_constraints( + const union ovsdb_atom *, const struct ovsdb_base_type *) + OVS_WARN_UNUSED_RESULT; + +/* An instance of an OVSDB type (given by struct ovsdb_type). + * + * - The 'keys' must be unique and in sorted order. Most functions that modify + * an ovsdb_datum maintain these invariants. Functions that don't maintain + * the invariants have names that end in "_unsafe". Use ovsdb_datum_sort() + * to check and restore these invariants. + * + * - 'n' is constrained by the ovsdb_type's 'n_min' and 'n_max'. + * + * If 'n' is nonzero, then 'keys' points to an array of 'n' atoms of the type + * specified by the ovsdb_type's 'key_type'. (Otherwise, 'keys' should be + * null.) + * + * If 'n' is nonzero and the ovsdb_type's 'value_type' is not + * OVSDB_TYPE_VOID, then 'values' points to an array of 'n' atoms of the type + * specified by the 'value_type'. (Otherwise, 'values' should be null.) + * + * Thus, for 'n' > 0, 'keys' will always be nonnull and 'values' will be + * nonnull only for "map" types. + */ +struct ovsdb_datum { + unsigned int n; /* Number of 'keys' and 'values'. */ + union ovsdb_atom *keys; /* Each of the ovsdb_type's 'key_type'. */ + union ovsdb_atom *values; /* Each of the ovsdb_type's 'value_type'. */ +}; +#define OVSDB_DATUM_INITIALIZER { 0, NULL, NULL } + +/* Basics. */ +void ovsdb_datum_init_empty(struct ovsdb_datum *); +void ovsdb_datum_init_default(struct ovsdb_datum *, const struct ovsdb_type *); +bool ovsdb_datum_is_default(const struct ovsdb_datum *, + const struct ovsdb_type *); +const struct ovsdb_datum *ovsdb_datum_default(const struct ovsdb_type *); +void ovsdb_datum_clone(struct ovsdb_datum *, const struct ovsdb_datum *, + const struct ovsdb_type *); +void ovsdb_datum_destroy(struct ovsdb_datum *, const struct ovsdb_type *); +void ovsdb_datum_swap(struct ovsdb_datum *, struct ovsdb_datum *); + +/* Checking and maintaining invariants. */ +struct ovsdb_error *ovsdb_datum_sort(struct ovsdb_datum *, + enum ovsdb_atomic_type key_type) + OVS_WARN_UNUSED_RESULT; + +void ovsdb_datum_sort_assert(struct ovsdb_datum *, + enum ovsdb_atomic_type key_type); + +size_t ovsdb_datum_sort_unique(struct ovsdb_datum *, + enum ovsdb_atomic_type key_type, + enum ovsdb_atomic_type value_type); + +struct ovsdb_error *ovsdb_datum_check_constraints( + const struct ovsdb_datum *, const struct ovsdb_type *) + OVS_WARN_UNUSED_RESULT; + +/* Type conversion. */ +struct ovsdb_error *ovsdb_datum_from_json(struct ovsdb_datum *, + const struct ovsdb_type *, + const struct json *, + struct ovsdb_symbol_table *) + OVS_WARN_UNUSED_RESULT; +struct ovsdb_error *ovsdb_transient_datum_from_json( + struct ovsdb_datum *, + const struct ovsdb_type *, + const struct json *) + OVS_WARN_UNUSED_RESULT; +struct ovsdb_error * +ovsdb_unconstrained_datum_from_json(struct ovsdb_datum *, + const struct ovsdb_type *, + const struct json *) + OVS_WARN_UNUSED_RESULT; +struct json *ovsdb_datum_to_json(const struct ovsdb_datum *, + const struct ovsdb_type *); + +char *ovsdb_datum_from_string(struct ovsdb_datum *, + const struct ovsdb_type *, const char *, + struct ovsdb_symbol_table *) + OVS_WARN_UNUSED_RESULT; +void ovsdb_datum_to_string(const struct ovsdb_datum *, + const struct ovsdb_type *, struct ds *); +void ovsdb_datum_to_bare(const struct ovsdb_datum *, + const struct ovsdb_type *, struct ds *); + +void ovsdb_datum_from_smap(struct ovsdb_datum *, const struct smap *); + +struct ovsdb_error *ovsdb_datum_convert(struct ovsdb_datum *dst, + const struct ovsdb_type *dst_type, + const struct ovsdb_datum *src, + const struct ovsdb_type *src_type) + OVS_WARN_UNUSED_RESULT; + +/* Comparison. */ +uint32_t ovsdb_datum_hash(const struct ovsdb_datum *, + const struct ovsdb_type *, uint32_t basis); +int ovsdb_datum_compare_3way(const struct ovsdb_datum *, + const struct ovsdb_datum *, + const struct ovsdb_type *); +bool ovsdb_datum_equals(const struct ovsdb_datum *, + const struct ovsdb_datum *, + const struct ovsdb_type *); + +/* Search. */ +bool ovsdb_datum_find_key(const struct ovsdb_datum *, + const union ovsdb_atom *key, + enum ovsdb_atomic_type key_type, + unsigned int *pos); +unsigned int ovsdb_datum_find_key_value(const struct ovsdb_datum *, + const union ovsdb_atom *key, + enum ovsdb_atomic_type key_type, + const union ovsdb_atom *value, + enum ovsdb_atomic_type value_type); + +/* Set operations. */ +bool ovsdb_datum_includes_all(const struct ovsdb_datum *, + const struct ovsdb_datum *, + const struct ovsdb_type *); +bool ovsdb_datum_excludes_all(const struct ovsdb_datum *, + const struct ovsdb_datum *, + const struct ovsdb_type *); +void ovsdb_datum_union(struct ovsdb_datum *, + const struct ovsdb_datum *, + const struct ovsdb_type *); +void ovsdb_datum_subtract(struct ovsdb_datum *a, + const struct ovsdb_type *a_type, + const struct ovsdb_datum *b, + const struct ovsdb_type *b_type); + +/* Generate and apply diffs */ +void ovsdb_datum_added_removed(struct ovsdb_datum *added, + struct ovsdb_datum *removed, + const struct ovsdb_datum *old, + const struct ovsdb_datum *new, + const struct ovsdb_type *type); + +void ovsdb_datum_diff(struct ovsdb_datum *diff, + const struct ovsdb_datum *old_datum, + const struct ovsdb_datum *new_datum, + const struct ovsdb_type *type); + +struct ovsdb_error *ovsdb_datum_apply_diff(struct ovsdb_datum *new_datum, + const struct ovsdb_datum *old_datum, + const struct ovsdb_datum *diff, + const struct ovsdb_type *type) +OVS_WARN_UNUSED_RESULT; + +struct ovsdb_error * ovsdb_datum_apply_diff_in_place( + struct ovsdb_datum *a, + const struct ovsdb_datum *diff, + const struct ovsdb_type *type) +OVS_WARN_UNUSED_RESULT; + +/* Raw operations that may not maintain the invariants. */ +void ovsdb_datum_remove_unsafe(struct ovsdb_datum *, size_t idx, + const struct ovsdb_type *); +void ovsdb_datum_add_unsafe(struct ovsdb_datum *, + const union ovsdb_atom *key, + const union ovsdb_atom *value, + const struct ovsdb_type *, + const union ovsdb_atom *range_end_atom); +void ovsdb_datum_add_from_index_unsafe(struct ovsdb_datum *dst, + const struct ovsdb_datum *src, + size_t idx, + const struct ovsdb_type *type); + +/* Transactions with named-uuid row names. */ +struct json *ovsdb_datum_to_json_with_row_names(const struct ovsdb_datum *, + const struct ovsdb_type *); +char *ovsdb_data_row_name(const struct uuid *); + +/* Type checking. */ +static inline bool +ovsdb_datum_conforms_to_type(const struct ovsdb_datum *datum, + const struct ovsdb_type *type) +{ + return datum->n >= type->n_min && datum->n <= type->n_max; +} + +/* A table mapping from names to data items. Currently the data items are + * always UUIDs; perhaps this will be expanded in the future. */ + +struct ovsdb_symbol_table { + struct shash sh; /* Maps from name to struct ovsdb_symbol *. */ +}; + +struct ovsdb_symbol { + struct uuid uuid; /* The UUID that the symbol represents. */ + bool created; /* Already used to create row? */ + bool strong_ref; /* Parsed a strong reference to this row? */ + bool weak_ref; /* Parsed a weak reference to this row? */ +}; + +struct ovsdb_symbol_table *ovsdb_symbol_table_create(void); +void ovsdb_symbol_table_destroy(struct ovsdb_symbol_table *); +struct ovsdb_symbol *ovsdb_symbol_table_get(const struct ovsdb_symbol_table *, + const char *name); +struct ovsdb_symbol *ovsdb_symbol_table_put(struct ovsdb_symbol_table *, + const char *name, + const struct uuid *, bool used); +struct ovsdb_symbol *ovsdb_symbol_table_insert(struct ovsdb_symbol_table *, + const char *name); + +/* Tokenization + * + * Used by ovsdb_atom_from_string() and ovsdb_datum_from_string(). */ + +char *ovsdb_token_parse(const char **, char **outp) OVS_WARN_UNUSED_RESULT; +bool ovsdb_token_is_delim(unsigned char); + +struct ovsdb_error *ovsdb_atom_range_check_size(int64_t range_start, + int64_t range_end); + +#ifdef __cplusplus +} +#endif + +#endif /* ovsdb-data.h */ Index: openvswitch-2.17.2/lib/ovsdb-error.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-error.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 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. - */ - -#ifndef OVSDB_ERROR_H -#define OVSDB_ERROR_H 1 - -#include "openvswitch/compiler.h" - -struct json; - -struct ovsdb_error *ovsdb_error(const char *tag, const char *details, ...) - OVS_PRINTF_FORMAT(2, 3) - OVS_WARN_UNUSED_RESULT; -struct ovsdb_error *ovsdb_io_error(int error, const char *details, ...) - OVS_PRINTF_FORMAT(2, 3) - OVS_WARN_UNUSED_RESULT; -struct ovsdb_error *ovsdb_syntax_error(const struct json *, const char *tag, - const char *details, ...) - OVS_PRINTF_FORMAT(3, 4) - OVS_WARN_UNUSED_RESULT; - -struct ovsdb_error *ovsdb_wrap_error(struct ovsdb_error *error, - const char *details, ...) - OVS_PRINTF_FORMAT(2, 3); - -struct ovsdb_error *ovsdb_internal_error(struct ovsdb_error *error, - const char *file, int line, - const char *details, ...) - OVS_PRINTF_FORMAT(4, 5) - OVS_WARN_UNUSED_RESULT; - -struct ovsdb_error *ovsdb_perm_error(const char *details, ...) - OVS_PRINTF_FORMAT(1, 2) - OVS_WARN_UNUSED_RESULT; - -/* Returns a pointer to an ovsdb_error that represents an internal error for - * the current file name and line number with MSG as the associated message. - * The caller is responsible for freeing the internal error. */ -#define OVSDB_BUG(MSG) \ - ovsdb_internal_error(NULL, __FILE__, __LINE__, "%s", MSG) - -/* Returns a pointer to an ovsdb_error that represents an internal error for - * the current file name and line number, with MSG as the associated message. - * If ERROR is nonnull then the internal error is wrapped around ERROR. Takes - * ownership of ERROR. The caller is responsible for freeing the returned - * error. */ -#define OVSDB_WRAP_BUG(MSG, ERROR) \ - ovsdb_internal_error(ERROR, __FILE__, __LINE__, "%s", MSG) - -void ovsdb_error_destroy(struct ovsdb_error *); -struct ovsdb_error *ovsdb_error_clone(const struct ovsdb_error *) - OVS_WARN_UNUSED_RESULT; - -char *ovsdb_error_to_string(const struct ovsdb_error *); -char *ovsdb_error_to_string_free(struct ovsdb_error *); -struct json *ovsdb_error_to_json(const struct ovsdb_error *); -struct json *ovsdb_error_to_json_free(struct ovsdb_error *); - -const char *ovsdb_error_get_tag(const struct ovsdb_error *); - -void ovsdb_error_assert(struct ovsdb_error *); - -#endif /* ovsdb-error.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-error.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-error.h @@ -0,0 +1,83 @@ +/* Copyright (c) 2009, 2010, 2011, 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. + */ + +#ifndef OVSDB_ERROR_H +#define OVSDB_ERROR_H 1 + +#include "openvswitch/compiler.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct json; + +struct ovsdb_error *ovsdb_error(const char *tag, const char *details, ...) + OVS_PRINTF_FORMAT(2, 3) + OVS_WARN_UNUSED_RESULT; +struct ovsdb_error *ovsdb_io_error(int error, const char *details, ...) + OVS_PRINTF_FORMAT(2, 3) + OVS_WARN_UNUSED_RESULT; +struct ovsdb_error *ovsdb_syntax_error(const struct json *, const char *tag, + const char *details, ...) + OVS_PRINTF_FORMAT(3, 4) + OVS_WARN_UNUSED_RESULT; + +struct ovsdb_error *ovsdb_wrap_error(struct ovsdb_error *error, + const char *details, ...) + OVS_PRINTF_FORMAT(2, 3); + +struct ovsdb_error *ovsdb_internal_error(struct ovsdb_error *error, + const char *file, int line, + const char *details, ...) + OVS_PRINTF_FORMAT(4, 5) + OVS_WARN_UNUSED_RESULT; + +struct ovsdb_error *ovsdb_perm_error(const char *details, ...) + OVS_PRINTF_FORMAT(1, 2) + OVS_WARN_UNUSED_RESULT; + +/* Returns a pointer to an ovsdb_error that represents an internal error for + * the current file name and line number with MSG as the associated message. + * The caller is responsible for freeing the internal error. */ +#define OVSDB_BUG(MSG) \ + ovsdb_internal_error(NULL, __FILE__, __LINE__, "%s", MSG) + +/* Returns a pointer to an ovsdb_error that represents an internal error for + * the current file name and line number, with MSG as the associated message. + * If ERROR is nonnull then the internal error is wrapped around ERROR. Takes + * ownership of ERROR. The caller is responsible for freeing the returned + * error. */ +#define OVSDB_WRAP_BUG(MSG, ERROR) \ + ovsdb_internal_error(ERROR, __FILE__, __LINE__, "%s", MSG) + +void ovsdb_error_destroy(struct ovsdb_error *); +struct ovsdb_error *ovsdb_error_clone(const struct ovsdb_error *) + OVS_WARN_UNUSED_RESULT; + +char *ovsdb_error_to_string(const struct ovsdb_error *); +char *ovsdb_error_to_string_free(struct ovsdb_error *); +struct json *ovsdb_error_to_json(const struct ovsdb_error *); +struct json *ovsdb_error_to_json_free(struct ovsdb_error *); + +const char *ovsdb_error_get_tag(const struct ovsdb_error *); + +void ovsdb_error_assert(struct ovsdb_error *); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ovsdb-error.h */ Index: openvswitch-2.17.2/lib/ovsdb-idl-provider.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-idl-provider.h +++ /dev/null @@ -1,181 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 2016 Nicira, Inc. - * Copyright (C) 2016 Hewlett Packard Enterprise Development LP - * - * 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 OVSDB_IDL_PROVIDER_H -#define OVSDB_IDL_PROVIDER_H 1 - -#include "openvswitch/hmap.h" -#include "openvswitch/list.h" -#include "ovsdb-idl.h" -#include "ovsdb-map-op.h" -#include "ovsdb-set-op.h" -#include "ovsdb-types.h" -#include "openvswitch/shash.h" -#include "sset.h" -#include "uuid.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* A local copy of a row in an OVSDB table, replicated from an OVSDB server. - * This structure is used as a header for a larger structure that translates - * the "struct ovsdb_datum"s into easier-to-use forms, via the ->parse() and - * ->unparse functions in struct ovsdb_idl_column. (Those functions are - * generated automatically via ovsdb-idlc.) - * - * When no transaction is in progress: - * - * - 'old_datum' points to the data committed to the database and currently - * in the row. - * - * - 'new_datum == old_datum'. - * - * When a transaction is in progress, the situation is a little different. For - * a row inserted in the transaction, 'old_datum' is NULL and 'new_datum' - * points to the row's initial contents. Otherwise: - * - * - 'old_datum' points to the data committed to the database and currently - * in the row. (This is the same as when no transaction is in progress.) - * - * - If the transaction does not modify the row, 'new_datum == old_datum'. - * - * - If the transaction modifies the row, 'new_datum' points to the - * modified data. - * - * - If the transaction deletes the row, 'new_datum' is NULL. - * - * Thus: - * - * - 'old_datum' always points to committed data, except that it is NULL if - * the row is inserted within the current transaction. - * - * - 'new_datum' always points to the newest, possibly uncommitted version - * of the row's data, except that it is NULL if the row is deleted within - * the current transaction. - */ -struct ovsdb_idl_row { - struct hmap_node hmap_node; /* In struct ovsdb_idl_table's 'rows'. */ - struct uuid uuid; /* Row "_uuid" field. */ - struct ovs_list src_arcs; /* Forward arcs (ovsdb_idl_arc.src_node). */ - struct ovs_list dst_arcs; /* Backward arcs (ovsdb_idl_arc.dst_node). */ - struct ovsdb_idl_table *table; /* Containing table. */ - struct ovsdb_datum *old_datum; /* Committed data (null if orphaned). */ - bool parsed; /* Whether the row is parsed. */ - struct ovs_list reparse_node; /* Rows that needs to be re-parsed due to - * insertion of a referenced row. */ - - /* Transactional data. */ - struct ovsdb_datum *new_datum; /* Modified data (null to delete row). */ - unsigned long int *prereqs; /* Bitmap of "old_datum" columns to verify. */ - unsigned long int *written; /* Bitmap of "new_datum" columns to write. */ - struct hmap_node txn_node; /* Node in ovsdb_idl_txn's list. */ - unsigned long int *map_op_written; /* Bitmap of columns pending map ops. */ - struct map_op_list **map_op_lists; /* Per-column map operations. */ - unsigned long int *set_op_written; /* Bitmap of columns pending set ops. */ - struct set_op_list **set_op_lists; /* Per-column set operations. */ - - /* Tracking data */ - unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX]; - struct ovs_list track_node; /* Rows modified/added/deleted by IDL */ - unsigned long int *updated; /* Bitmap of columns updated by IDL */ - struct ovsdb_datum *tracked_old_datum; /* Old deleted data. */ -}; - -struct ovsdb_idl_column { - char *name; - struct ovsdb_type type; - bool is_mutable; - bool is_synthetic; - void (*parse)(struct ovsdb_idl_row *, const struct ovsdb_datum *); - void (*unparse)(struct ovsdb_idl_row *); -}; - -struct ovsdb_idl_table_class { - char *name; - bool is_root; - bool is_singleton; - const struct ovsdb_idl_column *columns; - size_t n_columns; - size_t allocation_size; - void (*row_init)(struct ovsdb_idl_row *); -}; - -struct ovsdb_idl_table { - const struct ovsdb_idl_table_class *class_; - unsigned char *modes; /* OVSDB_IDL_* bitmasks, indexed by column. */ - bool need_table; /* Monitor table even if no columns are selected - * for replication. */ - struct shash columns; /* Contains "const struct ovsdb_idl_column *"s. */ - struct sset schema_columns; /* Column names from schema. */ - struct hmap rows; /* Contains "struct ovsdb_idl_row"s. */ - struct ovsdb_idl *idl; /* Containing IDL instance. */ - unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX]; - bool in_server_schema; /* Indicates if this table is in the server schema - * or not. */ - struct ovs_list indexes; /* Contains "struct ovsdb_idl_index"s */ - struct ovs_list track_list; /* Tracked rows (ovsdb_idl_row.track_node). */ -}; - -struct ovsdb_idl_class { - const char *database; /* for this database. */ - const struct ovsdb_idl_table_class *tables; - size_t n_tables; -}; - -struct ovsdb_idl_row *ovsdb_idl_get_row_arc( - struct ovsdb_idl_row *src, - const struct ovsdb_idl_table_class *dst_table, - const struct uuid *dst_uuid); - -void ovsdb_idl_txn_verify(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *); - -struct ovsdb_idl_txn *ovsdb_idl_txn_get(const struct ovsdb_idl_row *); - -/* Index internals. */ - -struct ovsdb_idl_index { - struct ovs_list node; /* In ->table->indexes. */ - struct ovsdb_idl_table *table; /* The indexed table. */ - struct ovsdb_idl_index_column *columns; /* The indexed columns. */ - size_t n_columns; - - /* Skiplist with pointers to rows. */ - struct skiplist *skiplist; - - /* True if a row in the index is being inserted or deleted. If true, the - search key is augmented with the UUID and address to discriminate - between entries with identical keys. */ - bool ins_del; -}; - -int ovsdb_idl_index_compare(struct ovsdb_idl_index *, - const struct ovsdb_idl_row *a, - const struct ovsdb_idl_row *b); - -void ovsdb_idl_index_write(struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - struct ovsdb_datum *, - const struct ovsdb_idl_table_class *); -struct ovsdb_idl_row *ovsdb_idl_index_init_row(struct ovsdb_idl_index *); -void ovsdb_idl_index_destroy_row(const struct ovsdb_idl_row *); - -#ifdef __cplusplus -} -#endif - -#endif /* ovsdb-idl-provider.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-idl-provider.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-idl-provider.h @@ -0,0 +1,181 @@ +/* Copyright (c) 2009, 2010, 2011, 2012, 2016 Nicira, Inc. + * Copyright (C) 2016 Hewlett Packard Enterprise Development LP + * + * 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 OVSDB_IDL_PROVIDER_H +#define OVSDB_IDL_PROVIDER_H 1 + +#include "openvswitch/hmap.h" +#include "openvswitch/list.h" +#include "openvswitch/ovsdb-idl.h" +#include "openvswitch/ovsdb-map-op.h" +#include "openvswitch/ovsdb-set-op.h" +#include "openvswitch/ovsdb-types.h" +#include "openvswitch/shash.h" +#include "internal/sset.h" +#include "internal/uuid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* A local copy of a row in an OVSDB table, replicated from an OVSDB server. + * This structure is used as a header for a larger structure that translates + * the "struct ovsdb_datum"s into easier-to-use forms, via the ->parse() and + * ->unparse functions in struct ovsdb_idl_column. (Those functions are + * generated automatically via ovsdb-idlc.) + * + * When no transaction is in progress: + * + * - 'old_datum' points to the data committed to the database and currently + * in the row. + * + * - 'new_datum == old_datum'. + * + * When a transaction is in progress, the situation is a little different. For + * a row inserted in the transaction, 'old_datum' is NULL and 'new_datum' + * points to the row's initial contents. Otherwise: + * + * - 'old_datum' points to the data committed to the database and currently + * in the row. (This is the same as when no transaction is in progress.) + * + * - If the transaction does not modify the row, 'new_datum == old_datum'. + * + * - If the transaction modifies the row, 'new_datum' points to the + * modified data. + * + * - If the transaction deletes the row, 'new_datum' is NULL. + * + * Thus: + * + * - 'old_datum' always points to committed data, except that it is NULL if + * the row is inserted within the current transaction. + * + * - 'new_datum' always points to the newest, possibly uncommitted version + * of the row's data, except that it is NULL if the row is deleted within + * the current transaction. + */ +struct ovsdb_idl_row { + struct hmap_node hmap_node; /* In struct ovsdb_idl_table's 'rows'. */ + struct uuid uuid; /* Row "_uuid" field. */ + struct ovs_list src_arcs; /* Forward arcs (ovsdb_idl_arc.src_node). */ + struct ovs_list dst_arcs; /* Backward arcs (ovsdb_idl_arc.dst_node). */ + struct ovsdb_idl_table *table; /* Containing table. */ + struct ovsdb_datum *old_datum; /* Committed data (null if orphaned). */ + bool parsed; /* Whether the row is parsed. */ + struct ovs_list reparse_node; /* Rows that needs to be re-parsed due to + * insertion of a referenced row. */ + + /* Transactional data. */ + struct ovsdb_datum *new_datum; /* Modified data (null to delete row). */ + unsigned long int *prereqs; /* Bitmap of "old_datum" columns to verify. */ + unsigned long int *written; /* Bitmap of "new_datum" columns to write. */ + struct hmap_node txn_node; /* Node in ovsdb_idl_txn's list. */ + unsigned long int *map_op_written; /* Bitmap of columns pending map ops. */ + struct map_op_list **map_op_lists; /* Per-column map operations. */ + unsigned long int *set_op_written; /* Bitmap of columns pending set ops. */ + struct set_op_list **set_op_lists; /* Per-column set operations. */ + + /* Tracking data */ + unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX]; + struct ovs_list track_node; /* Rows modified/added/deleted by IDL */ + unsigned long int *updated; /* Bitmap of columns updated by IDL */ + struct ovsdb_datum *tracked_old_datum; /* Old deleted data. */ +}; + +struct ovsdb_idl_column { + char *name; + struct ovsdb_type type; + bool is_mutable; + bool is_synthetic; + void (*parse)(struct ovsdb_idl_row *, const struct ovsdb_datum *); + void (*unparse)(struct ovsdb_idl_row *); +}; + +struct ovsdb_idl_table_class { + char *name; + bool is_root; + bool is_singleton; + const struct ovsdb_idl_column *columns; + size_t n_columns; + size_t allocation_size; + void (*row_init)(struct ovsdb_idl_row *); +}; + +struct ovsdb_idl_table { + const struct ovsdb_idl_table_class *class_; + unsigned char *modes; /* OVSDB_IDL_* bitmasks, indexed by column. */ + bool need_table; /* Monitor table even if no columns are selected + * for replication. */ + struct shash columns; /* Contains "const struct ovsdb_idl_column *"s. */ + struct sset schema_columns; /* Column names from schema. */ + struct hmap rows; /* Contains "struct ovsdb_idl_row"s. */ + struct ovsdb_idl *idl; /* Containing IDL instance. */ + unsigned int change_seqno[OVSDB_IDL_CHANGE_MAX]; + bool in_server_schema; /* Indicates if this table is in the server schema + * or not. */ + struct ovs_list indexes; /* Contains "struct ovsdb_idl_index"s */ + struct ovs_list track_list; /* Tracked rows (ovsdb_idl_row.track_node). */ +}; + +struct ovsdb_idl_class { + const char *database; /* for this database. */ + const struct ovsdb_idl_table_class *tables; + size_t n_tables; +}; + +struct ovsdb_idl_row *ovsdb_idl_get_row_arc( + struct ovsdb_idl_row *src, + const struct ovsdb_idl_table_class *dst_table, + const struct uuid *dst_uuid); + +void ovsdb_idl_txn_verify(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *); + +struct ovsdb_idl_txn *ovsdb_idl_txn_get(const struct ovsdb_idl_row *); + +/* Index internals. */ + +struct ovsdb_idl_index { + struct ovs_list node; /* In ->table->indexes. */ + struct ovsdb_idl_table *table; /* The indexed table. */ + struct ovsdb_idl_index_column *columns; /* The indexed columns. */ + size_t n_columns; + + /* Skiplist with pointers to rows. */ + struct skiplist *skiplist; + + /* True if a row in the index is being inserted or deleted. If true, the + search key is augmented with the UUID and address to discriminate + between entries with identical keys. */ + bool ins_del; +}; + +int ovsdb_idl_index_compare(struct ovsdb_idl_index *, + const struct ovsdb_idl_row *a, + const struct ovsdb_idl_row *b); + +void ovsdb_idl_index_write(struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + struct ovsdb_datum *, + const struct ovsdb_idl_table_class *); +struct ovsdb_idl_row *ovsdb_idl_index_init_row(struct ovsdb_idl_index *); +void ovsdb_idl_index_destroy_row(const struct ovsdb_idl_row *); + +#ifdef __cplusplus +} +#endif + +#endif /* ovsdb-idl-provider.h */ Index: openvswitch-2.17.2/lib/ovsdb-idl.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-idl.h +++ /dev/null @@ -1,488 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2019 Nicira, Inc. - * Copyright (C) 2016 Hewlett Packard Enterprise Development LP - * - * 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 OVSDB_IDL_H -#define OVSDB_IDL_H 1 - -/* Open vSwitch Database Interface Definition Language (OVSDB IDL). - * - * The OVSDB IDL maintains an in-memory replica of a database. It issues RPC - * requests to an OVSDB database server and parses the responses, converting - * raw JSON into data structures that are easier for clients to digest. Most - * notably, references to rows via UUID become C pointers. - * - * The IDL always presents a consistent snapshot of the database to its client, - * that is, it won't present the effects of some part of a transaction applied - * at the database server without presenting all of its effects. - * - * The IDL also assists with issuing database transactions. The client creates - * a transaction, manipulates the IDL data structures, and commits or aborts - * the transaction. The IDL then composes and issues the necessary JSON-RPC - * requests and reports to the client whether the transaction completed - * successfully. - */ - -#include -#include -#include "openvswitch/compiler.h" -#include "ovsdb-types.h" -#include "ovsdb-data.h" -#include "openvswitch/list.h" -#include "ovsdb-condition.h" -#include "skiplist.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct json; -struct ovsdb_datum; -struct ovsdb_idl_class; -struct ovsdb_idl_row; -struct ovsdb_idl_column; -struct ovsdb_idl_table; -struct ovsdb_idl_table_class; -struct simap; -struct uuid; - -struct ovsdb_idl *ovsdb_idl_create(const char *remote, - const struct ovsdb_idl_class *, - bool monitor_everything_by_default, - bool retry); -struct ovsdb_idl *ovsdb_idl_create_unconnected( - const struct ovsdb_idl_class *, bool monitor_everything_by_default); -void ovsdb_idl_set_remote(struct ovsdb_idl *, const char *remote, bool retry); -void ovsdb_idl_set_shuffle_remotes(struct ovsdb_idl *, bool shuffle); -void ovsdb_idl_reset_min_index(struct ovsdb_idl *); -void ovsdb_idl_destroy(struct ovsdb_idl *); - -void ovsdb_idl_set_leader_only(struct ovsdb_idl *, bool leader_only); - -void ovsdb_idl_run(struct ovsdb_idl *); -void ovsdb_idl_wait(struct ovsdb_idl *); - -void ovsdb_idl_get_memory_usage(struct ovsdb_idl *, struct simap *usage); - -void ovsdb_idl_set_lock(struct ovsdb_idl *, const char *lock_name); -bool ovsdb_idl_has_lock(const struct ovsdb_idl *); -bool ovsdb_idl_is_lock_contended(const struct ovsdb_idl *); - -unsigned int ovsdb_idl_get_seqno(const struct ovsdb_idl *); -bool ovsdb_idl_has_ever_connected(const struct ovsdb_idl *); -void ovsdb_idl_enable_reconnect(struct ovsdb_idl *); -void ovsdb_idl_force_reconnect(struct ovsdb_idl *); -void ovsdb_idl_verify_write_only(struct ovsdb_idl *); - -bool ovsdb_idl_is_alive(const struct ovsdb_idl *); -bool ovsdb_idl_is_connected(const struct ovsdb_idl *idl); -int ovsdb_idl_get_last_error(const struct ovsdb_idl *); - -void ovsdb_idl_set_probe_interval(const struct ovsdb_idl *, int probe_interval); - -void ovsdb_idl_check_consistency(const struct ovsdb_idl *); - -const struct ovsdb_idl_class *ovsdb_idl_get_class(const struct ovsdb_idl *); -const struct ovsdb_idl_table_class *ovsdb_idl_table_class_from_column( - const struct ovsdb_idl_class *, const struct ovsdb_idl_column *); -bool ovsdb_idl_server_has_table(const struct ovsdb_idl *, - const struct ovsdb_idl_table_class *); -bool ovsdb_idl_server_has_column(const struct ovsdb_idl *, - const struct ovsdb_idl_column *); - -/* Choosing columns and tables to replicate. - * - * The client may choose any subset of the columns and tables to replicate, - * specifying it one of two ways: - * - * - As a deny list (adding the columns or tables to replicate). To do so, - * the client passes false as 'monitor_everything_by_default' to - * ovsdb_idl_create() and then calls ovsdb_idl_add_column() and - * ovsdb_idl_add_table() for the desired columns and, if necessary, tables. - * - * - As an allow list (replicating all columns and tables except those - * explicitly removed). To do so, the client passes true as - * 'monitor_everything_by_default' to ovsdb_idl_create() and then calls - * ovsdb_idl_omit() to remove columns. - * - * There are multiple modes a column may be replicated: - * - * - Read-only. This is the default. Whenever the column changes in any - * replicated row, the value returned by ovsdb_idl_get_seqno() will change, - * letting the client know to look at the replicated data again. - * - * - Write-only. This is for columns that the client sets and updates but - * does not want to be alerted about its own updates (which, at the OVSDB - * level, cannot be distinguished from updates made by any other client). - * The column will be replicated in the same way as for read-only columns, - * but the value returned by ovsdb_idl_get_seqno() will not change when the - * column changes, saving wasted CPU time. - * - * (A "write-only" client probably does read the column so that it can know - * whether it needs to update it, but it doesn't expect to react to changes - * by other clients.) - * - * To mark a replicated column as write-only, a client calls - * ovsdb_idl_omit_alert(). (The column must already be replicated one of - * the ways described in the previous list.) - * - * This is an optimization only and does not affect behavioral correctness - * of an otherwise well-written client. - * - * - Read/write. In theory, an OVSDB client might both read and write a - * column, although OVSDB schemas are usually designed so that any given - * client only does one or the other. This is actually the same as - * read/write columns; that is, the client need take no special action. - */ - -/* Modes with which the IDL can replicate a column. See above comment for - * overview. - * - * If no bits are set, the IDL does not replicate the column at all. The - * client will always see it with the default value for its type. - * - * If OVSDB_IDL_MONITOR is set, then the IDL replicates the column and sets it - * to to the value in the database. If OVSDB_IDL_ALERT is also set, then the - * IDL will change the value returned by ovsdb_idl_get_seqno() when the - * column's value changes in any row. - * - * The possible mode combinations are: - * - * - 0, for a column that a client doesn't care about. This is the default - * for every column in every table, if the client passes false for - * 'monitor_everything_by_default' to ovsdb_idl_create(). - * - * - (OVSDB_IDL_MONITOR | OVSDB_IDL_ALERT), for a column that a client wants - * to track and possibly update. This is the default for every column in - * every table, if the client passes true for - * 'monitor_everything_by_default' to ovsdb_idl_create(). - * - * - OVSDB_IDL_MONITOR, for columns that a client treats as "write-only", - * that is, it updates them but doesn't want to get alerted about its own - * updates. It also won't be alerted about other clients' updates, so this - * is suitable only for use by a client that "owns" a particular column. - * Use ovsdb_idl_omit_alert() to set a column that is already replicated to - * this mode. - * - * - OVDSB_IDL_ALERT without OVSDB_IDL_MONITOR is not valid. - * - * - (OVSDB_IDL_MONITOR | OVSDB_IDL_ALERT | OVSDB_IDL_TRACK), for a column - * that a client wants to track using the change tracking - * ovsdb_idl_track_get_*() functions. - */ -#define OVSDB_IDL_MONITOR (1 << 0) /* Replicate this column? */ -#define OVSDB_IDL_ALERT (1 << 1) /* Alert client when column changes? */ -#define OVSDB_IDL_TRACK (1 << 2) - -void ovsdb_idl_add_column(struct ovsdb_idl *, const struct ovsdb_idl_column *); -void ovsdb_idl_add_table(struct ovsdb_idl *, - const struct ovsdb_idl_table_class *); - -void ovsdb_idl_omit(struct ovsdb_idl *, const struct ovsdb_idl_column *); -void ovsdb_idl_omit_alert(struct ovsdb_idl *, const struct ovsdb_idl_column *); - -/* Change tracking. - * - * In OVSDB, change tracking is applied at each client in the IDL layer. This - * means that when a client makes a request to track changes on a particular - * table, they are essentially requesting information about the incremental - * changes to that table from the point in time that the request is made. Once - * the client clears tracked changes, that information will no longer be - * available. - * - * The implication of the above is that if a client requires replaying - * untracked history, it faces the choice of either trying to remember changes - * itself (which translates into a memory leak) or of being structured with a - * path for processing the full untracked table as well as a path that - * processes incremental changes. */ -enum ovsdb_idl_change { - OVSDB_IDL_CHANGE_INSERT, - OVSDB_IDL_CHANGE_MODIFY, - OVSDB_IDL_CHANGE_DELETE, - OVSDB_IDL_CHANGE_MAX -}; - -/* Row, table sequence numbers */ -unsigned int ovsdb_idl_table_get_seqno( - const struct ovsdb_idl *idl, - const struct ovsdb_idl_table_class *table_class); -unsigned int ovsdb_idl_row_get_seqno( - const struct ovsdb_idl_row *row, - enum ovsdb_idl_change change); - -void ovsdb_idl_track_add_column(struct ovsdb_idl *idl, - const struct ovsdb_idl_column *column); -void ovsdb_idl_track_add_all(struct ovsdb_idl *idl); -bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table); -const struct ovsdb_idl_row *ovsdb_idl_track_get_first( - const struct ovsdb_idl *, const struct ovsdb_idl_table_class *); -const struct ovsdb_idl_row *ovsdb_idl_track_get_next(const struct ovsdb_idl_row *); -bool ovsdb_idl_track_is_updated(const struct ovsdb_idl_row *row, - const struct ovsdb_idl_column *column); -void ovsdb_idl_track_clear(struct ovsdb_idl *); - - -/* Reading the database replica. */ - -const struct ovsdb_idl_row *ovsdb_idl_get_row_for_uuid( - const struct ovsdb_idl *, const struct ovsdb_idl_table_class *, - const struct uuid *); -const struct ovsdb_idl_row *ovsdb_idl_first_row( - const struct ovsdb_idl *, const struct ovsdb_idl_table_class *); -const struct ovsdb_idl_row *ovsdb_idl_next_row(const struct ovsdb_idl_row *); - -const struct ovsdb_datum *ovsdb_idl_read(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *); -const struct ovsdb_datum *ovsdb_idl_get(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - enum ovsdb_atomic_type key_type, - enum ovsdb_atomic_type value_type); -bool ovsdb_idl_is_mutable(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *); - -bool ovsdb_idl_row_is_synthetic(const struct ovsdb_idl_row *); - -/* Transactions. - * - * A transaction may modify the contents of a database by modifying the values - * of columns, deleting rows, inserting rows, or adding checks that columns in - * the database have not changed ("verify" operations), through - * ovsdb_idl_txn_*() functions. (The OVSDB IDL code generator produces helper - * functions that internally call the ovsdb_idl_txn_*() functions. These are - * likely to be more convenient.) - * - * Reading and writing columns and inserting and deleting rows are all - * straightforward. The reasons to verify columns are less obvious. - * Verification is the key to maintaining transactional integrity. Because - * OVSDB handles multiple clients, it can happen that between the time that - * OVSDB client A reads a column and writes a new value, OVSDB client B has - * written that column. Client A's write should not ordinarily overwrite - * client B's, especially if the column in question is a "map" column that - * contains several more or less independent data items. If client A adds a - * "verify" operation before it writes the column, then the transaction fails - * in case client B modifies it first. Client A will then see the new value of - * the column and compose a new transaction based on the new contents written - * by client B. - * - * When a transaction is complete, which must be before the next call to - * ovsdb_idl_run() on 'idl', call ovsdb_idl_txn_commit() or - * ovsdb_idl_txn_abort(). - * - * The life-cycle of a transaction looks like this: - * - * 1. Create the transaction and record the initial sequence number: - * - * seqno = ovsdb_idl_get_seqno(idl); - * txn = ovsdb_idl_txn_create(idl); - * - * 2. Modify the database with ovsdb_idl_txn_*() functions directly or - * indirectly. - * - * 3. Commit the transaction by calling ovsdb_idl_txn_commit(). The first call - * to this function probably returns TXN_INCOMPLETE. The client must keep - * calling again along as this remains true, calling ovsdb_idl_run() in - * between to let the IDL do protocol processing. (If the client doesn't - * have anything else to do in the meantime, it can use - * ovsdb_idl_txn_commit_block() to avoid having to loop itself.) - * - * 4. If the final status is TXN_TRY_AGAIN, wait for ovsdb_idl_get_seqno() to - * change from the saved 'seqno' (it's possible that it's already changed, - * in which case the client should not wait at all), then start over from - * step 1. Only a call to ovsdb_idl_run() will change the return value of - * ovsdb_idl_get_seqno(). (ovsdb_idl_txn_commit_block() calls - * ovsdb_idl_run().) - */ - -enum ovsdb_idl_txn_status { - TXN_UNCOMMITTED, /* Not yet committed or aborted. */ - TXN_UNCHANGED, /* Transaction didn't include any changes. */ - TXN_INCOMPLETE, /* Commit in progress, please wait. */ - TXN_ABORTED, /* ovsdb_idl_txn_abort() called. */ - TXN_SUCCESS, /* Commit successful. */ - TXN_TRY_AGAIN, /* Commit failed because a "verify" operation - * reported an inconsistency, due to a network - * problem, or other transient failure. Wait - * for a change, then try again. */ - TXN_NOT_LOCKED, /* Server hasn't given us the lock yet. */ - TXN_ERROR /* Commit failed due to a hard error. */ -}; - -const char *ovsdb_idl_txn_status_to_string(enum ovsdb_idl_txn_status); - -struct ovsdb_idl_txn *ovsdb_idl_txn_create(struct ovsdb_idl *); -void ovsdb_idl_txn_add_comment(struct ovsdb_idl_txn *, const char *, ...) - OVS_PRINTF_FORMAT (2, 3); -void ovsdb_idl_txn_set_dry_run(struct ovsdb_idl_txn *); -void ovsdb_idl_txn_increment(struct ovsdb_idl_txn *, - const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - bool force); -void ovsdb_idl_txn_destroy(struct ovsdb_idl_txn *); -void ovsdb_idl_txn_wait(const struct ovsdb_idl_txn *); -enum ovsdb_idl_txn_status ovsdb_idl_txn_commit(struct ovsdb_idl_txn *); -enum ovsdb_idl_txn_status ovsdb_idl_txn_commit_block(struct ovsdb_idl_txn *); -void ovsdb_idl_txn_abort(struct ovsdb_idl_txn *); - -const char *ovsdb_idl_txn_get_error(const struct ovsdb_idl_txn *); - -int64_t ovsdb_idl_txn_get_increment_new_value(const struct ovsdb_idl_txn *); -const struct uuid *ovsdb_idl_txn_get_insert_uuid(const struct ovsdb_idl_txn *, - const struct uuid *); - -void ovsdb_idl_txn_write(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - struct ovsdb_datum *); -void ovsdb_idl_txn_write_clone(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - const struct ovsdb_datum *); -void ovsdb_idl_txn_write_partial_map(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - struct ovsdb_datum *); -void ovsdb_idl_txn_delete_partial_map(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - struct ovsdb_datum *); -void ovsdb_idl_txn_write_partial_set(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - struct ovsdb_datum *); -void ovsdb_idl_txn_delete_partial_set(const struct ovsdb_idl_row *, - const struct ovsdb_idl_column *, - struct ovsdb_datum *); -void ovsdb_idl_txn_delete(const struct ovsdb_idl_row *); -const struct ovsdb_idl_row *ovsdb_idl_txn_insert( - struct ovsdb_idl_txn *, const struct ovsdb_idl_table_class *, - const struct uuid *); - -struct ovsdb_idl *ovsdb_idl_txn_get_idl (struct ovsdb_idl_txn *); -void ovsdb_idl_get_initial_snapshot(struct ovsdb_idl *); - - -/* ovsdb_idl_loop provides an easy way to manage the transactions related - * to 'idl' and to cope with different status during transaction. */ -struct ovsdb_idl_loop { - struct ovsdb_idl *idl; - unsigned int skip_seqno; - - struct ovsdb_idl_txn *committing_txn; - unsigned int precommit_seqno; - - struct ovsdb_idl_txn *open_txn; - - /* These members allow a client a simple, stateless way to keep track of - * transactions that commit: when a transaction commits successfully, - * ovsdb_idl_loop_commit_and_wait() copies 'next_cfg' to 'cur_cfg'. Thus, - * the client can set 'next_cfg' to a value that indicates a successful - * commit and check 'cur_cfg' on each iteration. */ - int64_t cur_cfg; - int64_t next_cfg; -}; - -#define OVSDB_IDL_LOOP_INITIALIZER(IDL) { .idl = (IDL) } - -void ovsdb_idl_loop_destroy(struct ovsdb_idl_loop *); -struct ovsdb_idl_txn *ovsdb_idl_loop_run(struct ovsdb_idl_loop *); -int ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *); - -/* Conditional Replication - * ======================= - * - * By default, when the IDL replicates a particular table in the database, it - * replicates every row in the table. These functions allow the client to - * specify that only selected rows should be replicated, by constructing a - * per-table condition that specifies the rows to replicate. - * - * A condition is a disjunction of clauses. The condition is true, and thus a - * row is replicated, if any of the clauses evaluates to true for a given row. - * (Thus, a condition with no clauses is always false.) - */ - -struct ovsdb_idl_condition { - struct hmap clauses; /* Contains "struct ovsdb_idl_clause"s. */ - bool is_true; /* Is the condition unconditionally true? */ -}; -#define OVSDB_IDL_CONDITION_INIT(CONDITION) \ - { HMAP_INITIALIZER(&(CONDITION)->clauses), false } - -void ovsdb_idl_condition_init(struct ovsdb_idl_condition *); -void ovsdb_idl_condition_clear(struct ovsdb_idl_condition *); -void ovsdb_idl_condition_destroy(struct ovsdb_idl_condition *); -void ovsdb_idl_condition_add_clause(struct ovsdb_idl_condition *, - enum ovsdb_function function, - const struct ovsdb_idl_column *column, - const struct ovsdb_datum *arg); -void ovsdb_idl_condition_add_clause_true(struct ovsdb_idl_condition *); -bool ovsdb_idl_condition_is_true(const struct ovsdb_idl_condition *); - -unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *, - const struct ovsdb_idl_table_class *, - const struct ovsdb_idl_condition *); - -unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *); - -/* Indexes over one or more columns in the IDL, to retrieve rows matching - * particular search criteria and to iterate over a subset of rows in a defined - * order. */ - -enum ovsdb_index_order { - OVSDB_INDEX_ASC, /* 0, 1, 2, ... */ - OVSDB_INDEX_DESC /* 2, 1, 0, ... */ -}; - -typedef int column_comparator_func(const void *a, const void *b); - -struct ovsdb_idl_index_column { - const struct ovsdb_idl_column *column; - column_comparator_func *comparer; - enum ovsdb_index_order order; -}; - -/* Creating an index. */ -struct ovsdb_idl_index *ovsdb_idl_index_create( - struct ovsdb_idl *, const struct ovsdb_idl_index_column *, size_t n); -struct ovsdb_idl_index *ovsdb_idl_index_create1( - struct ovsdb_idl *, const struct ovsdb_idl_column *); -struct ovsdb_idl_index *ovsdb_idl_index_create2( - struct ovsdb_idl *, const struct ovsdb_idl_column *, - const struct ovsdb_idl_column *); - -/* Searching an index. */ -struct ovsdb_idl_row *ovsdb_idl_index_find(struct ovsdb_idl_index *, - const struct ovsdb_idl_row *); - -/* Iteration over an index. - * - * Usually these would be invoked through table-specific wrappers generated - * by the IDL. */ - -struct ovsdb_idl_cursor { - struct ovsdb_idl_index *index; /* Index being iterated. */ - struct skiplist_node *position; /* Current position in 'index'. */ -}; - -struct ovsdb_idl_cursor ovsdb_idl_cursor_first(struct ovsdb_idl_index *); -struct ovsdb_idl_cursor ovsdb_idl_cursor_first_eq( - struct ovsdb_idl_index *, const struct ovsdb_idl_row *); -struct ovsdb_idl_cursor ovsdb_idl_cursor_first_ge( - struct ovsdb_idl_index *, const struct ovsdb_idl_row *); - -void ovsdb_idl_cursor_next(struct ovsdb_idl_cursor *); -void ovsdb_idl_cursor_next_eq(struct ovsdb_idl_cursor *); - -struct ovsdb_idl_row *ovsdb_idl_cursor_data(struct ovsdb_idl_cursor *); - -#ifdef __cplusplus -} -#endif - -#endif /* ovsdb-idl.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-idl.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-idl.h @@ -0,0 +1,488 @@ +/* Copyright (c) 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2019 Nicira, Inc. + * Copyright (C) 2016 Hewlett Packard Enterprise Development LP + * + * 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 OVSDB_IDL_H +#define OVSDB_IDL_H 1 + +/* Open vSwitch Database Interface Definition Language (OVSDB IDL). + * + * The OVSDB IDL maintains an in-memory replica of a database. It issues RPC + * requests to an OVSDB database server and parses the responses, converting + * raw JSON into data structures that are easier for clients to digest. Most + * notably, references to rows via UUID become C pointers. + * + * The IDL always presents a consistent snapshot of the database to its client, + * that is, it won't present the effects of some part of a transaction applied + * at the database server without presenting all of its effects. + * + * The IDL also assists with issuing database transactions. The client creates + * a transaction, manipulates the IDL data structures, and commits or aborts + * the transaction. The IDL then composes and issues the necessary JSON-RPC + * requests and reports to the client whether the transaction completed + * successfully. + */ + +#include +#include +#include "openvswitch/compiler.h" +#include "openvswitch/ovsdb-types.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/list.h" +#include "openvswitch/ovsdb-condition.h" +#include "internal/skiplist.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct json; +struct ovsdb_datum; +struct ovsdb_idl_class; +struct ovsdb_idl_row; +struct ovsdb_idl_column; +struct ovsdb_idl_table; +struct ovsdb_idl_table_class; +struct simap; +struct uuid; + +struct ovsdb_idl *ovsdb_idl_create(const char *remote, + const struct ovsdb_idl_class *, + bool monitor_everything_by_default, + bool retry); +struct ovsdb_idl *ovsdb_idl_create_unconnected( + const struct ovsdb_idl_class *, bool monitor_everything_by_default); +void ovsdb_idl_set_remote(struct ovsdb_idl *, const char *remote, bool retry); +void ovsdb_idl_set_shuffle_remotes(struct ovsdb_idl *, bool shuffle); +void ovsdb_idl_reset_min_index(struct ovsdb_idl *); +void ovsdb_idl_destroy(struct ovsdb_idl *); + +void ovsdb_idl_set_leader_only(struct ovsdb_idl *, bool leader_only); + +void ovsdb_idl_run(struct ovsdb_idl *); +void ovsdb_idl_wait(struct ovsdb_idl *); + +void ovsdb_idl_get_memory_usage(struct ovsdb_idl *, struct simap *usage); + +void ovsdb_idl_set_lock(struct ovsdb_idl *, const char *lock_name); +bool ovsdb_idl_has_lock(const struct ovsdb_idl *); +bool ovsdb_idl_is_lock_contended(const struct ovsdb_idl *); + +unsigned int ovsdb_idl_get_seqno(const struct ovsdb_idl *); +bool ovsdb_idl_has_ever_connected(const struct ovsdb_idl *); +void ovsdb_idl_enable_reconnect(struct ovsdb_idl *); +void ovsdb_idl_force_reconnect(struct ovsdb_idl *); +void ovsdb_idl_verify_write_only(struct ovsdb_idl *); + +bool ovsdb_idl_is_alive(const struct ovsdb_idl *); +bool ovsdb_idl_is_connected(const struct ovsdb_idl *idl); +int ovsdb_idl_get_last_error(const struct ovsdb_idl *); + +void ovsdb_idl_set_probe_interval(const struct ovsdb_idl *, int probe_interval); + +void ovsdb_idl_check_consistency(const struct ovsdb_idl *); + +const struct ovsdb_idl_class *ovsdb_idl_get_class(const struct ovsdb_idl *); +const struct ovsdb_idl_table_class *ovsdb_idl_table_class_from_column( + const struct ovsdb_idl_class *, const struct ovsdb_idl_column *); +bool ovsdb_idl_server_has_table(const struct ovsdb_idl *, + const struct ovsdb_idl_table_class *); +bool ovsdb_idl_server_has_column(const struct ovsdb_idl *, + const struct ovsdb_idl_column *); + +/* Choosing columns and tables to replicate. + * + * The client may choose any subset of the columns and tables to replicate, + * specifying it one of two ways: + * + * - As a deny list (adding the columns or tables to replicate). To do so, + * the client passes false as 'monitor_everything_by_default' to + * ovsdb_idl_create() and then calls ovsdb_idl_add_column() and + * ovsdb_idl_add_table() for the desired columns and, if necessary, tables. + * + * - As an allow list (replicating all columns and tables except those + * explicitly removed). To do so, the client passes true as + * 'monitor_everything_by_default' to ovsdb_idl_create() and then calls + * ovsdb_idl_omit() to remove columns. + * + * There are multiple modes a column may be replicated: + * + * - Read-only. This is the default. Whenever the column changes in any + * replicated row, the value returned by ovsdb_idl_get_seqno() will change, + * letting the client know to look at the replicated data again. + * + * - Write-only. This is for columns that the client sets and updates but + * does not want to be alerted about its own updates (which, at the OVSDB + * level, cannot be distinguished from updates made by any other client). + * The column will be replicated in the same way as for read-only columns, + * but the value returned by ovsdb_idl_get_seqno() will not change when the + * column changes, saving wasted CPU time. + * + * (A "write-only" client probably does read the column so that it can know + * whether it needs to update it, but it doesn't expect to react to changes + * by other clients.) + * + * To mark a replicated column as write-only, a client calls + * ovsdb_idl_omit_alert(). (The column must already be replicated one of + * the ways described in the previous list.) + * + * This is an optimization only and does not affect behavioral correctness + * of an otherwise well-written client. + * + * - Read/write. In theory, an OVSDB client might both read and write a + * column, although OVSDB schemas are usually designed so that any given + * client only does one or the other. This is actually the same as + * read/write columns; that is, the client need take no special action. + */ + +/* Modes with which the IDL can replicate a column. See above comment for + * overview. + * + * If no bits are set, the IDL does not replicate the column at all. The + * client will always see it with the default value for its type. + * + * If OVSDB_IDL_MONITOR is set, then the IDL replicates the column and sets it + * to to the value in the database. If OVSDB_IDL_ALERT is also set, then the + * IDL will change the value returned by ovsdb_idl_get_seqno() when the + * column's value changes in any row. + * + * The possible mode combinations are: + * + * - 0, for a column that a client doesn't care about. This is the default + * for every column in every table, if the client passes false for + * 'monitor_everything_by_default' to ovsdb_idl_create(). + * + * - (OVSDB_IDL_MONITOR | OVSDB_IDL_ALERT), for a column that a client wants + * to track and possibly update. This is the default for every column in + * every table, if the client passes true for + * 'monitor_everything_by_default' to ovsdb_idl_create(). + * + * - OVSDB_IDL_MONITOR, for columns that a client treats as "write-only", + * that is, it updates them but doesn't want to get alerted about its own + * updates. It also won't be alerted about other clients' updates, so this + * is suitable only for use by a client that "owns" a particular column. + * Use ovsdb_idl_omit_alert() to set a column that is already replicated to + * this mode. + * + * - OVDSB_IDL_ALERT without OVSDB_IDL_MONITOR is not valid. + * + * - (OVSDB_IDL_MONITOR | OVSDB_IDL_ALERT | OVSDB_IDL_TRACK), for a column + * that a client wants to track using the change tracking + * ovsdb_idl_track_get_*() functions. + */ +#define OVSDB_IDL_MONITOR (1 << 0) /* Replicate this column? */ +#define OVSDB_IDL_ALERT (1 << 1) /* Alert client when column changes? */ +#define OVSDB_IDL_TRACK (1 << 2) + +void ovsdb_idl_add_column(struct ovsdb_idl *, const struct ovsdb_idl_column *); +void ovsdb_idl_add_table(struct ovsdb_idl *, + const struct ovsdb_idl_table_class *); + +void ovsdb_idl_omit(struct ovsdb_idl *, const struct ovsdb_idl_column *); +void ovsdb_idl_omit_alert(struct ovsdb_idl *, const struct ovsdb_idl_column *); + +/* Change tracking. + * + * In OVSDB, change tracking is applied at each client in the IDL layer. This + * means that when a client makes a request to track changes on a particular + * table, they are essentially requesting information about the incremental + * changes to that table from the point in time that the request is made. Once + * the client clears tracked changes, that information will no longer be + * available. + * + * The implication of the above is that if a client requires replaying + * untracked history, it faces the choice of either trying to remember changes + * itself (which translates into a memory leak) or of being structured with a + * path for processing the full untracked table as well as a path that + * processes incremental changes. */ +enum ovsdb_idl_change { + OVSDB_IDL_CHANGE_INSERT, + OVSDB_IDL_CHANGE_MODIFY, + OVSDB_IDL_CHANGE_DELETE, + OVSDB_IDL_CHANGE_MAX +}; + +/* Row, table sequence numbers */ +unsigned int ovsdb_idl_table_get_seqno( + const struct ovsdb_idl *idl, + const struct ovsdb_idl_table_class *table_class); +unsigned int ovsdb_idl_row_get_seqno( + const struct ovsdb_idl_row *row, + enum ovsdb_idl_change change); + +void ovsdb_idl_track_add_column(struct ovsdb_idl *idl, + const struct ovsdb_idl_column *column); +void ovsdb_idl_track_add_all(struct ovsdb_idl *idl); +bool ovsdb_idl_track_is_set(struct ovsdb_idl_table *table); +const struct ovsdb_idl_row *ovsdb_idl_track_get_first( + const struct ovsdb_idl *, const struct ovsdb_idl_table_class *); +const struct ovsdb_idl_row *ovsdb_idl_track_get_next(const struct ovsdb_idl_row *); +bool ovsdb_idl_track_is_updated(const struct ovsdb_idl_row *row, + const struct ovsdb_idl_column *column); +void ovsdb_idl_track_clear(struct ovsdb_idl *); + + +/* Reading the database replica. */ + +const struct ovsdb_idl_row *ovsdb_idl_get_row_for_uuid( + const struct ovsdb_idl *, const struct ovsdb_idl_table_class *, + const struct uuid *); +const struct ovsdb_idl_row *ovsdb_idl_first_row( + const struct ovsdb_idl *, const struct ovsdb_idl_table_class *); +const struct ovsdb_idl_row *ovsdb_idl_next_row(const struct ovsdb_idl_row *); + +const struct ovsdb_datum *ovsdb_idl_read(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *); +const struct ovsdb_datum *ovsdb_idl_get(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + enum ovsdb_atomic_type key_type, + enum ovsdb_atomic_type value_type); +bool ovsdb_idl_is_mutable(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *); + +bool ovsdb_idl_row_is_synthetic(const struct ovsdb_idl_row *); + +/* Transactions. + * + * A transaction may modify the contents of a database by modifying the values + * of columns, deleting rows, inserting rows, or adding checks that columns in + * the database have not changed ("verify" operations), through + * ovsdb_idl_txn_*() functions. (The OVSDB IDL code generator produces helper + * functions that internally call the ovsdb_idl_txn_*() functions. These are + * likely to be more convenient.) + * + * Reading and writing columns and inserting and deleting rows are all + * straightforward. The reasons to verify columns are less obvious. + * Verification is the key to maintaining transactional integrity. Because + * OVSDB handles multiple clients, it can happen that between the time that + * OVSDB client A reads a column and writes a new value, OVSDB client B has + * written that column. Client A's write should not ordinarily overwrite + * client B's, especially if the column in question is a "map" column that + * contains several more or less independent data items. If client A adds a + * "verify" operation before it writes the column, then the transaction fails + * in case client B modifies it first. Client A will then see the new value of + * the column and compose a new transaction based on the new contents written + * by client B. + * + * When a transaction is complete, which must be before the next call to + * ovsdb_idl_run() on 'idl', call ovsdb_idl_txn_commit() or + * ovsdb_idl_txn_abort(). + * + * The life-cycle of a transaction looks like this: + * + * 1. Create the transaction and record the initial sequence number: + * + * seqno = ovsdb_idl_get_seqno(idl); + * txn = ovsdb_idl_txn_create(idl); + * + * 2. Modify the database with ovsdb_idl_txn_*() functions directly or + * indirectly. + * + * 3. Commit the transaction by calling ovsdb_idl_txn_commit(). The first call + * to this function probably returns TXN_INCOMPLETE. The client must keep + * calling again along as this remains true, calling ovsdb_idl_run() in + * between to let the IDL do protocol processing. (If the client doesn't + * have anything else to do in the meantime, it can use + * ovsdb_idl_txn_commit_block() to avoid having to loop itself.) + * + * 4. If the final status is TXN_TRY_AGAIN, wait for ovsdb_idl_get_seqno() to + * change from the saved 'seqno' (it's possible that it's already changed, + * in which case the client should not wait at all), then start over from + * step 1. Only a call to ovsdb_idl_run() will change the return value of + * ovsdb_idl_get_seqno(). (ovsdb_idl_txn_commit_block() calls + * ovsdb_idl_run().) + */ + +enum ovsdb_idl_txn_status { + TXN_UNCOMMITTED, /* Not yet committed or aborted. */ + TXN_UNCHANGED, /* Transaction didn't include any changes. */ + TXN_INCOMPLETE, /* Commit in progress, please wait. */ + TXN_ABORTED, /* ovsdb_idl_txn_abort() called. */ + TXN_SUCCESS, /* Commit successful. */ + TXN_TRY_AGAIN, /* Commit failed because a "verify" operation + * reported an inconsistency, due to a network + * problem, or other transient failure. Wait + * for a change, then try again. */ + TXN_NOT_LOCKED, /* Server hasn't given us the lock yet. */ + TXN_ERROR /* Commit failed due to a hard error. */ +}; + +const char *ovsdb_idl_txn_status_to_string(enum ovsdb_idl_txn_status); + +struct ovsdb_idl_txn *ovsdb_idl_txn_create(struct ovsdb_idl *); +void ovsdb_idl_txn_add_comment(struct ovsdb_idl_txn *, const char *, ...) + OVS_PRINTF_FORMAT (2, 3); +void ovsdb_idl_txn_set_dry_run(struct ovsdb_idl_txn *); +void ovsdb_idl_txn_increment(struct ovsdb_idl_txn *, + const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + bool force); +void ovsdb_idl_txn_destroy(struct ovsdb_idl_txn *); +void ovsdb_idl_txn_wait(const struct ovsdb_idl_txn *); +enum ovsdb_idl_txn_status ovsdb_idl_txn_commit(struct ovsdb_idl_txn *); +enum ovsdb_idl_txn_status ovsdb_idl_txn_commit_block(struct ovsdb_idl_txn *); +void ovsdb_idl_txn_abort(struct ovsdb_idl_txn *); + +const char *ovsdb_idl_txn_get_error(const struct ovsdb_idl_txn *); + +int64_t ovsdb_idl_txn_get_increment_new_value(const struct ovsdb_idl_txn *); +const struct uuid *ovsdb_idl_txn_get_insert_uuid(const struct ovsdb_idl_txn *, + const struct uuid *); + +void ovsdb_idl_txn_write(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + struct ovsdb_datum *); +void ovsdb_idl_txn_write_clone(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + const struct ovsdb_datum *); +void ovsdb_idl_txn_write_partial_map(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + struct ovsdb_datum *); +void ovsdb_idl_txn_delete_partial_map(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + struct ovsdb_datum *); +void ovsdb_idl_txn_write_partial_set(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + struct ovsdb_datum *); +void ovsdb_idl_txn_delete_partial_set(const struct ovsdb_idl_row *, + const struct ovsdb_idl_column *, + struct ovsdb_datum *); +void ovsdb_idl_txn_delete(const struct ovsdb_idl_row *); +const struct ovsdb_idl_row *ovsdb_idl_txn_insert( + struct ovsdb_idl_txn *, const struct ovsdb_idl_table_class *, + const struct uuid *); + +struct ovsdb_idl *ovsdb_idl_txn_get_idl (struct ovsdb_idl_txn *); +void ovsdb_idl_get_initial_snapshot(struct ovsdb_idl *); + + +/* ovsdb_idl_loop provides an easy way to manage the transactions related + * to 'idl' and to cope with different status during transaction. */ +struct ovsdb_idl_loop { + struct ovsdb_idl *idl; + unsigned int skip_seqno; + + struct ovsdb_idl_txn *committing_txn; + unsigned int precommit_seqno; + + struct ovsdb_idl_txn *open_txn; + + /* These members allow a client a simple, stateless way to keep track of + * transactions that commit: when a transaction commits successfully, + * ovsdb_idl_loop_commit_and_wait() copies 'next_cfg' to 'cur_cfg'. Thus, + * the client can set 'next_cfg' to a value that indicates a successful + * commit and check 'cur_cfg' on each iteration. */ + int64_t cur_cfg; + int64_t next_cfg; +}; + +#define OVSDB_IDL_LOOP_INITIALIZER(IDL) { .idl = (IDL) } + +void ovsdb_idl_loop_destroy(struct ovsdb_idl_loop *); +struct ovsdb_idl_txn *ovsdb_idl_loop_run(struct ovsdb_idl_loop *); +int ovsdb_idl_loop_commit_and_wait(struct ovsdb_idl_loop *); + +/* Conditional Replication + * ======================= + * + * By default, when the IDL replicates a particular table in the database, it + * replicates every row in the table. These functions allow the client to + * specify that only selected rows should be replicated, by constructing a + * per-table condition that specifies the rows to replicate. + * + * A condition is a disjunction of clauses. The condition is true, and thus a + * row is replicated, if any of the clauses evaluates to true for a given row. + * (Thus, a condition with no clauses is always false.) + */ + +struct ovsdb_idl_condition { + struct hmap clauses; /* Contains "struct ovsdb_idl_clause"s. */ + bool is_true; /* Is the condition unconditionally true? */ +}; +#define OVSDB_IDL_CONDITION_INIT(CONDITION) \ + { HMAP_INITIALIZER(&(CONDITION)->clauses), false } + +void ovsdb_idl_condition_init(struct ovsdb_idl_condition *); +void ovsdb_idl_condition_clear(struct ovsdb_idl_condition *); +void ovsdb_idl_condition_destroy(struct ovsdb_idl_condition *); +void ovsdb_idl_condition_add_clause(struct ovsdb_idl_condition *, + enum ovsdb_function function, + const struct ovsdb_idl_column *column, + const struct ovsdb_datum *arg); +void ovsdb_idl_condition_add_clause_true(struct ovsdb_idl_condition *); +bool ovsdb_idl_condition_is_true(const struct ovsdb_idl_condition *); + +unsigned int ovsdb_idl_set_condition(struct ovsdb_idl *, + const struct ovsdb_idl_table_class *, + const struct ovsdb_idl_condition *); + +unsigned int ovsdb_idl_get_condition_seqno(const struct ovsdb_idl *); + +/* Indexes over one or more columns in the IDL, to retrieve rows matching + * particular search criteria and to iterate over a subset of rows in a defined + * order. */ + +enum ovsdb_index_order { + OVSDB_INDEX_ASC, /* 0, 1, 2, ... */ + OVSDB_INDEX_DESC /* 2, 1, 0, ... */ +}; + +typedef int column_comparator_func(const void *a, const void *b); + +struct ovsdb_idl_index_column { + const struct ovsdb_idl_column *column; + column_comparator_func *comparer; + enum ovsdb_index_order order; +}; + +/* Creating an index. */ +struct ovsdb_idl_index *ovsdb_idl_index_create( + struct ovsdb_idl *, const struct ovsdb_idl_index_column *, size_t n); +struct ovsdb_idl_index *ovsdb_idl_index_create1( + struct ovsdb_idl *, const struct ovsdb_idl_column *); +struct ovsdb_idl_index *ovsdb_idl_index_create2( + struct ovsdb_idl *, const struct ovsdb_idl_column *, + const struct ovsdb_idl_column *); + +/* Searching an index. */ +struct ovsdb_idl_row *ovsdb_idl_index_find(struct ovsdb_idl_index *, + const struct ovsdb_idl_row *); + +/* Iteration over an index. + * + * Usually these would be invoked through table-specific wrappers generated + * by the IDL. */ + +struct ovsdb_idl_cursor { + struct ovsdb_idl_index *index; /* Index being iterated. */ + struct skiplist_node *position; /* Current position in 'index'. */ +}; + +struct ovsdb_idl_cursor ovsdb_idl_cursor_first(struct ovsdb_idl_index *); +struct ovsdb_idl_cursor ovsdb_idl_cursor_first_eq( + struct ovsdb_idl_index *, const struct ovsdb_idl_row *); +struct ovsdb_idl_cursor ovsdb_idl_cursor_first_ge( + struct ovsdb_idl_index *, const struct ovsdb_idl_row *); + +void ovsdb_idl_cursor_next(struct ovsdb_idl_cursor *); +void ovsdb_idl_cursor_next_eq(struct ovsdb_idl_cursor *); + +struct ovsdb_idl_row *ovsdb_idl_cursor_data(struct ovsdb_idl_cursor *); + +#ifdef __cplusplus +} +#endif + +#endif /* ovsdb-idl.h */ Index: openvswitch-2.17.2/lib/ovsdb-map-op.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-map-op.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2016 Hewlett Packard Enterprise Development LP - * All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - *     http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -#ifndef OVSDB_MAP_OP_H -#define OVSDB_MAP_OP_H 1 - -#include "ovsdb-data.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum map_op_type { - MAP_OP_UPDATE, - MAP_OP_INSERT, - MAP_OP_DELETE -}; - -struct map_op; /* Map Operation: a Partial Map Update */ -struct map_op_list; /* List of Map Operations */ - -/* Map Operation functions */ -struct map_op *map_op_create(struct ovsdb_datum *, enum map_op_type); -void map_op_destroy(struct map_op *, const struct ovsdb_type *); -struct ovsdb_datum *map_op_datum(const struct map_op*); -enum map_op_type map_op_type(const struct map_op*); - -/* Map Operation List functions */ -struct map_op_list *map_op_list_create(void); -void map_op_list_destroy(struct map_op_list *, const struct ovsdb_type *); -void map_op_list_add(struct map_op_list *, struct map_op *, - const struct ovsdb_type *); -struct map_op *map_op_list_first(struct map_op_list *); -struct map_op *map_op_list_next(struct map_op_list *, struct map_op *); - -#ifdef __cplusplus -} -#endif - -#endif /* ovsdb-map-op.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-map-op.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-map-op.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2016 Hewlett Packard Enterprise Development LP + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#ifndef OVSDB_MAP_OP_H +#define OVSDB_MAP_OP_H 1 + +#include "openvswitch/ovsdb-data.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum map_op_type { + MAP_OP_UPDATE, + MAP_OP_INSERT, + MAP_OP_DELETE +}; + +struct map_op; /* Map Operation: a Partial Map Update */ +struct map_op_list; /* List of Map Operations */ + +/* Map Operation functions */ +struct map_op *map_op_create(struct ovsdb_datum *, enum map_op_type); +void map_op_destroy(struct map_op *, const struct ovsdb_type *); +struct ovsdb_datum *map_op_datum(const struct map_op*); +enum map_op_type map_op_type(const struct map_op*); + +/* Map Operation List functions */ +struct map_op_list *map_op_list_create(void); +void map_op_list_destroy(struct map_op_list *, const struct ovsdb_type *); +void map_op_list_add(struct map_op_list *, struct map_op *, + const struct ovsdb_type *); +struct map_op *map_op_list_first(struct map_op_list *); +struct map_op *map_op_list_next(struct map_op_list *, struct map_op *); + +#ifdef __cplusplus +} +#endif + +#endif /* ovsdb-map-op.h */ Index: openvswitch-2.17.2/lib/ovsdb-parser.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-parser.h +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011, 2015, 2016 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 OVSDB_PARSER_H -#define OVSDB_PARSER_H 1 - -#include -#include "openvswitch/compiler.h" -#include "openvswitch/json.h" -#include "sset.h" -#include "util.h" - -struct ovsdb_parser { - char *name; /* Used only in error messages. */ - struct sset used; /* Already-parsed names from 'object'. */ - const struct json *json; /* JSON object being parsed. */ - struct ovsdb_error *error; /* Error signaled, if any. */ -}; - -/* Check that the JSON types make the bitwise tricks below work OK. */ -BUILD_ASSERT_DECL(JSON_NULL >= 0 && JSON_NULL < 10); -BUILD_ASSERT_DECL(JSON_FALSE >= 0 && JSON_FALSE < 10); -BUILD_ASSERT_DECL(JSON_TRUE >= 0 && JSON_TRUE < 10); -BUILD_ASSERT_DECL(JSON_OBJECT >= 0 && JSON_OBJECT < 10); -BUILD_ASSERT_DECL(JSON_ARRAY >= 0 && JSON_ARRAY < 10); -BUILD_ASSERT_DECL(JSON_INTEGER >= 0 && JSON_INTEGER < 10); -BUILD_ASSERT_DECL(JSON_REAL >= 0 && JSON_REAL < 10); -BUILD_ASSERT_DECL(JSON_STRING >= 0 && JSON_STRING < 10); -BUILD_ASSERT_DECL(JSON_N_TYPES == 8); - -enum ovsdb_parser_types { - OP_NULL = 1 << JSON_NULL, /* null */ - OP_FALSE = 1 << JSON_FALSE, /* false */ - OP_TRUE = 1 << JSON_TRUE, /* true */ - OP_OBJECT = 1 << JSON_OBJECT, /* {"a": b, "c": d, ...} */ - OP_ARRAY = 1 << JSON_ARRAY, /* [1, 2, 3, ...] */ - OP_INTEGER = 1 << JSON_INTEGER, /* 123. */ - OP_NONINTEGER = 1 << JSON_REAL, /* 123.456. */ - OP_STRING = 1 << JSON_STRING, /* "..." */ - OP_ANY = (OP_NULL | OP_FALSE | OP_TRUE | OP_OBJECT | OP_ARRAY - | OP_INTEGER | OP_NONINTEGER | OP_STRING), - - OP_BOOLEAN = OP_FALSE | OP_TRUE, - OP_NUMBER = OP_INTEGER | OP_NONINTEGER, - - OP_ID = 1 << JSON_N_TYPES, /* "[_a-zA-Z][_a-zA-Z0-9]*" */ - OP_OPTIONAL = 1 << (JSON_N_TYPES + 1) /* no value at all */ -}; - -void ovsdb_parser_init(struct ovsdb_parser *, const struct json *, - const char *name, ...) - OVS_PRINTF_FORMAT(3, 4); -const struct json *ovsdb_parser_member(struct ovsdb_parser *, const char *name, - enum ovsdb_parser_types); - -void ovsdb_parser_raise_error(struct ovsdb_parser *parser, - const char *format, ...) - OVS_PRINTF_FORMAT(2, 3); -void ovsdb_parser_put_error(struct ovsdb_parser *, struct ovsdb_error *); -bool ovsdb_parser_has_error(const struct ovsdb_parser *); -struct ovsdb_error *ovsdb_parser_get_error(const struct ovsdb_parser *); -struct ovsdb_error *ovsdb_parser_finish(struct ovsdb_parser *) - OVS_WARN_UNUSED_RESULT; -struct ovsdb_error *ovsdb_parser_destroy(struct ovsdb_parser *) - OVS_WARN_UNUSED_RESULT; - -bool ovsdb_parser_is_id(const char *string); - -#endif /* ovsdb-parser.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-parser.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-parser.h @@ -0,0 +1,89 @@ +/* Copyright (c) 2009, 2010, 2011, 2015, 2016 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 OVSDB_PARSER_H +#define OVSDB_PARSER_H 1 + +#include +#include "openvswitch/compiler.h" +#include "openvswitch/json.h" +#include "internal/sset.h" +#include "internal/util.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct ovsdb_parser { + char *name; /* Used only in error messages. */ + struct sset used; /* Already-parsed names from 'object'. */ + const struct json *json; /* JSON object being parsed. */ + struct ovsdb_error *error; /* Error signaled, if any. */ +}; + +/* Check that the JSON types make the bitwise tricks below work OK. */ +BUILD_ASSERT_DECL(JSON_NULL >= 0 && JSON_NULL < 10); +BUILD_ASSERT_DECL(JSON_FALSE >= 0 && JSON_FALSE < 10); +BUILD_ASSERT_DECL(JSON_TRUE >= 0 && JSON_TRUE < 10); +BUILD_ASSERT_DECL(JSON_OBJECT >= 0 && JSON_OBJECT < 10); +BUILD_ASSERT_DECL(JSON_ARRAY >= 0 && JSON_ARRAY < 10); +BUILD_ASSERT_DECL(JSON_INTEGER >= 0 && JSON_INTEGER < 10); +BUILD_ASSERT_DECL(JSON_REAL >= 0 && JSON_REAL < 10); +BUILD_ASSERT_DECL(JSON_STRING >= 0 && JSON_STRING < 10); +BUILD_ASSERT_DECL(JSON_N_TYPES == 8); + +enum ovsdb_parser_types { + OP_NULL = 1 << JSON_NULL, /* null */ + OP_FALSE = 1 << JSON_FALSE, /* false */ + OP_TRUE = 1 << JSON_TRUE, /* true */ + OP_OBJECT = 1 << JSON_OBJECT, /* {"a": b, "c": d, ...} */ + OP_ARRAY = 1 << JSON_ARRAY, /* [1, 2, 3, ...] */ + OP_INTEGER = 1 << JSON_INTEGER, /* 123. */ + OP_NONINTEGER = 1 << JSON_REAL, /* 123.456. */ + OP_STRING = 1 << JSON_STRING, /* "..." */ + OP_ANY = (OP_NULL | OP_FALSE | OP_TRUE | OP_OBJECT | OP_ARRAY + | OP_INTEGER | OP_NONINTEGER | OP_STRING), + + OP_BOOLEAN = OP_FALSE | OP_TRUE, + OP_NUMBER = OP_INTEGER | OP_NONINTEGER, + + OP_ID = 1 << JSON_N_TYPES, /* "[_a-zA-Z][_a-zA-Z0-9]*" */ + OP_OPTIONAL = 1 << (JSON_N_TYPES + 1) /* no value at all */ +}; + +void ovsdb_parser_init(struct ovsdb_parser *, const struct json *, + const char *name, ...) + OVS_PRINTF_FORMAT(3, 4); +const struct json *ovsdb_parser_member(struct ovsdb_parser *, const char *name, + enum ovsdb_parser_types); + +void ovsdb_parser_raise_error(struct ovsdb_parser *parser, + const char *format, ...) + OVS_PRINTF_FORMAT(2, 3); +void ovsdb_parser_put_error(struct ovsdb_parser *, struct ovsdb_error *); +bool ovsdb_parser_has_error(const struct ovsdb_parser *); +struct ovsdb_error *ovsdb_parser_get_error(const struct ovsdb_parser *); +struct ovsdb_error *ovsdb_parser_finish(struct ovsdb_parser *) + OVS_WARN_UNUSED_RESULT; +struct ovsdb_error *ovsdb_parser_destroy(struct ovsdb_parser *) + OVS_WARN_UNUSED_RESULT; + +bool ovsdb_parser_is_id(const char *string); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* ovsdb-parser.h */ Index: openvswitch-2.17.2/lib/ovsdb-set-op.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-set-op.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 2016 Hewlett Packard Enterprise Development LP - * Copyright (C) 2016, IBM - * All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -#ifndef OVSDB_SET_OP_H -#define OVSDB_SET_OP_H 1 - -#include "ovsdb-data.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum set_op_type { - SET_OP_INSERT, - SET_OP_DELETE -}; - -struct set_op; /* Set Operation: a Partial Set Update */ -struct set_op_list; /* List of Set Operations */ - -/* Set Operation functions */ -struct set_op *set_op_create(struct ovsdb_datum *, enum set_op_type); -void set_op_destroy(struct set_op *, const struct ovsdb_type *); -struct ovsdb_datum *set_op_datum(const struct set_op*); -enum set_op_type set_op_type(const struct set_op*); - -/* Set Operation List functions */ -struct set_op_list *set_op_list_create(void); -void set_op_list_destroy(struct set_op_list *, const struct ovsdb_type *); -void set_op_list_add(struct set_op_list *, struct set_op *, - const struct ovsdb_type *); -struct set_op *set_op_list_first(struct set_op_list *); -struct set_op *set_op_list_next(struct set_op_list *, struct set_op *); - -#ifdef __cplusplus -} -#endif - -#endif /* ovsdb-set-op.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-set-op.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-set-op.h @@ -0,0 +1,53 @@ +/* Copyright (C) 2016 Hewlett Packard Enterprise Development LP + * Copyright (C) 2016, IBM + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#ifndef OVSDB_SET_OP_H +#define OVSDB_SET_OP_H 1 + +#include "openvswitch/ovsdb-data.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum set_op_type { + SET_OP_INSERT, + SET_OP_DELETE +}; + +struct set_op; /* Set Operation: a Partial Set Update */ +struct set_op_list; /* List of Set Operations */ + +/* Set Operation functions */ +struct set_op *set_op_create(struct ovsdb_datum *, enum set_op_type); +void set_op_destroy(struct set_op *, const struct ovsdb_type *); +struct ovsdb_datum *set_op_datum(const struct set_op*); +enum set_op_type set_op_type(const struct set_op*); + +/* Set Operation List functions */ +struct set_op_list *set_op_list_create(void); +void set_op_list_destroy(struct set_op_list *, const struct ovsdb_type *); +void set_op_list_add(struct set_op_list *, struct set_op *, + const struct ovsdb_type *); +struct set_op *set_op_list_first(struct set_op_list *); +struct set_op *set_op_list_next(struct set_op_list *, struct set_op *); + +#ifdef __cplusplus +} +#endif + +#endif /* ovsdb-set-op.h */ Index: openvswitch-2.17.2/lib/ovsdb-types.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-types.h +++ /dev/null @@ -1,242 +0,0 @@ -/* Copyright (c) 2009, 2010, 2011 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef OVSDB_TYPES_H -#define OVSDB_TYPES_H 1 - -#include -#include -#include -#include "openvswitch/compiler.h" -#include "uuid.h" - -#ifdef __cplusplus -extern "C" { -#endif - -struct json; - -/* An atomic type: one that OVSDB regards as a single unit of data. */ -enum ovsdb_atomic_type { - OVSDB_TYPE_VOID, /* No value. */ - OVSDB_TYPE_INTEGER, /* Signed 64-bit integer. */ - OVSDB_TYPE_REAL, /* IEEE 754 double-precision floating point. */ - OVSDB_TYPE_BOOLEAN, /* True or false. */ - OVSDB_TYPE_STRING, /* UTF-8 string. */ - OVSDB_TYPE_UUID, /* RFC 4122 UUID referencing a table row. */ - OVSDB_N_TYPES -}; - -static inline bool ovsdb_atomic_type_is_valid(enum ovsdb_atomic_type); -bool ovsdb_atomic_type_from_string(const char *, enum ovsdb_atomic_type *); -struct ovsdb_error *ovsdb_atomic_type_from_json(enum ovsdb_atomic_type *, - const struct json *); -const char *ovsdb_atomic_type_to_string(enum ovsdb_atomic_type); -struct json *ovsdb_atomic_type_to_json(enum ovsdb_atomic_type); - -/* An atomic type plus optional constraints. */ - -enum ovsdb_ref_type { - OVSDB_REF_STRONG, /* Target must exist. */ - OVSDB_REF_WEAK /* Delete reference if target disappears. */ -}; - -struct ovsdb_integer_constraints { - int64_t min; /* minInteger or INT64_MIN. */ - int64_t max; /* maxInteger or INT64_MAX. */ -}; - -struct ovsdb_real_constraints { - double min; /* minReal or -DBL_MAX. */ - double max; /* minReal or DBL_MAX. */ -}; - -struct ovsdb_string_constraints { - unsigned int minLen; /* minLength or 0. */ - unsigned int maxLen; /* maxLength or UINT_MAX. */ -}; - -struct ovsdb_uuid_constraints { - char *refTableName; /* Name of referenced table, or NULL. */ - struct ovsdb_table *refTable; /* Referenced table, if available. */ - enum ovsdb_ref_type refType; /* Reference type. */ -}; - -struct ovsdb_base_type { - enum ovsdb_atomic_type type; - - /* If nonnull, a datum with keys of type 'type' that expresses all the - * valid values for this base_type. */ - struct ovsdb_datum *enum_; - - union { - struct ovsdb_integer_constraints integer; - struct ovsdb_real_constraints real; - /* No constraints for Boolean types. */ - struct ovsdb_string_constraints string; - struct ovsdb_uuid_constraints uuid; - }; -}; - -#define OVSDB_BASE_VOID_INIT { .type = OVSDB_TYPE_VOID } -#define OVSDB_BASE_INTEGER_INIT { .type = OVSDB_TYPE_INTEGER, \ - .integer = { INT64_MIN, INT64_MAX } } -#define OVSDB_BASE_REAL_INIT { .type = OVSDB_TYPE_REAL, \ - .real = { -DBL_MAX, DBL_MAX } } -#define OVSDB_BASE_BOOLEAN_INIT { .type = OVSDB_TYPE_BOOLEAN } -#define OVSDB_BASE_STRING_INIT { .type = OVSDB_TYPE_STRING, \ - .string = { 0, UINT_MAX } } -#define OVSDB_BASE_UUID_INIT { .type = OVSDB_TYPE_UUID, \ - .uuid = { NULL, NULL, 0 } } - -void ovsdb_base_type_init(struct ovsdb_base_type *, enum ovsdb_atomic_type); -void ovsdb_base_type_clone(struct ovsdb_base_type *, - const struct ovsdb_base_type *); -void ovsdb_base_type_destroy(struct ovsdb_base_type *); - -bool ovsdb_base_type_is_valid(const struct ovsdb_base_type *); -bool ovsdb_base_type_has_constraints(const struct ovsdb_base_type *); -void ovsdb_base_type_clear_constraints(struct ovsdb_base_type *); -const struct ovsdb_type *ovsdb_base_type_get_enum_type(enum ovsdb_atomic_type); - -struct ovsdb_error *ovsdb_base_type_from_json(struct ovsdb_base_type *, - const struct json *) - OVS_WARN_UNUSED_RESULT; -struct json *ovsdb_base_type_to_json(const struct ovsdb_base_type *); - -static inline bool ovsdb_base_type_is_ref(const struct ovsdb_base_type *); -static inline bool ovsdb_base_type_is_strong_ref( - const struct ovsdb_base_type *); -static inline bool ovsdb_base_type_is_weak_ref(const struct ovsdb_base_type *); - -/* An OVSDB type. - * - * Several rules constrain the valid types. See ovsdb_type_is_valid() (in - * ovsdb-types.c) for details. - * - * If 'value_type' is OVSDB_TYPE_VOID, 'n_min' is 1, and 'n_max' is 1, then the - * type is a single atomic 'key_type'. - * - * If 'value_type' is OVSDB_TYPE_VOID and 'n_min' or 'n_max' (or both) has a - * value other than 1, then the type is a set of 'key_type'. If 'n_min' is 0 - * and 'n_max' is 1, then the type can also be considered an optional - * 'key_type'. - * - * If 'value_type' is not OVSDB_TYPE_VOID, then the type is a map from - * 'key_type' to 'value_type'. If 'n_min' is 0 and 'n_max' is 1, then the type - * can also be considered an optional pair of 'key_type' and 'value_type'. - */ -struct ovsdb_type { - struct ovsdb_base_type key; - struct ovsdb_base_type value; - unsigned int n_min; - unsigned int n_max; /* UINT_MAX stands in for "unlimited". */ -}; - -#define OVSDB_TYPE_SCALAR_INITIALIZER(KEY) { KEY, OVSDB_BASE_VOID_INIT, 1, 1 } - -extern const struct ovsdb_type ovsdb_type_integer; -extern const struct ovsdb_type ovsdb_type_real; -extern const struct ovsdb_type ovsdb_type_boolean; -extern const struct ovsdb_type ovsdb_type_string; -extern const struct ovsdb_type ovsdb_type_uuid; - -void ovsdb_type_clone(struct ovsdb_type *, const struct ovsdb_type *); -void ovsdb_type_destroy(struct ovsdb_type *); - -bool ovsdb_type_is_valid(const struct ovsdb_type *); - -static inline bool ovsdb_type_is_scalar(const struct ovsdb_type *); -static inline bool ovsdb_type_is_optional(const struct ovsdb_type *); -static inline bool ovsdb_type_is_optional_scalar( - const struct ovsdb_type *); -static inline bool ovsdb_type_is_composite(const struct ovsdb_type *); -static inline bool ovsdb_type_is_set(const struct ovsdb_type *); -static inline bool ovsdb_type_is_map(const struct ovsdb_type *); - -char *ovsdb_type_to_english(const struct ovsdb_type *); - -struct ovsdb_error *ovsdb_type_from_json(struct ovsdb_type *, - const struct json *) - OVS_WARN_UNUSED_RESULT; -struct json *ovsdb_type_to_json(const struct ovsdb_type *); - -/* Inline function implementations. */ - -static inline bool -ovsdb_atomic_type_is_valid(enum ovsdb_atomic_type atomic_type) -{ - return (int) atomic_type >= 0 && atomic_type < OVSDB_N_TYPES; -} - -static inline bool -ovsdb_base_type_is_ref(const struct ovsdb_base_type *base) -{ - return base->type == OVSDB_TYPE_UUID && base->uuid.refTableName; -} - -static inline bool -ovsdb_base_type_is_strong_ref(const struct ovsdb_base_type *base) -{ - return (ovsdb_base_type_is_ref(base) - && base->uuid.refType == OVSDB_REF_STRONG); -} - -static inline bool -ovsdb_base_type_is_weak_ref(const struct ovsdb_base_type *base) -{ - return (ovsdb_base_type_is_ref(base) - && base->uuid.refType == OVSDB_REF_WEAK); -} - -static inline bool ovsdb_type_is_scalar(const struct ovsdb_type *type) -{ - return (type->value.type == OVSDB_TYPE_VOID - && type->n_min == 1 && type->n_max == 1); -} - -static inline bool ovsdb_type_is_optional(const struct ovsdb_type *type) -{ - return type->n_min == 0; -} - -static inline bool ovsdb_type_is_optional_scalar( - const struct ovsdb_type *type) -{ - return (type->value.type == OVSDB_TYPE_VOID - && type->n_min == 0 && type->n_max == 1); -} - -static inline bool ovsdb_type_is_composite(const struct ovsdb_type *type) -{ - return type->n_max > 1; -} - -static inline bool ovsdb_type_is_set(const struct ovsdb_type *type) -{ - return (type->value.type == OVSDB_TYPE_VOID - && (type->n_min != 1 || type->n_max != 1)); -} - -static inline bool ovsdb_type_is_map(const struct ovsdb_type *type) -{ - return type->value.type != OVSDB_TYPE_VOID; -} - -#ifdef __cplusplus -} -#endif - -#endif /* ovsdb-types.h */ Index: openvswitch-2.17.2/include/openvswitch/ovsdb-types.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/openvswitch/ovsdb-types.h @@ -0,0 +1,242 @@ +/* Copyright (c) 2009, 2010, 2011 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef OVSDB_TYPES_H +#define OVSDB_TYPES_H 1 + +#include +#include +#include +#include "openvswitch/compiler.h" +#include "internal/uuid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct json; + +/* An atomic type: one that OVSDB regards as a single unit of data. */ +enum ovsdb_atomic_type { + OVSDB_TYPE_VOID, /* No value. */ + OVSDB_TYPE_INTEGER, /* Signed 64-bit integer. */ + OVSDB_TYPE_REAL, /* IEEE 754 double-precision floating point. */ + OVSDB_TYPE_BOOLEAN, /* True or false. */ + OVSDB_TYPE_STRING, /* UTF-8 string. */ + OVSDB_TYPE_UUID, /* RFC 4122 UUID referencing a table row. */ + OVSDB_N_TYPES +}; + +static inline bool ovsdb_atomic_type_is_valid(enum ovsdb_atomic_type); +bool ovsdb_atomic_type_from_string(const char *, enum ovsdb_atomic_type *); +struct ovsdb_error *ovsdb_atomic_type_from_json(enum ovsdb_atomic_type *, + const struct json *); +const char *ovsdb_atomic_type_to_string(enum ovsdb_atomic_type); +struct json *ovsdb_atomic_type_to_json(enum ovsdb_atomic_type); + +/* An atomic type plus optional constraints. */ + +enum ovsdb_ref_type { + OVSDB_REF_STRONG, /* Target must exist. */ + OVSDB_REF_WEAK /* Delete reference if target disappears. */ +}; + +struct ovsdb_integer_constraints { + int64_t min; /* minInteger or INT64_MIN. */ + int64_t max; /* maxInteger or INT64_MAX. */ +}; + +struct ovsdb_real_constraints { + double min; /* minReal or -DBL_MAX. */ + double max; /* minReal or DBL_MAX. */ +}; + +struct ovsdb_string_constraints { + unsigned int minLen; /* minLength or 0. */ + unsigned int maxLen; /* maxLength or UINT_MAX. */ +}; + +struct ovsdb_uuid_constraints { + char *refTableName; /* Name of referenced table, or NULL. */ + struct ovsdb_table *refTable; /* Referenced table, if available. */ + enum ovsdb_ref_type refType; /* Reference type. */ +}; + +struct ovsdb_base_type { + enum ovsdb_atomic_type type; + + /* If nonnull, a datum with keys of type 'type' that expresses all the + * valid values for this base_type. */ + struct ovsdb_datum *enum_; + + union { + struct ovsdb_integer_constraints integer; + struct ovsdb_real_constraints real; + /* No constraints for Boolean types. */ + struct ovsdb_string_constraints string; + struct ovsdb_uuid_constraints uuid; + }; +}; + +#define OVSDB_BASE_VOID_INIT { .type = OVSDB_TYPE_VOID } +#define OVSDB_BASE_INTEGER_INIT { .type = OVSDB_TYPE_INTEGER, \ + .integer = { INT64_MIN, INT64_MAX } } +#define OVSDB_BASE_REAL_INIT { .type = OVSDB_TYPE_REAL, \ + .real = { -DBL_MAX, DBL_MAX } } +#define OVSDB_BASE_BOOLEAN_INIT { .type = OVSDB_TYPE_BOOLEAN } +#define OVSDB_BASE_STRING_INIT { .type = OVSDB_TYPE_STRING, \ + .string = { 0, UINT_MAX } } +#define OVSDB_BASE_UUID_INIT { .type = OVSDB_TYPE_UUID, \ + .uuid = { NULL, NULL, 0 } } + +void ovsdb_base_type_init(struct ovsdb_base_type *, enum ovsdb_atomic_type); +void ovsdb_base_type_clone(struct ovsdb_base_type *, + const struct ovsdb_base_type *); +void ovsdb_base_type_destroy(struct ovsdb_base_type *); + +bool ovsdb_base_type_is_valid(const struct ovsdb_base_type *); +bool ovsdb_base_type_has_constraints(const struct ovsdb_base_type *); +void ovsdb_base_type_clear_constraints(struct ovsdb_base_type *); +const struct ovsdb_type *ovsdb_base_type_get_enum_type(enum ovsdb_atomic_type); + +struct ovsdb_error *ovsdb_base_type_from_json(struct ovsdb_base_type *, + const struct json *) + OVS_WARN_UNUSED_RESULT; +struct json *ovsdb_base_type_to_json(const struct ovsdb_base_type *); + +static inline bool ovsdb_base_type_is_ref(const struct ovsdb_base_type *); +static inline bool ovsdb_base_type_is_strong_ref( + const struct ovsdb_base_type *); +static inline bool ovsdb_base_type_is_weak_ref(const struct ovsdb_base_type *); + +/* An OVSDB type. + * + * Several rules constrain the valid types. See ovsdb_type_is_valid() (in + * ovsdb-types.c) for details. + * + * If 'value_type' is OVSDB_TYPE_VOID, 'n_min' is 1, and 'n_max' is 1, then the + * type is a single atomic 'key_type'. + * + * If 'value_type' is OVSDB_TYPE_VOID and 'n_min' or 'n_max' (or both) has a + * value other than 1, then the type is a set of 'key_type'. If 'n_min' is 0 + * and 'n_max' is 1, then the type can also be considered an optional + * 'key_type'. + * + * If 'value_type' is not OVSDB_TYPE_VOID, then the type is a map from + * 'key_type' to 'value_type'. If 'n_min' is 0 and 'n_max' is 1, then the type + * can also be considered an optional pair of 'key_type' and 'value_type'. + */ +struct ovsdb_type { + struct ovsdb_base_type key; + struct ovsdb_base_type value; + unsigned int n_min; + unsigned int n_max; /* UINT_MAX stands in for "unlimited". */ +}; + +#define OVSDB_TYPE_SCALAR_INITIALIZER(KEY) { KEY, OVSDB_BASE_VOID_INIT, 1, 1 } + +extern const struct ovsdb_type ovsdb_type_integer; +extern const struct ovsdb_type ovsdb_type_real; +extern const struct ovsdb_type ovsdb_type_boolean; +extern const struct ovsdb_type ovsdb_type_string; +extern const struct ovsdb_type ovsdb_type_uuid; + +void ovsdb_type_clone(struct ovsdb_type *, const struct ovsdb_type *); +void ovsdb_type_destroy(struct ovsdb_type *); + +bool ovsdb_type_is_valid(const struct ovsdb_type *); + +static inline bool ovsdb_type_is_scalar(const struct ovsdb_type *); +static inline bool ovsdb_type_is_optional(const struct ovsdb_type *); +static inline bool ovsdb_type_is_optional_scalar( + const struct ovsdb_type *); +static inline bool ovsdb_type_is_composite(const struct ovsdb_type *); +static inline bool ovsdb_type_is_set(const struct ovsdb_type *); +static inline bool ovsdb_type_is_map(const struct ovsdb_type *); + +char *ovsdb_type_to_english(const struct ovsdb_type *); + +struct ovsdb_error *ovsdb_type_from_json(struct ovsdb_type *, + const struct json *) + OVS_WARN_UNUSED_RESULT; +struct json *ovsdb_type_to_json(const struct ovsdb_type *); + +/* Inline function implementations. */ + +static inline bool +ovsdb_atomic_type_is_valid(enum ovsdb_atomic_type atomic_type) +{ + return (int) atomic_type >= 0 && atomic_type < OVSDB_N_TYPES; +} + +static inline bool +ovsdb_base_type_is_ref(const struct ovsdb_base_type *base) +{ + return base->type == OVSDB_TYPE_UUID && base->uuid.refTableName; +} + +static inline bool +ovsdb_base_type_is_strong_ref(const struct ovsdb_base_type *base) +{ + return (ovsdb_base_type_is_ref(base) + && base->uuid.refType == OVSDB_REF_STRONG); +} + +static inline bool +ovsdb_base_type_is_weak_ref(const struct ovsdb_base_type *base) +{ + return (ovsdb_base_type_is_ref(base) + && base->uuid.refType == OVSDB_REF_WEAK); +} + +static inline bool ovsdb_type_is_scalar(const struct ovsdb_type *type) +{ + return (type->value.type == OVSDB_TYPE_VOID + && type->n_min == 1 && type->n_max == 1); +} + +static inline bool ovsdb_type_is_optional(const struct ovsdb_type *type) +{ + return type->n_min == 0; +} + +static inline bool ovsdb_type_is_optional_scalar( + const struct ovsdb_type *type) +{ + return (type->value.type == OVSDB_TYPE_VOID + && type->n_min == 0 && type->n_max == 1); +} + +static inline bool ovsdb_type_is_composite(const struct ovsdb_type *type) +{ + return type->n_max > 1; +} + +static inline bool ovsdb_type_is_set(const struct ovsdb_type *type) +{ + return (type->value.type == OVSDB_TYPE_VOID + && (type->n_min != 1 || type->n_max != 1)); +} + +static inline bool ovsdb_type_is_map(const struct ovsdb_type *type) +{ + return type->value.type != OVSDB_TYPE_VOID; +} + +#ifdef __cplusplus +} +#endif + +#endif /* ovsdb-types.h */ Index: openvswitch-2.17.2/include/sparse/automake.mk =================================================================== --- openvswitch-2.17.2.orig/include/sparse/automake.mk +++ openvswitch-2.17.2/include/sparse/automake.mk @@ -1,4 +1,4 @@ -noinst_HEADERS += \ +sparse_headers = \ include/sparse/rte_byteorder.h \ include/sparse/xmmintrin.h \ include/sparse/arpa/inet.h \ @@ -21,3 +21,11 @@ noinst_HEADERS += \ include/sparse/threads.h \ include/sparse/linux/if_packet.h \ include/sparse/linux/tc_act/tc_pedit.h + +# Only install headers if enabled +if ENABLE_SPARSE_BY_DEFAULT + ovssparseincludedir = $(openvswitchincludedir)/sparse + ovssparseinclude_HEADERS = $(sparse_headers) +else + noinst_HEADERS += $(sparse_headers) +endif Index: openvswitch-2.17.2/include/windows/netinet/icmp6.h =================================================================== --- openvswitch-2.17.2.orig/include/windows/netinet/icmp6.h +++ openvswitch-2.17.2/include/windows/netinet/icmp6.h @@ -61,7 +61,7 @@ #ifndef _NETINET_ICMP6_H_ #define _NETINET_ICMP6_H_ -#include "byte-order.h" +#include "internal/byte-order.h" #define ICMPV6_PLD_MAXLEN 1232 /* IPV6_MMTU - sizeof(struct ip6_hdr) - sizeof(struct icmp6_hdr) */ Index: openvswitch-2.17.2/include/windows/netinet/ip6.h =================================================================== --- openvswitch-2.17.2.orig/include/windows/netinet/ip6.h +++ openvswitch-2.17.2/include/windows/netinet/ip6.h @@ -62,7 +62,7 @@ #define _NETINET_IP6_H_ #include #include -#include "byte-order.h" +#include "internal/byte-order.h" /* * Definition for internet protocol version 6. Index: openvswitch-2.17.2/lib/aes128.c =================================================================== --- openvswitch-2.17.2.orig/lib/aes128.c +++ openvswitch-2.17.2/lib/aes128.c @@ -26,7 +26,7 @@ #include "aes128.h" -#include "util.h" +#include "internal/util.h" static const uint32_t Te0[256] = { 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, Index: openvswitch-2.17.2/lib/async-append-aio.c =================================================================== --- openvswitch-2.17.2.orig/lib/async-append-aio.c +++ openvswitch-2.17.2/lib/async-append-aio.c @@ -26,8 +26,8 @@ #include #include "byteq.h" -#include "ovs-thread.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/util.h" /* Maximum number of bytes of buffered data. */ enum { BUFFER_SIZE = 65536 }; Index: openvswitch-2.17.2/lib/async-append-null.c =================================================================== --- openvswitch-2.17.2.orig/lib/async-append-null.c +++ openvswitch-2.17.2/lib/async-append-null.c @@ -23,7 +23,7 @@ #include #include -#include "util.h" +#include "internal/util.h" struct async_append * async_append_create(int fd OVS_UNUSED) Index: openvswitch-2.17.2/lib/automake.mk =================================================================== --- openvswitch-2.17.2.orig/lib/automake.mk +++ openvswitch-2.17.2/lib/automake.mk @@ -237,31 +237,15 @@ lib_libopenvswitch_la_SOURCES = \ lib/ofp-version-opt.h \ lib/ofp-version-opt.c \ lib/ofpbuf.c \ - lib/ovs-atomic-c++.h \ - lib/ovs-atomic-c11.h \ - lib/ovs-atomic-clang.h \ - lib/ovs-atomic-flag-gcc4.7+.h \ - lib/ovs-atomic-gcc4+.h \ - lib/ovs-atomic-gcc4.7+.h \ - lib/ovs-atomic-i586.h \ - lib/ovs-atomic-locked.c \ - lib/ovs-atomic-locked.h \ - lib/ovs-atomic-msvc.h \ - lib/ovs-atomic-pthreads.h \ - lib/ovs-atomic-x86_64.h \ - lib/ovs-atomic.h \ lib/ovs-lldp.c \ lib/ovs-lldp.h \ lib/ovs-numa.c \ - lib/ovs-numa.h \ lib/ovs-rcu.c \ - lib/ovs-rcu.h \ lib/ovs-replay.c \ lib/ovs-replay.h \ lib/ovs-router.h \ lib/ovs-router.c \ lib/ovs-thread.c \ - lib/ovs-thread.h \ lib/ovsdb-cs.c \ lib/ovsdb-cs.h \ lib/ovsdb-data.c \ Index: openvswitch-2.17.2/lib/backtrace.c =================================================================== --- openvswitch-2.17.2.orig/lib/backtrace.c +++ openvswitch-2.17.2/lib/backtrace.c @@ -23,7 +23,7 @@ #include "backtrace.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(backtrace); Index: openvswitch-2.17.2/lib/bfd.c =================================================================== --- openvswitch-2.17.2.orig/lib/bfd.c +++ openvswitch-2.17.2/lib/bfd.c @@ -22,30 +22,30 @@ #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "connectivity.h" -#include "csum.h" -#include "dp-packet.h" +#include "internal/csum.h" +#include "internal/dp-packet.h" #include "dpif.h" #include "openvswitch/dynamic-string.h" -#include "flow.h" -#include "hash.h" +#include "internal/flow.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" -#include "netdev.h" +#include "internal/netdev.h" #include "odp-util.h" #include "openvswitch/ofpbuf.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/types.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "random.h" -#include "seq.h" -#include "smap.h" -#include "timeval.h" -#include "unaligned.h" -#include "unixctl.h" -#include "util.h" +#include "internal/random.h" +#include "internal/seq.h" +#include "internal/smap.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(bfd); Index: openvswitch-2.17.2/lib/bfd.h =================================================================== --- openvswitch-2.17.2.orig/lib/bfd.h +++ openvswitch-2.17.2/lib/bfd.h @@ -21,7 +21,7 @@ #include #include -#include "packets.h" +#include "internal/packets.h" struct bfd; struct dpif_flow_stats; Index: openvswitch-2.17.2/lib/bundle.c =================================================================== --- openvswitch-2.17.2.orig/lib/bundle.c +++ openvswitch-2.17.2/lib/bundle.c @@ -15,16 +15,16 @@ #include -#include "bundle.h" +#include "internal/bundle.h" #include #include #include #include -#include "colors.h" +#include "internal/colors.h" #include "multipath.h" -#include "nx-match.h" +#include "internal/nx-match.h" #include "openflow/nicira-ext.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/meta-flow.h" @@ -33,7 +33,7 @@ #include "openvswitch/ofp-port.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(bundle); Index: openvswitch-2.17.2/lib/byteq.c =================================================================== --- openvswitch-2.17.2.orig/lib/byteq.c +++ openvswitch-2.17.2/lib/byteq.c @@ -18,7 +18,7 @@ #include #include #include -#include "util.h" +#include "internal/util.h" /* Initializes 'q' as an empty byteq that uses the 'size' bytes of 'buffer' to * store data. 'size' must be a power of 2. Index: openvswitch-2.17.2/lib/ccmap.c =================================================================== --- openvswitch-2.17.2.orig/lib/ccmap.c +++ openvswitch-2.17.2/lib/ccmap.c @@ -16,12 +16,12 @@ #include #include "ccmap.h" -#include "coverage.h" -#include "bitmap.h" -#include "hash.h" -#include "ovs-rcu.h" -#include "random.h" -#include "util.h" +#include "internal/coverage.h" +#include "internal/bitmap.h" +#include "internal/hash.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/random.h" +#include "internal/util.h" COVERAGE_DEFINE(ccmap_expand); COVERAGE_DEFINE(ccmap_shrink); Index: openvswitch-2.17.2/lib/ccmap.h =================================================================== --- openvswitch-2.17.2.orig/lib/ccmap.h +++ openvswitch-2.17.2/lib/ccmap.h @@ -19,8 +19,8 @@ #include #include -#include "ovs-rcu.h" -#include "util.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/util.h" /* Concurrent hash map for numerical counts of given hash values. * ============================================================== Index: openvswitch-2.17.2/lib/cfm.c =================================================================== --- openvswitch-2.17.2.orig/lib/cfm.c +++ openvswitch-2.17.2/lib/cfm.c @@ -21,24 +21,24 @@ #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "connectivity.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/dynamic-string.h" -#include "flow.h" -#include "hash.h" +#include "internal/flow.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "netdev.h" -#include "ovs-atomic.h" -#include "packets.h" +#include "internal/netdev.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "random.h" -#include "seq.h" -#include "timer.h" -#include "timeval.h" -#include "unixctl.h" +#include "internal/random.h" +#include "internal/seq.h" +#include "internal/timer.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(cfm); Index: openvswitch-2.17.2/lib/cfm.h =================================================================== --- openvswitch-2.17.2.orig/lib/cfm.h +++ openvswitch-2.17.2/lib/cfm.h @@ -20,7 +20,7 @@ #include "openvswitch/hmap.h" #include "openvswitch/types.h" -#include "packets.h" +#include "internal/packets.h" struct flow; struct dp_packet; Index: openvswitch-2.17.2/lib/classifier-private.h =================================================================== --- openvswitch-2.17.2.orig/lib/classifier-private.h +++ openvswitch-2.17.2/lib/classifier-private.h @@ -18,10 +18,10 @@ #define CLASSIFIER_PRIVATE_H 1 #include "ccmap.h" -#include "cmap.h" -#include "flow.h" -#include "hash.h" -#include "rculist.h" +#include "internal/cmap.h" +#include "internal/flow.h" +#include "internal/hash.h" +#include "internal/rculist.h" /* Classifier internal definitions, subject to change at any time. */ Index: openvswitch-2.17.2/lib/classifier.c =================================================================== --- openvswitch-2.17.2.orig/lib/classifier.c +++ openvswitch-2.17.2/lib/classifier.c @@ -15,16 +15,16 @@ */ #include -#include "classifier.h" +#include "internal/classifier.h" #include "classifier-private.h" #include #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/dynamic-string.h" #include "odp-util.h" -#include "packets.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/util.h" struct trie_ctx; Index: openvswitch-2.17.2/lib/cmap.c =================================================================== --- openvswitch-2.17.2.orig/lib/cmap.c +++ openvswitch-2.17.2/lib/cmap.c @@ -15,13 +15,13 @@ */ #include -#include "cmap.h" -#include "coverage.h" -#include "bitmap.h" -#include "hash.h" -#include "ovs-rcu.h" -#include "random.h" -#include "util.h" +#include "internal/cmap.h" +#include "internal/coverage.h" +#include "internal/bitmap.h" +#include "internal/hash.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/random.h" +#include "internal/util.h" COVERAGE_DEFINE(cmap_expand); COVERAGE_DEFINE(cmap_shrink); Index: openvswitch-2.17.2/lib/colors.c =================================================================== --- openvswitch-2.17.2.orig/lib/colors.c +++ openvswitch-2.17.2/lib/colors.c @@ -18,12 +18,12 @@ #include -#include "colors.h" +#include "internal/colors.h" #include #include -#include "util.h" +#include "internal/util.h" struct color_key { const char *name; Index: openvswitch-2.17.2/lib/command-line.c =================================================================== --- openvswitch-2.17.2.orig/lib/command-line.c +++ openvswitch-2.17.2/lib/command-line.c @@ -15,14 +15,14 @@ */ #include -#include "command-line.h" +#include "internal/command-line.h" #include #include #include -#include "svec.h" +#include "internal/svec.h" #include "openvswitch/dynamic-string.h" -#include "ovs-thread.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(command_line); Index: openvswitch-2.17.2/lib/connectivity.c =================================================================== --- openvswitch-2.17.2.orig/lib/connectivity.c +++ openvswitch-2.17.2/lib/connectivity.c @@ -16,8 +16,8 @@ #include #include "connectivity.h" -#include "ovs-thread.h" -#include "seq.h" +#include "openvswitch/ovs-thread.h" +#include "internal/seq.h" static struct seq *connectivity_seq; Index: openvswitch-2.17.2/lib/conntrack-icmp.c =================================================================== --- openvswitch-2.17.2.orig/lib/conntrack-icmp.c +++ openvswitch-2.17.2/lib/conntrack-icmp.c @@ -23,7 +23,7 @@ #include "conntrack-private.h" #include "conntrack-tp.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" enum OVS_PACKED_ENUM icmp_state { ICMPS_FIRST, Index: openvswitch-2.17.2/lib/conntrack-other.c =================================================================== --- openvswitch-2.17.2.orig/lib/conntrack-other.c +++ openvswitch-2.17.2/lib/conntrack-other.c @@ -18,7 +18,7 @@ #include "conntrack-private.h" #include "conntrack-tp.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" enum OVS_PACKED_ENUM other_state { OTHERS_FIRST, Index: openvswitch-2.17.2/lib/conntrack-private.h =================================================================== --- openvswitch-2.17.2.orig/lib/conntrack-private.h +++ openvswitch-2.17.2/lib/conntrack-private.h @@ -21,16 +21,16 @@ #include #include -#include "cmap.h" +#include "internal/cmap.h" #include "conntrack.h" #include "ct-dpif.h" #include "ipf.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" #include "openvswitch/types.h" -#include "packets.h" -#include "unaligned.h" -#include "dp-packet.h" +#include "internal/packets.h" +#include "internal/unaligned.h" +#include "internal/dp-packet.h" struct ct_endpoint { union ct_addr addr; Index: openvswitch-2.17.2/lib/conntrack-tcp.c =================================================================== --- openvswitch-2.17.2.orig/lib/conntrack-tcp.c +++ openvswitch-2.17.2/lib/conntrack-tcp.c @@ -40,10 +40,10 @@ #include "conntrack-private.h" #include "conntrack-tp.h" -#include "coverage.h" +#include "internal/coverage.h" #include "ct-dpif.h" -#include "dp-packet.h" -#include "util.h" +#include "internal/dp-packet.h" +#include "internal/util.h" COVERAGE_DEFINE(conntrack_tcp_seq_chk_bypass); COVERAGE_DEFINE(conntrack_tcp_seq_chk_failed); Index: openvswitch-2.17.2/lib/conntrack.c =================================================================== --- openvswitch-2.17.2.orig/lib/conntrack.c +++ openvswitch-2.17.2/lib/conntrack.c @@ -22,24 +22,24 @@ #include #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "conntrack.h" #include "conntrack-private.h" #include "conntrack-tp.h" -#include "coverage.h" -#include "csum.h" +#include "internal/coverage.h" +#include "internal/csum.h" #include "ct-dpif.h" -#include "dp-packet.h" -#include "flow.h" -#include "netdev.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" +#include "internal/netdev.h" #include "odp-netlink.h" #include "openvswitch/hmap.h" #include "openvswitch/vlog.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" -#include "random.h" -#include "timeval.h" +#include "internal/random.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(conntrack); Index: openvswitch-2.17.2/lib/conntrack.h =================================================================== --- openvswitch-2.17.2.orig/lib/conntrack.h +++ openvswitch-2.17.2/lib/conntrack.h @@ -19,18 +19,18 @@ #include -#include "cmap.h" +#include "internal/cmap.h" #include "ct-dpif.h" -#include "latch.h" +#include "internal/latch.h" #include "odp-netlink.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" #include "openvswitch/thread.h" #include "openvswitch/types.h" -#include "ovs-atomic.h" -#include "ovs-thread.h" -#include "packets.h" -#include "hindex.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/hindex.h" /* Userspace connection tracker * ============================ Index: openvswitch-2.17.2/lib/coverage.c =================================================================== --- openvswitch-2.17.2.orig/lib/coverage.c +++ openvswitch-2.17.2/lib/coverage.c @@ -15,15 +15,15 @@ */ #include -#include "coverage.h" +#include "internal/coverage.h" #include #include #include "openvswitch/dynamic-string.h" -#include "hash.h" -#include "svec.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/hash.h" +#include "internal/svec.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(coverage); Index: openvswitch-2.17.2/lib/crc32c.c =================================================================== --- openvswitch-2.17.2.orig/lib/crc32c.c +++ openvswitch-2.17.2/lib/crc32c.c @@ -43,8 +43,8 @@ */ #include -#include "crc32c.h" -#include "byte-order.h" +#include "internal/crc32c.h" +#include "internal/byte-order.h" /*****************************************************************/ /* */ Index: openvswitch-2.17.2/lib/csum.c =================================================================== --- openvswitch-2.17.2.orig/lib/csum.c +++ openvswitch-2.17.2/lib/csum.c @@ -15,8 +15,8 @@ */ #include -#include "csum.h" -#include "unaligned.h" +#include "internal/csum.h" +#include "internal/unaligned.h" #include #include Index: openvswitch-2.17.2/lib/ct-dpif.h =================================================================== --- openvswitch-2.17.2.orig/lib/ct-dpif.h +++ openvswitch-2.17.2/lib/ct-dpif.h @@ -18,7 +18,7 @@ #define CT_DPIF_H #include "openvswitch/types.h" -#include "packets.h" +#include "internal/packets.h" union ct_dpif_inet_addr { ovs_be32 ip; Index: openvswitch-2.17.2/lib/daemon-unix.c =================================================================== --- openvswitch-2.17.2.orig/lib/daemon-unix.c +++ openvswitch-2.17.2/lib/daemon-unix.c @@ -16,7 +16,7 @@ #include #include "backtrace.h" -#include "daemon.h" +#include "internal/daemon.h" #include "daemon-private.h" #include #include @@ -32,15 +32,15 @@ #if HAVE_LIBCAPNG #include #endif -#include "command-line.h" -#include "fatal-signal.h" -#include "dirs.h" +#include "internal/command-line.h" +#include "internal/fatal-signal.h" +#include "internal/dirs.h" #include "lockfile.h" -#include "ovs-thread.h" -#include "process.h" -#include "socket-util.h" -#include "timeval.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/process.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(daemon_unix); Index: openvswitch-2.17.2/lib/daemon-windows.c =================================================================== --- openvswitch-2.17.2.orig/lib/daemon-windows.c +++ openvswitch-2.17.2/lib/daemon-windows.c @@ -15,15 +15,15 @@ */ #include -#include "daemon.h" +#include "internal/daemon.h" #include "daemon-private.h" #include #include #include #include -#include "dirs.h" -#include "fatal-signal.h" -#include "ovs-thread.h" +#include "internal/dirs.h" +#include "internal/fatal-signal.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/daemon.c =================================================================== --- openvswitch-2.17.2.orig/lib/daemon.c +++ openvswitch-2.17.2/lib/daemon.c @@ -14,13 +14,13 @@ * limitations under the License. */ #include -#include "daemon.h" +#include "internal/daemon.h" #include "daemon-private.h" #include #include #include -#include "util.h" -#include "ovs-thread.h" +#include "internal/util.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(daemon); Index: openvswitch-2.17.2/lib/db-ctl-base.c =================================================================== --- openvswitch-2.17.2.orig/lib/db-ctl-base.c +++ openvswitch-2.17.2/lib/db-ctl-base.c @@ -20,24 +20,25 @@ #include #include -#include "db-ctl-base.h" +#include "internal/db-ctl-base.h" +#include "internal/command-line.h" #include "openvswitch/compiler.h" -#include "dirs.h" +#include "internal/dirs.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/json.h" #include "openvswitch/vlog.h" -#include "ovsdb-data.h" -#include "ovsdb-idl.h" -#include "ovsdb-idl-provider.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-idl.h" +#include "openvswitch/ovsdb-idl-provider.h" #include "openvswitch/shash.h" -#include "sset.h" -#include "svec.h" +#include "internal/sset.h" +#include "internal/svec.h" #include "string.h" -#include "table.h" -#include "util.h" +#include "internal/table.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(db_ctl_base); Index: openvswitch-2.17.2/lib/dhparams.c =================================================================== --- openvswitch-2.17.2.orig/lib/dhparams.c +++ openvswitch-2.17.2/lib/dhparams.c @@ -3,7 +3,7 @@ * If you do need to regenerate this file, run "make generate-dhparams-c". */ #include -#include "lib/dhparams.h" +#include "internal/dhparams.h" #include "openvswitch/util.h" static int Index: openvswitch-2.17.2/lib/dirs.c.in =================================================================== --- openvswitch-2.17.2.orig/lib/dirs.c.in +++ openvswitch-2.17.2/lib/dirs.c.in @@ -16,10 +16,10 @@ */ #include -#include "dirs.h" +#include "internal/dirs.h" #include -#include "ovs-thread.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/util.h" struct directory { const char *value; /* Actual value; NULL if not yet determined. */ Index: openvswitch-2.17.2/lib/dns-resolve.c =================================================================== --- openvswitch-2.17.2.orig/lib/dns-resolve.c +++ openvswitch-2.17.2/lib/dns-resolve.c @@ -24,10 +24,10 @@ #include #include #include -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "openvswitch/vlog.h" -#include "timeval.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(dns_resolve); Index: openvswitch-2.17.2/lib/dp-packet.c =================================================================== --- openvswitch-2.17.2.orig/lib/dp-packet.c +++ openvswitch-2.17.2/lib/dp-packet.c @@ -18,11 +18,11 @@ #include #include -#include "dp-packet.h" -#include "netdev-afxdp.h" -#include "netdev-dpdk.h" +#include "internal/dp-packet.h" +#include "internal/netdev-afxdp.h" +#include "internal/netdev-dpdk.h" #include "openvswitch/dynamic-string.h" -#include "util.h" +#include "internal/util.h" static void dp_packet_init__(struct dp_packet *b, size_t allocated, enum dp_packet_source source) Index: openvswitch-2.17.2/lib/dpctl.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpctl.c +++ openvswitch-2.17.2/lib/dpctl.c @@ -27,27 +27,28 @@ #include #include +#include "internal/command-line.h" #include "openvswitch/compiler.h" #include "ct-dpif.h" -#include "dirs.h" +#include "internal/dirs.h" #include "dpctl.h" #include "dpif.h" #include "dpif-provider.h" #include "openvswitch/dynamic-string.h" -#include "flow.h" +#include "internal/flow.h" #include "openvswitch/match.h" -#include "netdev.h" -#include "netlink.h" +#include "internal/netdev.h" +#include "internal/netlink.h" #include "odp-util.h" #include "openvswitch/ofpbuf.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/shash.h" -#include "simap.h" -#include "smap.h" -#include "sset.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/simap.h" +#include "internal/smap.h" +#include "internal/sset.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/ofp-flow.h" #include "openvswitch/ofp-port.h" Index: openvswitch-2.17.2/lib/dpdk-stub.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpdk-stub.c +++ openvswitch-2.17.2/lib/dpdk-stub.c @@ -18,8 +18,8 @@ #include #include "dpdk.h" -#include "smap.h" -#include "ovs-thread.h" +#include "internal/smap.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/vlog.h" #include "vswitch-idl.h" Index: openvswitch-2.17.2/lib/dpdk.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpdk.c +++ openvswitch-2.17.2/lib/dpdk.c @@ -29,18 +29,18 @@ #include #include -#include "dirs.h" -#include "fatal-signal.h" -#include "netdev-dpdk.h" +#include "internal/dirs.h" +#include "internal/fatal-signal.h" +#include "internal/netdev-dpdk.h" #include "netdev-offload-provider.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" -#include "ovs-atomic.h" -#include "ovs-numa.h" -#include "smap.h" -#include "svec.h" -#include "unixctl.h" -#include "util.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-numa.h" +#include "internal/smap.h" +#include "internal/svec.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "vswitch-idl.h" VLOG_DEFINE_THIS_MODULE(dpdk); Index: openvswitch-2.17.2/lib/dpif-netdev-avx512.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-avx512.c +++ openvswitch-2.17.2/lib/dpif-netdev-avx512.c @@ -28,8 +28,8 @@ #include #include -#include "dp-packet.h" -#include "netdev.h" +#include "internal/dp-packet.h" +#include "internal/netdev.h" #include "netdev-offload.h" /* Each AVX512 register (zmm register in assembly notation) can contain up to Index: openvswitch-2.17.2/lib/dpif-netdev-extract-avx512.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-extract-avx512.c +++ openvswitch-2.17.2/lib/dpif-netdev-extract-avx512.c @@ -43,7 +43,7 @@ #include #include "cpu.h" -#include "flow.h" +#include "internal/flow.h" #include "dpif-netdev-private-dpcls.h" #include "dpif-netdev-private-extract.h" Index: openvswitch-2.17.2/lib/dpif-netdev-extract-study.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-extract-study.c +++ openvswitch-2.17.2/lib/dpif-netdev-extract-study.c @@ -21,7 +21,7 @@ #include "dpif-netdev-private-thread.h" #include "openvswitch/vlog.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" VLOG_DEFINE_THIS_MODULE(dpif_mfex_extract_study); Index: openvswitch-2.17.2/lib/dpif-netdev-lookup-avx512-gather.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-lookup-avx512-gather.c +++ openvswitch-2.17.2/lib/dpif-netdev-lookup-avx512-gather.c @@ -22,10 +22,10 @@ #include "dpif-netdev.h" #include "dpif-netdev-lookup.h" -#include "cmap.h" +#include "internal/cmap.h" #include "cpu.h" -#include "flow.h" -#include "pvector.h" +#include "internal/flow.h" +#include "internal/pvector.h" #include "openvswitch/vlog.h" #include "immintrin.h" Index: openvswitch-2.17.2/lib/dpif-netdev-lookup-generic.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-lookup-generic.c +++ openvswitch-2.17.2/lib/dpif-netdev-lookup-generic.c @@ -19,17 +19,17 @@ #include "dpif-netdev.h" #include "dpif-netdev-lookup.h" -#include "bitmap.h" -#include "cmap.h" +#include "internal/bitmap.h" +#include "internal/cmap.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "dpif.h" #include "dpif-netdev-perf.h" #include "dpif-provider.h" -#include "flow.h" -#include "ovs-thread.h" -#include "packets.h" -#include "pvector.h" +#include "internal/flow.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/pvector.h" VLOG_DEFINE_THIS_MODULE(dpif_lookup_generic); Index: openvswitch-2.17.2/lib/dpif-netdev-perf.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-perf.c +++ openvswitch-2.17.2/lib/dpif-netdev-perf.c @@ -21,9 +21,9 @@ #include "dpif-netdev-perf.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" -#include "ovs-numa.h" -#include "ovs-thread.h" -#include "timeval.h" +#include "openvswitch/ovs-numa.h" +#include "openvswitch/ovs-thread.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(pmd_perf); Index: openvswitch-2.17.2/lib/dpif-netdev-perf.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-perf.h +++ openvswitch-2.17.2/lib/dpif-netdev-perf.h @@ -30,10 +30,10 @@ #endif #include "openvswitch/vlog.h" -#include "ovs-atomic.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/dpif-netdev-private-dpcls.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-private-dpcls.h +++ openvswitch-2.17.2/lib/dpif-netdev-private-dpcls.h @@ -23,7 +23,7 @@ #include #include -#include "cmap.h" +#include "internal/cmap.h" #include "openvswitch/thread.h" #ifdef __cplusplus Index: openvswitch-2.17.2/lib/dpif-netdev-private-dpif.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-private-dpif.c +++ openvswitch-2.17.2/lib/dpif-netdev-private-dpif.c @@ -24,7 +24,7 @@ #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(dpif_netdev_impl); Index: openvswitch-2.17.2/lib/dpif-netdev-private-extract.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-private-extract.c +++ openvswitch-2.17.2/lib/dpif-netdev-private-extract.c @@ -19,14 +19,14 @@ #include #include -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "dpif-netdev-private-dpcls.h" #include "dpif-netdev-private-extract.h" #include "dpif-netdev-private-thread.h" -#include "flow.h" +#include "internal/flow.h" #include "openvswitch/vlog.h" -#include "ovs-thread.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(dpif_netdev_extract); Index: openvswitch-2.17.2/lib/dpif-netdev-private-flow.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-private-flow.h +++ openvswitch-2.17.2/lib/dpif-netdev-private-flow.h @@ -24,7 +24,7 @@ #include #include -#include "cmap.h" +#include "internal/cmap.h" #include "openvswitch/thread.h" #ifdef __cplusplus Index: openvswitch-2.17.2/lib/dpif-netdev-private-thread.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev-private-thread.h +++ openvswitch-2.17.2/lib/dpif-netdev-private-thread.h @@ -27,7 +27,7 @@ #include #include "ccmap.h" -#include "cmap.h" +#include "internal/cmap.h" #include "dpif-netdev-private-dfc.h" #include "dpif-netdev-private-dpif.h" Index: openvswitch-2.17.2/lib/dpif-netdev.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev.c +++ openvswitch-2.17.2/lib/dpif-netdev.c @@ -34,15 +34,15 @@ #include #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "ccmap.h" -#include "cmap.h" +#include "internal/cmap.h" #include "conntrack.h" #include "conntrack-tp.h" -#include "coverage.h" +#include "internal/coverage.h" #include "ct-dpif.h" -#include "csum.h" -#include "dp-packet.h" +#include "internal/csum.h" +#include "internal/dp-packet.h" #include "dpif.h" #include "dpif-netdev-lookup.h" #include "dpif-netdev-perf.h" @@ -50,18 +50,18 @@ #include "dpif-provider.h" #include "dummy.h" #include "fat-rwlock.h" -#include "flow.h" -#include "hmapx.h" +#include "internal/flow.h" +#include "internal/hmapx.h" #include "id-fpool.h" -#include "id-pool.h" +#include "internal/id-pool.h" #include "ipf.h" #include "mov-avg.h" #include "mpsc-queue.h" -#include "netdev.h" +#include "internal/netdev.h" #include "netdev-offload.h" #include "netdev-provider.h" #include "netdev-vport.h" -#include "netlink.h" +#include "internal/netlink.h" #include "odp-execute.h" #include "odp-util.h" #include "openvswitch/dynamic-string.h" @@ -72,21 +72,21 @@ #include "openvswitch/ofpbuf.h" #include "openvswitch/shash.h" #include "openvswitch/vlog.h" -#include "ovs-numa.h" -#include "ovs-rcu.h" -#include "packets.h" +#include "openvswitch/ovs-numa.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "pvector.h" -#include "random.h" -#include "seq.h" -#include "smap.h" -#include "sset.h" -#include "timeval.h" +#include "internal/pvector.h" +#include "internal/random.h" +#include "internal/seq.h" +#include "internal/smap.h" +#include "internal/sset.h" +#include "internal/timeval.h" #include "tnl-neigh-cache.h" #include "tnl-ports.h" -#include "unixctl.h" -#include "util.h" -#include "uuid.h" +#include "internal/unixctl.h" +#include "internal/util.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(dpif_netdev); Index: openvswitch-2.17.2/lib/dpif-netdev.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netdev.h +++ openvswitch-2.17.2/lib/dpif-netdev.h @@ -22,8 +22,8 @@ #include #include "dpif.h" #include "openvswitch/types.h" -#include "dp-packet.h" -#include "packets.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/dpif-netlink-rtnl.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netlink-rtnl.h +++ openvswitch-2.17.2/lib/dpif-netlink-rtnl.h @@ -19,7 +19,7 @@ #include -#include "netdev.h" +#include "internal/netdev.h" /* Declare these to keep sparse happy. */ int dpif_netlink_rtnl_port_create(struct netdev *netdev); Index: openvswitch-2.17.2/lib/dpif-netlink.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netlink.c +++ openvswitch-2.17.2/lib/dpif-netlink.c @@ -32,20 +32,20 @@ #include #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "dpif-netlink-rtnl.h" #include "dpif-provider.h" #include "fat-rwlock.h" -#include "flow.h" +#include "internal/flow.h" #include "netdev-linux.h" #include "netdev-offload.h" #include "netdev-provider.h" #include "netdev-vport.h" -#include "netdev.h" +#include "internal/netdev.h" #include "netlink-conntrack.h" #include "netlink-notifier.h" #include "netlink-socket.h" -#include "netlink.h" +#include "internal/netlink.h" #include "netnsid.h" #include "odp-util.h" #include "openvswitch/dynamic-string.h" @@ -58,12 +58,12 @@ #include "openvswitch/thread.h" #include "openvswitch/usdt-probes.h" #include "openvswitch/vlog.h" -#include "packets.h" -#include "random.h" -#include "sset.h" -#include "timeval.h" -#include "unaligned.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/random.h" +#include "internal/sset.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(dpif_netlink); #ifdef _WIN32 Index: openvswitch-2.17.2/lib/dpif-netlink.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-netlink.h +++ openvswitch-2.17.2/lib/dpif-netlink.h @@ -21,7 +21,7 @@ #include #include -#include "flow.h" +#include "internal/flow.h" struct ofpbuf; Index: openvswitch-2.17.2/lib/dpif-provider.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif-provider.h +++ openvswitch-2.17.2/lib/dpif-provider.h @@ -24,7 +24,7 @@ #include "openflow/openflow.h" #include "dpif.h" -#include "util.h" +#include "internal/util.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/dpif.c =================================================================== --- openvswitch-2.17.2.orig/lib/dpif.c +++ openvswitch-2.17.2/lib/dpif.c @@ -23,25 +23,25 @@ #include #include -#include "coverage.h" -#include "dp-packet.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" #include "dpctl.h" #include "dpif-netdev.h" -#include "flow.h" +#include "internal/flow.h" #include "netdev-provider.h" -#include "netdev.h" -#include "netlink.h" +#include "internal/netdev.h" +#include "internal/netlink.h" #include "odp-execute.h" #include "odp-util.h" -#include "packets.h" +#include "internal/packets.h" #include "route-table.h" -#include "seq.h" -#include "sset.h" -#include "timeval.h" +#include "internal/seq.h" +#include "internal/sset.h" +#include "internal/timeval.h" #include "tnl-neigh-cache.h" #include "tnl-ports.h" -#include "util.h" -#include "uuid.h" +#include "internal/util.h" +#include "internal/uuid.h" #include "valgrind.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/ofp-errors.h" Index: openvswitch-2.17.2/lib/dpif.h =================================================================== --- openvswitch-2.17.2.orig/lib/dpif.h +++ openvswitch-2.17.2/lib/dpif.h @@ -377,13 +377,13 @@ #include #include "dpdk.h" -#include "dp-packet.h" -#include "netdev.h" +#include "internal/dp-packet.h" +#include "internal/netdev.h" #include "openflow/openflow.h" #include "openvswitch/ofp-meter.h" -#include "ovs-numa.h" -#include "packets.h" -#include "util.h" +#include "openvswitch/ovs-numa.h" +#include "internal/packets.h" +#include "internal/util.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/dummy.c =================================================================== --- openvswitch-2.17.2.orig/lib/dummy.c +++ openvswitch-2.17.2/lib/dummy.c @@ -17,7 +17,7 @@ #include #include "dummy.h" #include -#include "util.h" +#include "internal/util.h" /* Enables support for "dummy" network devices and dpifs, which are useful for * testing. A client program might call this function if it is designed Index: openvswitch-2.17.2/lib/dynamic-string.c =================================================================== --- openvswitch-2.17.2.orig/lib/dynamic-string.c +++ openvswitch-2.17.2/lib/dynamic-string.c @@ -20,8 +20,8 @@ #include #include #include -#include "timeval.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/util.h" /* Initializes 'ds' as an empty string buffer. */ void Index: openvswitch-2.17.2/lib/entropy.c =================================================================== --- openvswitch-2.17.2.orig/lib/entropy.c +++ openvswitch-2.17.2/lib/entropy.c @@ -23,8 +23,8 @@ #ifdef _WIN32 #include #endif -#include "util.h" -#include "socket-util.h" +#include "internal/util.h" +#include "internal/socket-util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(entropy); Index: openvswitch-2.17.2/lib/fat-rwlock.c =================================================================== --- openvswitch-2.17.2.orig/lib/fat-rwlock.c +++ openvswitch-2.17.2/lib/fat-rwlock.c @@ -22,8 +22,8 @@ #include "openvswitch/hmap.h" #include "openvswitch/list.h" -#include "ovs-thread.h" -#include "random.h" +#include "openvswitch/ovs-thread.h" +#include "internal/random.h" struct fat_rwlock_slot { /* Membership in rwlock's list of "struct fat_rwlock_slot"s. Index: openvswitch-2.17.2/lib/fat-rwlock.h =================================================================== --- openvswitch-2.17.2.orig/lib/fat-rwlock.h +++ openvswitch-2.17.2/lib/fat-rwlock.h @@ -19,7 +19,7 @@ #include "openvswitch/compiler.h" #include "openvswitch/list.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" /* "Fat rwlock". * Index: openvswitch-2.17.2/lib/fatal-signal.c =================================================================== --- openvswitch-2.17.2.orig/lib/fatal-signal.c +++ openvswitch-2.17.2/lib/fatal-signal.c @@ -15,7 +15,7 @@ */ #include #include "backtrace.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include #include #include @@ -24,13 +24,13 @@ #include #include #include -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "sset.h" +#include "internal/sset.h" #include "signals.h" -#include "socket-util.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" #include "openvswitch/type-props.h" Index: openvswitch-2.17.2/lib/flow.c =================================================================== --- openvswitch-2.17.2.orig/lib/flow.c +++ openvswitch-2.17.2/lib/flow.c @@ -15,7 +15,7 @@ */ #include #include -#include "flow.h" +#include "internal/flow.h" #include #include #include @@ -26,21 +26,21 @@ #include #include #include -#include "byte-order.h" -#include "colors.h" -#include "coverage.h" -#include "csum.h" +#include "internal/byte-order.h" +#include "internal/colors.h" +#include "internal/coverage.h" +#include "internal/csum.h" #include "openvswitch/dynamic-string.h" -#include "hash.h" +#include "internal/hash.h" #include "jhash.h" #include "openvswitch/match.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openflow/openflow.h" -#include "packets.h" +#include "internal/packets.h" #include "odp-util.h" -#include "random.h" -#include "unaligned.h" -#include "util.h" +#include "internal/random.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "openvswitch/nsh.h" #include "ovs-router.h" #include "lib/netdev-provider.h" @@ -133,7 +133,7 @@ struct mf_ctx { /* miniflow_push_* macros allow filling in a miniflow data values in order. * Assertions are needed only when the layout of the struct flow is modified. * 'ofs' is a compile-time constant, which allows most of the code be optimized - * away. Some GCC versions gave warnings on ALWAYS_INLINE, so these are + * away. Some GCC versions gave warnings on OVS_ALWAYS_INLINE, so these are * defined as macros. */ #if (FLOW_WC_SEQ != 42) @@ -345,7 +345,7 @@ parse_mpls(const void **datap, size_t *s } /* passed vlan_hdrs arg must be at least size FLOW_MAX_VLAN_HEADERS. */ -static inline ALWAYS_INLINE size_t +static inline OVS_ALWAYS_INLINE size_t parse_vlan(const void **datap, size_t *sizep, union flow_vlan_hdr *vlan_hdrs) { const ovs_be16 *eth_type; @@ -369,7 +369,7 @@ parse_vlan(const void **datap, size_t *s return n; } -static inline ALWAYS_INLINE ovs_be16 +static inline OVS_ALWAYS_INLINE ovs_be16 parse_ethertype(const void **datap, size_t *sizep) { const struct llc_snap_header *llc; Index: openvswitch-2.17.2/lib/getopt_long.c =================================================================== --- openvswitch-2.17.2.orig/lib/getopt_long.c +++ openvswitch-2.17.2/lib/getopt_long.c @@ -32,7 +32,7 @@ #include #include #include -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(getopt_long); Index: openvswitch-2.17.2/lib/getrusage-windows.c =================================================================== --- openvswitch-2.17.2.orig/lib/getrusage-windows.c +++ openvswitch-2.17.2/lib/getrusage-windows.c @@ -19,7 +19,7 @@ #include #include #include -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(getrusage_windows); Index: openvswitch-2.17.2/lib/guarded-list.h =================================================================== --- openvswitch-2.17.2.orig/lib/guarded-list.h +++ openvswitch-2.17.2/lib/guarded-list.h @@ -20,7 +20,7 @@ #include #include "openvswitch/compiler.h" #include "openvswitch/list.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" struct guarded_list { struct ovs_mutex mutex; Index: openvswitch-2.17.2/lib/hash.c =================================================================== --- openvswitch-2.17.2.orig/lib/hash.c +++ openvswitch-2.17.2/lib/hash.c @@ -14,9 +14,9 @@ * limitations under the License. */ #include -#include "hash.h" +#include "internal/hash.h" #include -#include "unaligned.h" +#include "internal/unaligned.h" /* Returns the hash of 'a', 'b', and 'c'. */ uint32_t Index: openvswitch-2.17.2/lib/heap.c =================================================================== --- openvswitch-2.17.2.orig/lib/heap.c +++ openvswitch-2.17.2/lib/heap.c @@ -17,7 +17,7 @@ #include #include "heap.h" #include -#include "util.h" +#include "internal/util.h" static void put_node(struct heap *, struct heap_node *, size_t i); static void swap_nodes(struct heap *, size_t i, size_t j); Index: openvswitch-2.17.2/lib/hindex.c =================================================================== --- openvswitch-2.17.2.orig/lib/hindex.c +++ openvswitch-2.17.2/lib/hindex.c @@ -15,8 +15,8 @@ */ #include -#include "hindex.h" -#include "coverage.h" +#include "internal/hindex.h" +#include "internal/coverage.h" static bool hindex_node_is_body(const struct hindex_node *); static bool hindex_node_is_head(const struct hindex_node *); Index: openvswitch-2.17.2/lib/hmap.c =================================================================== --- openvswitch-2.17.2.orig/lib/hmap.c +++ openvswitch-2.17.2/lib/hmap.c @@ -18,9 +18,9 @@ #include "openvswitch/hmap.h" #include #include -#include "coverage.h" -#include "random.h" -#include "util.h" +#include "internal/coverage.h" +#include "internal/random.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(hmap); Index: openvswitch-2.17.2/lib/hmapx.c =================================================================== --- openvswitch-2.17.2.orig/lib/hmapx.c +++ openvswitch-2.17.2/lib/hmapx.c @@ -16,9 +16,9 @@ #include -#include "hmapx.h" +#include "internal/hmapx.h" -#include "hash.h" +#include "internal/hash.h" static struct hmapx_node * hmapx_find__(const struct hmapx *map, const void *data, size_t hash) Index: openvswitch-2.17.2/lib/id-fpool.c =================================================================== --- openvswitch-2.17.2.orig/lib/id-fpool.c +++ openvswitch-2.17.2/lib/id-fpool.c @@ -19,7 +19,7 @@ #include "openvswitch/list.h" #include "openvswitch/thread.h" #include "openvswitch/util.h" -#include "ovs-atomic.h" +#include "openvswitch/ovs-atomic.h" #include "id-fpool.h" #ifdef HAVE_PTHREAD_SPIN_LOCK Index: openvswitch-2.17.2/lib/id-pool.c =================================================================== --- openvswitch-2.17.2.orig/lib/id-pool.c +++ openvswitch-2.17.2/lib/id-pool.c @@ -16,9 +16,9 @@ */ #include -#include "id-pool.h" +#include "internal/id-pool.h" #include "openvswitch/hmap.h" -#include "hash.h" +#include "internal/hash.h" struct id_node { struct hmap_node node; Index: openvswitch-2.17.2/lib/if-notifier-bsd.c =================================================================== --- openvswitch-2.17.2.orig/lib/if-notifier-bsd.c +++ openvswitch-2.17.2/lib/if-notifier-bsd.c @@ -17,7 +17,7 @@ #include #include "if-notifier.h" #include "rtbsd.h" -#include "util.h" +#include "internal/util.h" struct if_notifier { struct rtbsd_notifier notifier; Index: openvswitch-2.17.2/lib/if-notifier.c =================================================================== --- openvswitch-2.17.2.orig/lib/if-notifier.c +++ openvswitch-2.17.2/lib/if-notifier.c @@ -17,7 +17,7 @@ #include #include "if-notifier.h" #include "rtnetlink.h" -#include "util.h" +#include "internal/util.h" struct if_notifier { struct nln_notifier *notifier; Index: openvswitch-2.17.2/lib/ipf.c =================================================================== --- openvswitch-2.17.2.orig/lib/ipf.c +++ openvswitch-2.17.2/lib/ipf.c @@ -23,16 +23,16 @@ #include #include -#include "coverage.h" -#include "csum.h" +#include "internal/coverage.h" +#include "internal/csum.h" #include "ipf.h" -#include "latch.h" +#include "internal/latch.h" #include "openvswitch/hmap.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" -#include "ovs-atomic.h" -#include "packets.h" -#include "util.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/packets.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ipf); COVERAGE_DEFINE(ipf_stuck_frag_list_purged); Index: openvswitch-2.17.2/lib/ipf.h =================================================================== --- openvswitch-2.17.2.orig/lib/ipf.h +++ openvswitch-2.17.2/lib/ipf.h @@ -17,7 +17,7 @@ #ifndef IPF_H #define IPF_H 1 -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/types.h" struct ipf; Index: openvswitch-2.17.2/lib/jhash.c =================================================================== --- openvswitch-2.17.2.orig/lib/jhash.c +++ openvswitch-2.17.2/lib/jhash.c @@ -17,7 +17,7 @@ #include #include "jhash.h" #include -#include "unaligned.h" +#include "internal/unaligned.h" /* This is the public domain lookup3 hash by Bob Jenkins from * http://burtleburtle.net/bob/c/lookup3.c, modified for style. */ Index: openvswitch-2.17.2/lib/jhash.h =================================================================== --- openvswitch-2.17.2.orig/lib/jhash.h +++ openvswitch-2.17.2/lib/jhash.h @@ -21,7 +21,7 @@ #include #include #include -#include "util.h" +#include "internal/util.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/json.c =================================================================== --- openvswitch-2.17.2.orig/lib/json.c +++ openvswitch-2.17.2/lib/json.c @@ -25,11 +25,11 @@ #include #include "openvswitch/dynamic-string.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/shash.h" #include "unicode.h" -#include "util.h" -#include "uuid.h" +#include "internal/util.h" +#include "internal/uuid.h" /* The type of a JSON token. */ enum json_token_type { Index: openvswitch-2.17.2/lib/jsonrpc.c =================================================================== --- openvswitch-2.17.2.orig/lib/jsonrpc.c +++ openvswitch-2.17.2/lib/jsonrpc.c @@ -16,23 +16,23 @@ #include -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include #include "byteq.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/json.h" #include "openvswitch/list.h" #include "openvswitch/ofpbuf.h" #include "ovs-replay.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" #include "reconnect.h" -#include "stream.h" -#include "svec.h" -#include "timeval.h" +#include "internal/stream.h" +#include "internal/svec.h" +#include "internal/timeval.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(jsonrpc); Index: openvswitch-2.17.2/lib/lacp.c =================================================================== --- openvswitch-2.17.2.orig/lib/lacp.c +++ openvswitch-2.17.2/lib/lacp.c @@ -20,19 +20,19 @@ #include "connectivity.h" #include "openvswitch/dynamic-string.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "dp-packet.h" -#include "ovs-atomic.h" -#include "packets.h" +#include "internal/dp-packet.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "seq.h" +#include "internal/seq.h" #include "openvswitch/shash.h" -#include "timer.h" -#include "timeval.h" -#include "unixctl.h" +#include "internal/timer.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(lacp); Index: openvswitch-2.17.2/lib/lacp.h =================================================================== --- openvswitch-2.17.2.orig/lib/lacp.h +++ openvswitch-2.17.2/lib/lacp.h @@ -19,7 +19,7 @@ #include #include -#include "packets.h" +#include "internal/packets.h" /* LACP Protocol Implementation. */ Index: openvswitch-2.17.2/lib/latch-unix.c =================================================================== --- openvswitch-2.17.2.orig/lib/latch-unix.c +++ openvswitch-2.17.2/lib/latch-unix.c @@ -16,12 +16,12 @@ #include -#include "latch.h" +#include "internal/latch.h" #include #include #include #include "openvswitch/poll-loop.h" -#include "socket-util.h" +#include "internal/socket-util.h" /* Initializes 'latch' as initially unset. */ void Index: openvswitch-2.17.2/lib/latch-windows.c =================================================================== --- openvswitch-2.17.2.orig/lib/latch-windows.c +++ openvswitch-2.17.2/lib/latch-windows.c @@ -16,12 +16,12 @@ #include -#include "latch.h" +#include "internal/latch.h" #include #include #include #include "openvswitch/poll-loop.h" -#include "socket-util.h" +#include "internal/socket-util.h" /* Initializes 'latch' as initially unset. */ void Index: openvswitch-2.17.2/lib/learn.c =================================================================== --- openvswitch-2.17.2.orig/lib/learn.c +++ openvswitch-2.17.2/lib/learn.c @@ -18,9 +18,9 @@ #include "learn.h" -#include "byte-order.h" -#include "colors.h" -#include "nx-match.h" +#include "internal/byte-order.h" +#include "internal/colors.h" +#include "internal/nx-match.h" #include "openflow/openflow.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/match.h" @@ -32,7 +32,7 @@ #include "openvswitch/ofp-table.h" #include "openvswitch/ofpbuf.h" #include "vl-mff-map.h" -#include "unaligned.h" +#include "internal/unaligned.h" /* Checks that 'learn' is a valid action on 'flow'. Returns 0 if it is valid, Index: openvswitch-2.17.2/lib/learning-switch.c =================================================================== --- openvswitch-2.17.2.orig/lib/learning-switch.c +++ openvswitch-2.17.2/lib/learning-switch.c @@ -24,10 +24,10 @@ #include #include -#include "byte-order.h" -#include "classifier.h" -#include "dp-packet.h" -#include "flow.h" +#include "internal/byte-order.h" +#include "internal/classifier.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" #include "openvswitch/hmap.h" #include "mac-learning.h" #include "openflow/openflow.h" @@ -48,8 +48,8 @@ #include "openvswitch/poll-loop.h" #include "openvswitch/rconn.h" #include "openvswitch/shash.h" -#include "simap.h" -#include "timeval.h" +#include "internal/simap.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(learning_switch); Index: openvswitch-2.17.2/lib/lldp/lldp.c =================================================================== --- openvswitch-2.17.2.orig/lib/lldp/lldp.c +++ openvswitch-2.17.2/lib/lldp/lldp.c @@ -26,8 +26,8 @@ #include #include #include "openvswitch/compiler.h" -#include "dp-packet.h" -#include "packets.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" VLOG_DEFINE_THIS_MODULE(lldp); Index: openvswitch-2.17.2/lib/lldp/lldpd-structs.c =================================================================== --- openvswitch-2.17.2.orig/lib/lldp/lldpd-structs.c +++ openvswitch-2.17.2/lib/lldp/lldpd-structs.c @@ -21,7 +21,7 @@ #include #include #include "lldpd.h" -#include "timeval.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(lldpd_structs); Index: openvswitch-2.17.2/lib/lldp/lldpd-structs.h =================================================================== --- openvswitch-2.17.2.orig/lib/lldp/lldpd-structs.h +++ openvswitch-2.17.2/lib/lldp/lldpd-structs.h @@ -25,7 +25,7 @@ #include #include "aa-structs.h" #include "lldp-const.h" -#include "packets.h" +#include "internal/packets.h" enum { LLDPD_AF_UNSPEC = 0, Index: openvswitch-2.17.2/lib/lldp/lldpd.c =================================================================== --- openvswitch-2.17.2.orig/lib/lldp/lldpd.c +++ openvswitch-2.17.2/lib/lldp/lldpd.c @@ -42,8 +42,8 @@ #include "openvswitch/compiler.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/list.h" -#include "packets.h" -#include "timeval.h" +#include "internal/packets.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(lldpd); Index: openvswitch-2.17.2/lib/lldp/lldpd.h =================================================================== --- openvswitch-2.17.2.orig/lib/lldp/lldpd.h +++ openvswitch-2.17.2/lib/lldp/lldpd.h @@ -24,11 +24,11 @@ #include #include #include -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/list.h" #include "lldpd-structs.h" #include "lldp-tlv.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/vlog.h" #define ETHERTYPE_LLDP 0x88cc Index: openvswitch-2.17.2/lib/lockfile.c =================================================================== --- openvswitch-2.17.2.orig/lib/lockfile.c +++ openvswitch-2.17.2/lib/lockfile.c @@ -24,12 +24,12 @@ #include #include -#include "coverage.h" -#include "hash.h" +#include "internal/coverage.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "ovs-thread.h" -#include "timeval.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(lockfile); Index: openvswitch-2.17.2/lib/mac-learning.c =================================================================== --- openvswitch-2.17.2.orig/lib/mac-learning.c +++ openvswitch-2.17.2/lib/mac-learning.c @@ -20,14 +20,14 @@ #include #include -#include "bitmap.h" -#include "coverage.h" -#include "hash.h" +#include "internal/bitmap.h" +#include "internal/coverage.h" +#include "internal/hash.h" #include "openvswitch/list.h" #include "openvswitch/poll-loop.h" -#include "timeval.h" -#include "unaligned.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "vlan-bitmap.h" COVERAGE_DEFINE(mac_learning_learned); Index: openvswitch-2.17.2/lib/mac-learning.h =================================================================== --- openvswitch-2.17.2.orig/lib/mac-learning.h +++ openvswitch-2.17.2/lib/mac-learning.h @@ -21,10 +21,10 @@ #include "heap.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" -#include "ovs-atomic.h" -#include "ovs-thread.h" -#include "packets.h" -#include "timeval.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/timeval.h" /* MAC learning table * ================== Index: openvswitch-2.17.2/lib/match.c =================================================================== --- openvswitch-2.17.2.orig/lib/match.c +++ openvswitch-2.17.2/lib/match.c @@ -17,14 +17,14 @@ #include #include "openvswitch/match.h" #include -#include "flow.h" -#include "byte-order.h" -#include "colors.h" +#include "internal/flow.h" +#include "internal/byte-order.h" +#include "internal/colors.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/meta-flow.h" #include "openvswitch/ofp-port.h" -#include "packets.h" -#include "tun-metadata.h" +#include "internal/packets.h" +#include "internal/tun-metadata-private.h" #include "openvswitch/nsh.h" /* Converts the flow in 'flow' into a match in 'match', with the given Index: openvswitch-2.17.2/lib/mcast-snooping.c =================================================================== --- openvswitch-2.17.2.orig/lib/mcast-snooping.c +++ openvswitch-2.17.2/lib/mcast-snooping.c @@ -17,21 +17,21 @@ */ #include -#include "mcast-snooping.h" +#include "internal/mcast-snooping.h" #include #include -#include "bitmap.h" -#include "byte-order.h" -#include "coverage.h" -#include "hash.h" +#include "internal/bitmap.h" +#include "internal/byte-order.h" +#include "internal/coverage.h" +#include "internal/hash.h" #include "openvswitch/list.h" #include "openvswitch/poll-loop.h" -#include "timeval.h" +#include "internal/timeval.h" #include "entropy.h" -#include "unaligned.h" -#include "util.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "vlan-bitmap.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/memory.c =================================================================== --- openvswitch-2.17.2.orig/lib/memory.c +++ openvswitch-2.17.2/lib/memory.c @@ -15,15 +15,15 @@ */ #include -#include "memory.h" +#include "internal/memory.h" #include #include #include #include "openvswitch/dynamic-string.h" #include "openvswitch/poll-loop.h" -#include "simap.h" -#include "timeval.h" -#include "unixctl.h" +#include "internal/simap.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(memory); Index: openvswitch-2.17.2/lib/meta-flow.c =================================================================== --- openvswitch-2.17.2.orig/lib/meta-flow.c +++ openvswitch-2.17.2/lib/meta-flow.c @@ -23,19 +23,19 @@ #include #include -#include "classifier.h" +#include "internal/classifier.h" #include "openvswitch/dynamic-string.h" -#include "nx-match.h" -#include "ovs-atomic.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" -#include "packets.h" -#include "random.h" +#include "internal/nx-match.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/random.h" #include "openvswitch/shash.h" -#include "socket-util.h" -#include "tun-metadata.h" -#include "unaligned.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/tun-metadata-private.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-match.h" #include "openvswitch/ofp-port.h" Index: openvswitch-2.17.2/lib/mpsc-queue.c =================================================================== --- openvswitch-2.17.2.orig/lib/mpsc-queue.c +++ openvswitch-2.17.2/lib/mpsc-queue.c @@ -16,7 +16,7 @@ #include -#include "ovs-atomic.h" +#include "openvswitch/ovs-atomic.h" #include "mpsc-queue.h" Index: openvswitch-2.17.2/lib/mpsc-queue.h =================================================================== --- openvswitch-2.17.2.orig/lib/mpsc-queue.h +++ openvswitch-2.17.2/lib/mpsc-queue.h @@ -24,7 +24,7 @@ #include #include -#include "ovs-atomic.h" +#include "openvswitch/ovs-atomic.h" /* Multi-producer, single-consumer queue * ===================================== Index: openvswitch-2.17.2/lib/multipath.c =================================================================== --- openvswitch-2.17.2.orig/lib/multipath.c +++ openvswitch-2.17.2/lib/multipath.c @@ -21,14 +21,14 @@ #include #include #include -#include "colors.h" -#include "nx-match.h" +#include "internal/colors.h" +#include "internal/nx-match.h" #include "openflow/nicira-ext.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-errors.h" -#include "packets.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/util.h" /* Checks that 'mp' is valid on flow. Returns 0 if it is valid, otherwise an * OFPERR_*. */ Index: openvswitch-2.17.2/lib/namemap.c =================================================================== --- openvswitch-2.17.2.orig/lib/namemap.c +++ openvswitch-2.17.2/lib/namemap.c @@ -17,7 +17,7 @@ #include #include "openvswitch/namemap.h" #include -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" Index: openvswitch-2.17.2/lib/netdev-afxdp-pool.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-afxdp-pool.c +++ openvswitch-2.17.2/lib/netdev-afxdp-pool.c @@ -15,7 +15,7 @@ */ #include -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "netdev-afxdp-pool.h" #include "openvswitch/util.h" Index: openvswitch-2.17.2/lib/netdev-afxdp-pool.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-afxdp-pool.h +++ openvswitch-2.17.2/lib/netdev-afxdp-pool.h @@ -24,7 +24,7 @@ #include #include "openvswitch/thread.h" -#include "ovs-atomic.h" +#include "openvswitch/ovs-atomic.h" /* LIFO ptr_array. */ struct umem_pool { Index: openvswitch-2.17.2/lib/netdev-afxdp.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-afxdp.c +++ openvswitch-2.17.2/lib/netdev-afxdp.c @@ -18,7 +18,7 @@ #include "netdev-linux-private.h" #include "netdev-linux.h" -#include "netdev-afxdp.h" +#include "internal/netdev-afxdp.h" #include "netdev-afxdp-pool.h" #include @@ -35,19 +35,19 @@ #include #include -#include "coverage.h" -#include "dp-packet.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" #include "dpif-netdev.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/compiler.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/list.h" #include "openvswitch/thread.h" #include "openvswitch/vlog.h" -#include "ovs-numa.h" -#include "packets.h" -#include "socket-util.h" -#include "util.h" +#include "openvswitch/ovs-numa.h" +#include "internal/packets.h" +#include "internal/socket-util.h" +#include "internal/util.h" #ifndef SOL_XDP #define SOL_XDP 283 Index: openvswitch-2.17.2/lib/netdev-bsd.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-bsd.c +++ openvswitch-2.17.2/lib/netdev-bsd.c @@ -48,19 +48,19 @@ #endif #include "rtbsd.h" -#include "coverage.h" -#include "dp-packet.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" #include "dpif-netdev.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openflow/openflow.h" -#include "ovs-thread.h" -#include "packets.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "socket-util.h" -#include "svec.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/svec.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(netdev_bsd); Index: openvswitch-2.17.2/lib/netdev-dpdk.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-dpdk.c +++ openvswitch-2.17.2/lib/netdev-dpdk.c @@ -15,7 +15,7 @@ */ #include -#include "netdev-dpdk.h" +#include "internal/netdev-dpdk.h" #include #include @@ -39,13 +39,13 @@ #include #include -#include "cmap.h" -#include "coverage.h" -#include "dirs.h" -#include "dp-packet.h" +#include "internal/cmap.h" +#include "internal/coverage.h" +#include "internal/dirs.h" +#include "internal/dp-packet.h" #include "dpdk.h" #include "dpif-netdev.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "if-notifier.h" #include "netdev-provider.h" #include "netdev-vport.h" @@ -56,18 +56,18 @@ #include "openvswitch/ofp-print.h" #include "openvswitch/shash.h" #include "openvswitch/vlog.h" -#include "ovs-numa.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" -#include "packets.h" -#include "smap.h" -#include "sset.h" -#include "timeval.h" -#include "unaligned.h" -#include "unixctl.h" +#include "openvswitch/ovs-numa.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/smap.h" +#include "internal/sset.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" #include "userspace-tso.h" -#include "util.h" -#include "uuid.h" +#include "internal/util.h" +#include "internal/uuid.h" enum {VIRTIO_RXQ, VIRTIO_TXQ, VIRTIO_QNUM}; Index: openvswitch-2.17.2/lib/netdev-dummy.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-dummy.c +++ openvswitch-2.17.2/lib/netdev-dummy.c @@ -21,9 +21,9 @@ #include #include -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "dpif-netdev.h" -#include "flow.h" +#include "internal/flow.h" #include "netdev-offload-provider.h" #include "netdev-provider.h" #include "netdev-vport.h" @@ -34,16 +34,16 @@ #include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "ovs-atomic.h" -#include "packets.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/packets.h" #include "pcap-file.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "sset.h" -#include "stream.h" -#include "unaligned.h" -#include "timeval.h" -#include "unixctl.h" +#include "internal/sset.h" +#include "internal/stream.h" +#include "internal/unaligned.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" #include "reconnect.h" VLOG_DEFINE_THIS_MODULE(netdev_dummy); Index: openvswitch-2.17.2/lib/netdev-linux-private.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-linux-private.h +++ openvswitch-2.17.2/lib/netdev-linux-private.h @@ -27,14 +27,14 @@ #include #include -#include "dp-packet.h" -#include "netdev-afxdp.h" +#include "internal/dp-packet.h" +#include "internal/netdev-afxdp.h" #include "netdev-afxdp-pool.h" #include "netdev-provider.h" #include "netdev-vport.h" #include "openvswitch/thread.h" -#include "ovs-atomic.h" -#include "timer.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/timer.h" struct netdev; Index: openvswitch-2.17.2/lib/netdev-linux.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-linux.c +++ openvswitch-2.17.2/lib/netdev-linux.c @@ -49,37 +49,37 @@ #include #include -#include "coverage.h" -#include "dp-packet.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" #include "dpif-netlink.h" #include "dpif-netdev.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "netdev-afxdp.h" +#include "internal/netdev-afxdp.h" #include "netdev-provider.h" #include "netdev-vport.h" #include "netlink-notifier.h" #include "netlink-socket.h" -#include "netlink.h" +#include "internal/netlink.h" #include "netnsid.h" #include "openvswitch/ofpbuf.h" #include "openflow/openflow.h" -#include "ovs-atomic.h" -#include "ovs-numa.h" -#include "packets.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-numa.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" #include "rtnetlink.h" #include "openvswitch/shash.h" -#include "socket-util.h" -#include "sset.h" +#include "internal/socket-util.h" +#include "internal/sset.h" #include "tc.h" -#include "timer.h" -#include "unaligned.h" +#include "internal/timer.h" +#include "internal/unaligned.h" #include "openvswitch/vlog.h" #include "userspace-tso.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(netdev_linux); Index: openvswitch-2.17.2/lib/netdev-native-tnl.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-native-tnl.c +++ openvswitch-2.17.2/lib/netdev-native-tnl.c @@ -32,17 +32,17 @@ #include #include -#include "byte-order.h" -#include "csum.h" -#include "dp-packet.h" -#include "netdev.h" +#include "internal/byte-order.h" +#include "internal/csum.h" +#include "internal/dp-packet.h" +#include "internal/netdev.h" #include "netdev-vport.h" #include "netdev-vport-private.h" #include "odp-netlink.h" -#include "packets.h" -#include "seq.h" -#include "unaligned.h" -#include "unixctl.h" +#include "internal/packets.h" +#include "internal/seq.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(native_tnl); Index: openvswitch-2.17.2/lib/netdev-native-tnl.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-native-tnl.h +++ openvswitch-2.17.2/lib/netdev-native-tnl.h @@ -20,9 +20,9 @@ #include #include #include "openvswitch/compiler.h" -#include "dp-packet.h" -#include "packets.h" -#include "unixctl.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" +#include "internal/unixctl.h" struct netdev; struct ovs_action_push_tnl; Index: openvswitch-2.17.2/lib/netdev-offload-dpdk.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-offload-dpdk.c +++ openvswitch-2.17.2/lib/netdev-offload-dpdk.c @@ -21,7 +21,7 @@ #include #include -#include "cmap.h" +#include "internal/cmap.h" #include "dpif-netdev.h" #include "netdev-offload-provider.h" #include "netdev-provider.h" @@ -29,9 +29,9 @@ #include "odp-util.h" #include "openvswitch/match.h" #include "openvswitch/vlog.h" -#include "ovs-rcu.h" -#include "packets.h" -#include "uuid.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/packets.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(netdev_offload_dpdk); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(600, 600); Index: openvswitch-2.17.2/lib/netdev-offload-provider.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-offload-provider.h +++ openvswitch-2.17.2/lib/netdev-offload-provider.h @@ -18,11 +18,11 @@ #ifndef NETDEV_FLOW_API_PROVIDER_H #define NETDEV_FLOW_API_PROVIDER_H 1 -#include "flow.h" +#include "internal/flow.h" #include "netdev-offload.h" #include "openvswitch/netdev.h" #include "openvswitch/types.h" -#include "packets.h" +#include "internal/packets.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/netdev-offload-tc.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-offload-tc.c +++ openvswitch-2.17.2/lib/netdev-offload-tc.c @@ -20,7 +20,7 @@ #include #include "dpif.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "openvswitch/match.h" #include "openvswitch/ofpbuf.h" @@ -32,13 +32,13 @@ #include "netdev-offload-provider.h" #include "netdev-provider.h" #include "netdev-vport.h" -#include "netlink.h" +#include "internal/netlink.h" #include "netlink-socket.h" #include "odp-netlink.h" #include "odp-util.h" #include "tc.h" -#include "unaligned.h" -#include "util.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "dpif-provider.h" VLOG_DEFINE_THIS_MODULE(netdev_offload_tc); Index: openvswitch-2.17.2/lib/netdev-offload.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-offload.c +++ openvswitch-2.17.2/lib/netdev-offload.c @@ -26,31 +26,31 @@ #include #include -#include "cmap.h" -#include "coverage.h" +#include "internal/cmap.h" +#include "internal/coverage.h" #include "dpif.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/list.h" #include "netdev-offload-provider.h" #include "netdev-provider.h" #include "netdev-vport.h" #include "odp-netlink.h" #include "openflow/openflow.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/ofp-print.h" #include "openvswitch/poll-loop.h" -#include "seq.h" +#include "internal/seq.h" #include "openvswitch/shash.h" -#include "smap.h" -#include "socket-util.h" -#include "sset.h" -#include "svec.h" +#include "internal/smap.h" +#include "internal/socket-util.h" +#include "internal/sset.h" +#include "internal/svec.h" #include "openvswitch/vlog.h" -#include "flow.h" -#include "util.h" +#include "internal/flow.h" +#include "internal/util.h" #ifdef __linux__ #include "tc.h" #endif Index: openvswitch-2.17.2/lib/netdev-offload.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-offload.h +++ openvswitch-2.17.2/lib/netdev-offload.h @@ -20,10 +20,10 @@ #include "openvswitch/netdev.h" #include "openvswitch/types.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" -#include "packets.h" -#include "flow.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/flow.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/netdev-provider.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-provider.h +++ openvswitch-2.17.2/lib/netdev-provider.h @@ -20,15 +20,15 @@ /* Generic interface to network devices. */ #include "connectivity.h" -#include "netdev.h" +#include "internal/netdev.h" #include "netdev-offload.h" #include "openvswitch/list.h" -#include "ovs-numa.h" -#include "ovs-rcu.h" -#include "packets.h" -#include "seq.h" +#include "openvswitch/ovs-numa.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/packets.h" +#include "internal/seq.h" #include "openvswitch/shash.h" -#include "smap.h" +#include "internal/smap.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/netdev-vport-private.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-vport-private.h +++ openvswitch-2.17.2/lib/netdev-vport-private.h @@ -20,9 +20,9 @@ #include #include #include "openvswitch/compiler.h" -#include "netdev.h" +#include "internal/netdev.h" #include "netdev-provider.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" struct netdev_vport { struct netdev up; Index: openvswitch-2.17.2/lib/netdev-vport.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-vport.c +++ openvswitch-2.17.2/lib/netdev-vport.c @@ -28,24 +28,24 @@ #include #include -#include "byte-order.h" -#include "daemon.h" -#include "dirs.h" +#include "internal/byte-order.h" +#include "internal/daemon.h" +#include "internal/dirs.h" #include "dpif.h" -#include "netdev.h" +#include "internal/netdev.h" #include "netdev-native-tnl.h" #include "netdev-provider.h" #include "netdev-vport-private.h" #include "openvswitch/dynamic-string.h" #include "ovs-router.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" #include "route-table.h" -#include "simap.h" -#include "smap.h" -#include "socket-util.h" -#include "unaligned.h" -#include "unixctl.h" +#include "internal/simap.h" +#include "internal/smap.h" +#include "internal/socket-util.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" #include "openvswitch/vlog.h" #include "openvswitch/ofp-parse.h" #ifdef __linux__ Index: openvswitch-2.17.2/lib/netdev-windows.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-windows.c +++ openvswitch-2.17.2/lib/netdev-windows.c @@ -21,18 +21,18 @@ #include -#include "coverage.h" -#include "fatal-signal.h" +#include "internal/coverage.h" +#include "internal/fatal-signal.h" #include "netdev-provider.h" #include "openvswitch/ofpbuf.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "svec.h" +#include "internal/svec.h" #include "openvswitch/vlog.h" #include "odp-netlink.h" #include "netlink-socket.h" -#include "netlink.h" +#include "internal/netlink.h" VLOG_DEFINE_THIS_MODULE(netdev_windows); static struct vlog_rate_limit error_rl = VLOG_RATE_LIMIT_INIT(9999, 5); Index: openvswitch-2.17.2/lib/netdev.c =================================================================== --- openvswitch-2.17.2.orig/lib/netdev.c +++ openvswitch-2.17.2/lib/netdev.c @@ -15,7 +15,7 @@ */ #include -#include "netdev.h" +#include "internal/netdev.h" #include #include @@ -31,31 +31,31 @@ #include #endif -#include "cmap.h" -#include "coverage.h" +#include "internal/cmap.h" +#include "internal/coverage.h" #include "dpif.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/list.h" #include "netdev-offload-provider.h" #include "netdev-provider.h" #include "netdev-vport.h" #include "odp-netlink.h" #include "openflow/openflow.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/ofp-print.h" #include "openvswitch/poll-loop.h" -#include "seq.h" +#include "internal/seq.h" #include "openvswitch/shash.h" -#include "smap.h" -#include "socket-util.h" -#include "sset.h" -#include "svec.h" +#include "internal/smap.h" +#include "internal/socket-util.h" +#include "internal/sset.h" +#include "internal/svec.h" #include "openvswitch/vlog.h" -#include "flow.h" -#include "util.h" +#include "internal/flow.h" +#include "internal/util.h" #ifdef __linux__ #include "tc.h" #endif Index: openvswitch-2.17.2/lib/netflow.h =================================================================== --- openvswitch-2.17.2.orig/lib/netflow.h +++ openvswitch-2.17.2/lib/netflow.h @@ -21,7 +21,7 @@ #include #include "openvswitch/types.h" -#include "util.h" +#include "internal/util.h" #define NETFLOW_V5_VERSION 5 Index: openvswitch-2.17.2/lib/netlink-conntrack.c =================================================================== --- openvswitch-2.17.2.orig/lib/netlink-conntrack.c +++ openvswitch-2.17.2/lib/netlink-conntrack.c @@ -26,17 +26,17 @@ #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/compiler.h" #include "openvswitch/dynamic-string.h" -#include "netlink.h" +#include "internal/netlink.h" #include "netlink-socket.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" #include "openvswitch/poll-loop.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(netlink_conntrack); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); Index: openvswitch-2.17.2/lib/netlink-conntrack.h =================================================================== --- openvswitch-2.17.2.orig/lib/netlink-conntrack.h +++ openvswitch-2.17.2/lib/netlink-conntrack.h @@ -19,15 +19,15 @@ #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/compiler.h" #include "ct-dpif.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" #include "openvswitch/ofpbuf.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" enum nl_ct_event_type { NL_CT_EVENT_NEW = 1 << 0, Index: openvswitch-2.17.2/lib/netlink-notifier.c =================================================================== --- openvswitch-2.17.2.orig/lib/netlink-notifier.c +++ openvswitch-2.17.2/lib/netlink-notifier.c @@ -22,8 +22,8 @@ #include #include -#include "coverage.h" -#include "netlink.h" +#include "internal/coverage.h" +#include "internal/netlink.h" #include "netlink-socket.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/netlink-socket.c =================================================================== --- openvswitch-2.17.2.orig/lib/netlink-socket.c +++ openvswitch-2.17.2/lib/netlink-socket.c @@ -23,20 +23,20 @@ #include #include #include -#include "coverage.h" +#include "internal/coverage.h" #include "openvswitch/dynamic-string.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "netlink.h" -#include "netlink-protocol.h" +#include "internal/netlink.h" +#include "internal/netlink-protocol.h" #include "netnsid.h" #include "odp-netlink.h" #include "openvswitch/ofpbuf.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" -#include "seq.h" -#include "socket-util.h" -#include "util.h" +#include "internal/seq.h" +#include "internal/socket-util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(netlink_socket); Index: openvswitch-2.17.2/lib/netlink-socket.h =================================================================== --- openvswitch-2.17.2.orig/lib/netlink-socket.h +++ openvswitch-2.17.2/lib/netlink-socket.h @@ -194,8 +194,8 @@ #include #include #include "openvswitch/ofpbuf.h" -#include "ovs-atomic.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-thread.h" struct nl_sock; Index: openvswitch-2.17.2/lib/netlink.c =================================================================== --- openvswitch-2.17.2.orig/lib/netlink.c +++ openvswitch-2.17.2/lib/netlink.c @@ -15,19 +15,19 @@ */ #include -#include "netlink.h" +#include "internal/netlink.h" #include #include #include #include -#include "coverage.h" -#include "flow.h" -#include "netlink-protocol.h" +#include "internal/coverage.h" +#include "internal/flow.h" +#include "internal/netlink-protocol.h" #include "openvswitch/ofpbuf.h" -#include "timeval.h" -#include "unaligned.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(netlink); Index: openvswitch-2.17.2/lib/nx-match.c =================================================================== --- openvswitch-2.17.2.orig/lib/nx-match.c +++ openvswitch-2.17.2/lib/nx-match.c @@ -16,12 +16,12 @@ #include -#include "nx-match.h" +#include "internal/nx-match.h" #include -#include "classifier.h" -#include "colors.h" +#include "internal/classifier.h" +#include "internal/colors.h" #include "openvswitch/hmap.h" #include "openflow/nicira-ext.h" #include "openvswitch/dynamic-string.h" @@ -32,11 +32,11 @@ #include "openvswitch/ofp-port.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/shash.h" -#include "tun-metadata.h" -#include "unaligned.h" -#include "util.h" +#include "internal/tun-metadata-private.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "vl-mff-map.h" VLOG_DEFINE_THIS_MODULE(nx_match); Index: openvswitch-2.17.2/lib/object-collection.c =================================================================== --- openvswitch-2.17.2.orig/lib/object-collection.c +++ openvswitch-2.17.2/lib/object-collection.c @@ -17,7 +17,7 @@ #include #include "object-collection.h" -#include "util.h" +#include "internal/util.h" void object_collection_init(struct object_collection *coll) Index: openvswitch-2.17.2/lib/odp-execute.c =================================================================== --- openvswitch-2.17.2.orig/lib/odp-execute.c +++ openvswitch-2.17.2/lib/odp-execute.c @@ -25,17 +25,17 @@ #include #include -#include "coverage.h" -#include "dp-packet.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" #include "dpif.h" -#include "netlink.h" +#include "internal/netlink.h" #include "odp-netlink.h" #include "odp-util.h" -#include "packets.h" -#include "flow.h" -#include "unaligned.h" -#include "util.h" -#include "csum.h" +#include "internal/packets.h" +#include "internal/flow.h" +#include "internal/unaligned.h" +#include "internal/util.h" +#include "internal/csum.h" #include "conntrack.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/odp-util.c =================================================================== --- openvswitch-2.17.2.orig/lib/odp-util.c +++ openvswitch-2.17.2/lib/odp-util.c @@ -27,24 +27,24 @@ #include #include -#include "byte-order.h" -#include "coverage.h" +#include "internal/byte-order.h" +#include "internal/coverage.h" #include "dpif.h" #include "openvswitch/dynamic-string.h" -#include "flow.h" -#include "netlink.h" +#include "internal/flow.h" +#include "internal/netlink.h" #include "openvswitch/ofpbuf.h" -#include "packets.h" -#include "simap.h" -#include "timeval.h" -#include "tun-metadata.h" -#include "unaligned.h" -#include "util.h" -#include "uuid.h" +#include "internal/packets.h" +#include "internal/simap.h" +#include "internal/timeval.h" +#include "internal/tun-metadata-private.h" +#include "internal/unaligned.h" +#include "internal/util.h" +#include "internal/uuid.h" #include "openvswitch/vlog.h" #include "openvswitch/match.h" #include "odp-netlink-macros.h" -#include "csum.h" +#include "internal/csum.h" VLOG_DEFINE_THIS_MODULE(odp_util); Index: openvswitch-2.17.2/lib/odp-util.h =================================================================== --- openvswitch-2.17.2.orig/lib/odp-util.h +++ openvswitch-2.17.2/lib/odp-util.h @@ -21,14 +21,14 @@ #include #include #include -#include "flow.h" -#include "hash.h" +#include "internal/flow.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/uuid.h" #include "odp-netlink.h" #include "openflow/openflow.h" -#include "util.h" +#include "internal/util.h" struct ds; struct nlattr; Index: openvswitch-2.17.2/lib/ofp-actions.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-actions.c +++ openvswitch-2.17.2/lib/ofp-actions.c @@ -19,15 +19,15 @@ #include #include -#include "bundle.h" -#include "byte-order.h" -#include "colors.h" +#include "internal/bundle.h" +#include "internal/byte-order.h" +#include "internal/colors.h" #include "openvswitch/compiler.h" #include "dummy.h" #include "openvswitch/hmap.h" #include "learn.h" #include "multipath.h" -#include "nx-match.h" +#include "internal/nx-match.h" #include "odp-netlink.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/meta-flow.h" @@ -39,8 +39,8 @@ #include "openvswitch/ofp-table.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "unaligned.h" -#include "util.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "vl-mff-map.h" VLOG_DEFINE_THIS_MODULE(ofp_actions); Index: openvswitch-2.17.2/lib/ofp-bundle.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-bundle.c +++ openvswitch-2.17.2/lib/ofp-bundle.c @@ -22,7 +22,7 @@ #include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_bundle); Index: openvswitch-2.17.2/lib/ofp-connection.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-connection.c +++ openvswitch-2.17.2/lib/ofp-connection.c @@ -16,7 +16,7 @@ #include #include "openvswitch/ofp-connection.h" -#include "byte-order.h" +#include "internal/byte-order.h" #include "openflow/nicira-ext.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-monitor.h" @@ -27,7 +27,7 @@ #include "openvswitch/ofpbuf.h" #include "openvswitch/type-props.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_connection); Index: openvswitch-2.17.2/lib/ofp-ed-props.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-ed-props.c +++ openvswitch-2.17.2/lib/ofp-ed-props.c @@ -21,8 +21,8 @@ #include "openvswitch/ofp-ed-props.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/ofp-parse.h" -#include "util.h" -#include "lib/packets.h" +#include "internal/util.h" +#include "internal/packets.h" enum ofperr Index: openvswitch-2.17.2/lib/ofp-errors.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-errors.c +++ openvswitch-2.17.2/lib/ofp-errors.c @@ -16,7 +16,7 @@ #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openflow/openflow.h" #include "openflow/nicira-ext.h" #include "openvswitch/dynamic-string.h" @@ -25,7 +25,7 @@ #include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_errors); Index: openvswitch-2.17.2/lib/ofp-flow.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-flow.c +++ openvswitch-2.17.2/lib/ofp-flow.c @@ -17,10 +17,10 @@ #include #include "openvswitch/ofp-flow.h" #include -#include "byte-order.h" -#include "colors.h" -#include "flow.h" -#include "nx-match.h" +#include "internal/byte-order.h" +#include "internal/colors.h" +#include "internal/flow.h" +#include "internal/nx-match.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-group.h" #include "openvswitch/ofp-match.h" @@ -31,7 +31,7 @@ #include "openvswitch/ofp-table.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" #include "ox-stat.h" VLOG_DEFINE_THIS_MODULE(ofp_flow); Index: openvswitch-2.17.2/lib/ofp-group.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-group.c +++ openvswitch-2.17.2/lib/ofp-group.c @@ -17,9 +17,9 @@ #include #include "openvswitch/ofp-group.h" #include -#include "byte-order.h" -#include "id-pool.h" -#include "nx-match.h" +#include "internal/byte-order.h" +#include "internal/id-pool.h" +#include "internal/nx-match.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/ofp-msgs.h" @@ -29,7 +29,7 @@ #include "openvswitch/ofp-prop.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_group); Index: openvswitch-2.17.2/lib/ofp-ipfix.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-ipfix.c +++ openvswitch-2.17.2/lib/ofp-ipfix.c @@ -17,12 +17,12 @@ #include #include "openvswitch/ofp-ipfix.h" #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openflow/nicira-ext.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofpbuf.h" -#include "util.h" +#include "internal/util.h" static void ofputil_ipfix_stats_to_reply(const struct ofputil_ipfix_stats *ois, Index: openvswitch-2.17.2/lib/ofp-match.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-match.c +++ openvswitch-2.17.2/lib/ofp-match.c @@ -16,9 +16,9 @@ #include #include "openvswitch/ofp-match.h" -#include "byte-order.h" -#include "flow.h" -#include "nx-match.h" +#include "internal/byte-order.h" +#include "internal/flow.h" +#include "internal/nx-match.h" #include "openvswitch/match.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-msgs.h" Index: openvswitch-2.17.2/lib/ofp-meter.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-meter.c +++ openvswitch-2.17.2/lib/ofp-meter.c @@ -16,8 +16,8 @@ #include #include "openvswitch/ofp-meter.h" -#include "byte-order.h" -#include "nx-match.h" +#include "internal/byte-order.h" +#include "internal/nx-match.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofp-parse.h" Index: openvswitch-2.17.2/lib/ofp-monitor.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-monitor.c +++ openvswitch-2.17.2/lib/ofp-monitor.c @@ -16,9 +16,9 @@ #include #include "openvswitch/ofp-monitor.h" -#include "byte-order.h" -#include "nx-match.h" -#include "ovs-atomic.h" +#include "internal/byte-order.h" +#include "internal/nx-match.h" +#include "openvswitch/ovs-atomic.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-group.h" Index: openvswitch-2.17.2/lib/ofp-msgs.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-msgs.c +++ openvswitch-2.17.2/lib/ofp-msgs.c @@ -15,8 +15,8 @@ */ #include -#include "byte-order.h" -#include "hash.h" +#include "internal/byte-order.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" @@ -24,8 +24,8 @@ #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "ovs-thread.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_msgs); Index: openvswitch-2.17.2/lib/ofp-packet.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-packet.c +++ openvswitch-2.17.2/lib/ofp-packet.c @@ -17,8 +17,8 @@ #include #include "openvswitch/ofp-packet.h" #include -#include "dp-packet.h" -#include "nx-match.h" +#include "internal/dp-packet.h" +#include "internal/nx-match.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-msgs.h" @@ -29,8 +29,8 @@ #include "openvswitch/ofp-table.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" -#include "uuid.h" +#include "internal/util.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(ofp_packet); Index: openvswitch-2.17.2/lib/ofp-parse.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-parse.c +++ openvswitch-2.17.2/lib/ofp-parse.c @@ -17,16 +17,16 @@ #include #include "openvswitch/ofp-parse.h" #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/match.h" #include "openvswitch/meta-flow.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-flow.h" #include "openvswitch/ofp-match.h" #include "openvswitch/ofp-table.h" -#include "packets.h" -#include "socket-util.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/socket-util.h" +#include "internal/util.h" /* Parses 'str' as an 8-bit unsigned integer into '*valuep'. * Index: openvswitch-2.17.2/lib/ofp-port.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-port.c +++ openvswitch-2.17.2/lib/ofp-port.c @@ -17,8 +17,8 @@ #include #include "openvswitch/ofp-port.h" #include -#include "byte-order.h" -#include "flow.h" +#include "internal/byte-order.h" +#include "internal/flow.h" #include "openflow/intel-ext.h" #include "openvswitch/json.h" #include "openvswitch/ofp-errors.h" Index: openvswitch-2.17.2/lib/ofp-print.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-print.c +++ openvswitch-2.17.2/lib/ofp-print.c @@ -27,16 +27,16 @@ #include #include -#include "bundle.h" -#include "byte-order.h" -#include "colors.h" +#include "internal/bundle.h" +#include "internal/byte-order.h" +#include "internal/colors.h" #include "openvswitch/compiler.h" -#include "dp-packet.h" -#include "flow.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" #include "learn.h" #include "multipath.h" -#include "netdev.h" -#include "nx-match.h" +#include "internal/netdev.h" +#include "internal/nx-match.h" #include "odp-util.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" @@ -59,10 +59,10 @@ #include "openvswitch/ofp-util.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/type-props.h" -#include "packets.h" -#include "unaligned.h" -#include "util.h" -#include "uuid.h" +#include "internal/packets.h" +#include "internal/unaligned.h" +#include "internal/util.h" +#include "internal/uuid.h" static void ofp_print_error(struct ds *, enum ofperr); Index: openvswitch-2.17.2/lib/ofp-prop.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-prop.c +++ openvswitch-2.17.2/lib/ofp-prop.c @@ -16,13 +16,13 @@ #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-prop.h" #include "openvswitch/vlog.h" -#include "util.h" -#include "uuid.h" +#include "internal/util.h" +#include "internal/uuid.h" struct ofp_prop_be16 { ovs_be16 type; Index: openvswitch-2.17.2/lib/ofp-protocol.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-protocol.c +++ openvswitch-2.17.2/lib/ofp-protocol.c @@ -22,7 +22,7 @@ #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_protocol); Index: openvswitch-2.17.2/lib/ofp-queue.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-queue.c +++ openvswitch-2.17.2/lib/ofp-queue.c @@ -16,15 +16,15 @@ #include #include "openvswitch/ofp-queue.h" -#include "byte-order.h" -#include "flow.h" +#include "internal/byte-order.h" +#include "internal/flow.h" #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofp-print.h" #include "openvswitch/ofp-port.h" #include "openvswitch/ofp-prop.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_queue); Index: openvswitch-2.17.2/lib/ofp-switch.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-switch.c +++ openvswitch-2.17.2/lib/ofp-switch.c @@ -16,14 +16,14 @@ #include #include "openvswitch/ofp-switch.h" -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofp-port.h" #include "openvswitch/ofp-print.h" -#include "util.h" +#include "internal/util.h" /* ofputil_switch_features */ Index: openvswitch-2.17.2/lib/ofp-table.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-table.c +++ openvswitch-2.17.2/lib/ofp-table.c @@ -16,8 +16,8 @@ #include #include "openvswitch/ofp-table.h" -#include "bitmap.h" -#include "nx-match.h" +#include "internal/bitmap.h" +#include "internal/nx-match.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" #include "openvswitch/ofp-actions.h" @@ -26,7 +26,7 @@ #include "openvswitch/ofp-prop.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofp_table); Index: openvswitch-2.17.2/lib/ofp-util.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-util.c +++ openvswitch-2.17.2/lib/ofp-util.c @@ -23,15 +23,15 @@ #include #include #include -#include "bitmap.h" -#include "bundle.h" -#include "byte-order.h" -#include "classifier.h" +#include "internal/bitmap.h" +#include "internal/bundle.h" +#include "internal/byte-order.h" +#include "internal/classifier.h" #include "learn.h" #include "multipath.h" -#include "netdev.h" -#include "nx-match.h" -#include "id-pool.h" +#include "internal/netdev.h" +#include "internal/nx-match.h" +#include "internal/id-pool.h" #include "openflow/netronome-ext.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" @@ -45,12 +45,12 @@ #include "openvswitch/type-props.h" #include "openvswitch/vlog.h" #include "openflow/intel-ext.h" -#include "packets.h" -#include "random.h" -#include "tun-metadata.h" -#include "unaligned.h" -#include "util.h" -#include "uuid.h" +#include "internal/packets.h" +#include "internal/random.h" +#include "internal/tun-metadata-private.h" +#include "internal/unaligned.h" +#include "internal/util.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(ofp_util); Index: openvswitch-2.17.2/lib/ofp-version-opt.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-version-opt.c +++ openvswitch-2.17.2/lib/ofp-version-opt.c @@ -2,7 +2,7 @@ #include "openvswitch/dynamic-string.h" #include "openvswitch/ofp-protocol.h" #include "ofp-version-opt.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" static uint32_t allowed_versions = 0; Index: openvswitch-2.17.2/lib/ofp-version-opt.h =================================================================== --- openvswitch-2.17.2.orig/lib/ofp-version-opt.h +++ openvswitch-2.17.2/lib/ofp-version-opt.h @@ -2,7 +2,7 @@ #define OFP_VERSION_H 1 #include -#include "util.h" +#include "internal/util.h" #define OFP_VERSION_LONG_OPTIONS \ {"version", no_argument, NULL, 'V'}, \ Index: openvswitch-2.17.2/lib/ofpbuf.c =================================================================== --- openvswitch-2.17.2.orig/lib/ofpbuf.c +++ openvswitch-2.17.2/lib/ofpbuf.c @@ -19,7 +19,7 @@ #include #include #include "openvswitch/dynamic-string.h" -#include "util.h" +#include "internal/util.h" static void ofpbuf_init__(struct ofpbuf *b, size_t allocated, enum ofpbuf_source source) Index: openvswitch-2.17.2/lib/ovs-lldp.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-lldp.c +++ openvswitch-2.17.2/lib/ovs-lldp.c @@ -35,17 +35,17 @@ #include #include #include "openvswitch/dynamic-string.h" -#include "flow.h" +#include "internal/flow.h" #include "openvswitch/list.h" #include "lldp/lldpd.h" #include "lldp/lldpd-structs.h" -#include "netdev.h" +#include "internal/netdev.h" #include "openvswitch/types.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "smap.h" -#include "unixctl.h" -#include "util.h" +#include "internal/smap.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovs_lldp); Index: openvswitch-2.17.2/lib/ovs-lldp.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-lldp.h +++ openvswitch-2.17.2/lib/ovs-lldp.h @@ -20,13 +20,13 @@ #define OVS_LLDP_H #include -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" #include "lldp/lldpd.h" -#include "ovs-atomic.h" -#include "packets.h" -#include "timer.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/packets.h" +#include "internal/timer.h" /* Transmit every LLDPD_TX_INTERVAL seconds. */ #define LLDP_DEFAULT_TRANSMIT_INTERVAL_MS (LLDPD_TX_INTERVAL * 1000) Index: openvswitch-2.17.2/lib/ovs-numa.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-numa.c +++ openvswitch-2.17.2/lib/ovs-numa.c @@ -15,7 +15,7 @@ */ #include -#include "ovs-numa.h" +#include "openvswitch/ovs-numa.h" #include #include @@ -27,12 +27,12 @@ #include #endif /* __linux__ */ -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ovs_numa); Index: openvswitch-2.17.2/lib/ovs-rcu.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-rcu.c +++ openvswitch-2.17.2/lib/ovs-rcu.c @@ -16,16 +16,16 @@ #include #include -#include "ovs-rcu.h" -#include "fatal-signal.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/fatal-signal.h" #include "guarded-list.h" -#include "latch.h" +#include "internal/latch.h" #include "openvswitch/list.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" -#include "seq.h" -#include "timeval.h" -#include "util.h" +#include "internal/seq.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovs_rcu); Index: openvswitch-2.17.2/lib/ovs-replay.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-replay.c +++ openvswitch-2.17.2/lib/ovs-replay.c @@ -22,10 +22,10 @@ #include #include #include -#include "dirs.h" -#include "ovs-atomic.h" +#include "internal/dirs.h" +#include "openvswitch/ovs-atomic.h" #include "ovs-replay.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovs_replay); Index: openvswitch-2.17.2/lib/ovs-router.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-router.c +++ openvswitch-2.17.2/lib/ovs-router.c @@ -30,21 +30,21 @@ #include #include -#include "classifier.h" -#include "colors.h" +#include "internal/classifier.h" +#include "internal/command-line.h" #include "openvswitch/compiler.h" #include "dpif.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/dynamic-string.h" -#include "netdev.h" -#include "packets.h" -#include "seq.h" -#include "ovs-thread.h" +#include "internal/netdev.h" +#include "internal/packets.h" +#include "internal/seq.h" +#include "openvswitch/ovs-thread.h" #include "route-table.h" #include "tnl-ports.h" -#include "unixctl.h" -#include "util.h" -#include "unaligned.h" +#include "internal/unixctl.h" +#include "internal/util.h" +#include "internal/unaligned.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovs_router); Index: openvswitch-2.17.2/lib/ovs-router.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-router.h +++ openvswitch-2.17.2/lib/ovs-router.h @@ -20,7 +20,7 @@ #include #include -#include "util.h" +#include "internal/util.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/lib/ovs-thread.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-thread.c +++ openvswitch-2.17.2/lib/ovs-thread.c @@ -15,7 +15,7 @@ */ #include -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include #include #ifndef _WIN32 @@ -24,14 +24,14 @@ #include #include #include "openvswitch/compiler.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/list.h" -#include "ovs-rcu.h" +#include "openvswitch/ovs-rcu.h" #include "openvswitch/poll-loop.h" -#include "seq.h" -#include "socket-util.h" -#include "util.h" +#include "internal/seq.h" +#include "internal/socket-util.h" +#include "internal/util.h" #ifdef __CHECKER__ /* Omit the definitions in this file because they are somewhat difficult to Index: openvswitch-2.17.2/lib/ovsdb-condition.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-condition.c +++ openvswitch-2.17.2/lib/ovsdb-condition.c @@ -16,8 +16,8 @@ #include #include -#include "ovsdb-error.h" -#include "ovsdb-condition.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-condition.h" struct ovsdb_error * ovsdb_function_from_string(const char *name, enum ovsdb_function *function) Index: openvswitch-2.17.2/lib/ovsdb-cs.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-cs.c +++ openvswitch-2.17.2/lib/ovsdb-cs.c @@ -16,27 +16,27 @@ #include -#include "ovsdb-cs.h" +#include "openvswitch/ovsdb-cs.h" #include -#include "hash.h" -#include "jsonrpc.h" +#include "internal/hash.h" +#include "internal/jsonrpc.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" #include "openvswitch/json.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" #include "openvswitch/vlog.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "ovsdb-session.h" -#include "ovsdb-types.h" -#include "sset.h" -#include "svec.h" -#include "util.h" -#include "uuid.h" +#include "openvswitch/ovsdb-types.h" +#include "internal/sset.h" +#include "internal/svec.h" +#include "internal/util.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(ovsdb_cs); Index: openvswitch-2.17.2/lib/ovsdb-data.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-data.c +++ openvswitch-2.17.2/lib/ovsdb-data.c @@ -15,7 +15,7 @@ #include -#include "ovsdb-data.h" +#include "openvswitch/ovsdb-data.h" #include #include @@ -23,16 +23,16 @@ #include #include "openvswitch/dynamic-string.h" -#include "hash.h" -#include "ovs-thread.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "internal/hash.h" +#include "openvswitch/ovs-thread.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "openvswitch/json.h" #include "openvswitch/shash.h" -#include "smap.h" -#include "sort.h" +#include "internal/smap.h" +#include "internal/sort.h" #include "unicode.h" -#include "util.h" +#include "internal/util.h" static struct json * wrap_json(const char *name, struct json *wrapped) Index: openvswitch-2.17.2/lib/ovsdb-error.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-error.c +++ openvswitch-2.17.2/lib/ovsdb-error.c @@ -15,14 +15,14 @@ #include -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include #include "backtrace.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovsdb_error); Index: openvswitch-2.17.2/lib/ovsdb-idl.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-idl.c +++ openvswitch-2.17.2/lib/ovsdb-idl.c @@ -16,37 +16,37 @@ #include -#include "ovsdb-idl.h" +#include "openvswitch/ovsdb-idl.h" #include #include #include #include -#include "bitmap.h" -#include "coverage.h" -#include "hash.h" +#include "internal/bitmap.h" +#include "internal/coverage.h" +#include "internal/hash.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/json.h" -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include "ovsdb/ovsdb.h" #include "ovsdb/table.h" -#include "ovsdb-cs.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "ovsdb-idl-provider.h" -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-cs.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-idl-provider.h" +#include "openvswitch/ovsdb-parser.h" #include "ovsdb-server-idl.h" #include "ovsdb-session.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "skiplist.h" -#include "simap.h" -#include "sset.h" -#include "svec.h" -#include "util.h" -#include "uuid.h" +#include "internal/skiplist.h" +#include "internal/simap.h" +#include "internal/sset.h" +#include "internal/svec.h" +#include "internal/util.h" +#include "internal/uuid.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovsdb_idl); Index: openvswitch-2.17.2/lib/ovsdb-map-op.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-map-op.c +++ openvswitch-2.17.2/lib/ovsdb-map-op.c @@ -15,10 +15,10 @@  */ #include -#include "ovsdb-map-op.h" -#include "util.h" +#include "openvswitch/ovsdb-map-op.h" +#include "internal/util.h" #include "openvswitch/hmap.h" -#include "hash.h" +#include "internal/hash.h" /* Map Operation: a Partial Map Update */ struct map_op { Index: openvswitch-2.17.2/lib/ovsdb-parser.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-parser.c +++ openvswitch-2.17.2/lib/ovsdb-parser.c @@ -15,12 +15,12 @@ #include -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-parser.h" #include #include -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" void ovsdb_parser_init(struct ovsdb_parser *parser, const struct json *json, Index: openvswitch-2.17.2/lib/ovsdb-session.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-session.c +++ openvswitch-2.17.2/lib/ovsdb-session.c @@ -18,9 +18,9 @@ #include #include #include -#include "svec.h" -#include "util.h" -#include "uuid.h" +#include "internal/svec.h" +#include "internal/util.h" +#include "internal/uuid.h" static const char * next_remote(const char *s) Index: openvswitch-2.17.2/lib/ovsdb-set-op.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-set-op.c +++ openvswitch-2.17.2/lib/ovsdb-set-op.c @@ -16,8 +16,8 @@ */ #include -#include "ovsdb-set-op.h" -#include "util.h" +#include "openvswitch/ovsdb-set-op.h" +#include "internal/util.h" /* Set Operation: a Partial Set Update */ struct set_op { Index: openvswitch-2.17.2/lib/ovsdb-types.c =================================================================== --- openvswitch-2.17.2.orig/lib/ovsdb-types.c +++ openvswitch-2.17.2/lib/ovsdb-types.c @@ -15,18 +15,18 @@ #include -#include "ovsdb-types.h" +#include "openvswitch/ovsdb-types.h" #include #include #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "ovs-thread.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" +#include "internal/util.h" const struct ovsdb_type ovsdb_type_integer = OVSDB_TYPE_SCALAR_INITIALIZER(OVSDB_BASE_INTEGER_INIT); Index: openvswitch-2.17.2/lib/ox-stat.c =================================================================== --- openvswitch-2.17.2.orig/lib/ox-stat.c +++ openvswitch-2.17.2/lib/ox-stat.c @@ -16,12 +16,12 @@ #include #include "ox-stat.h" -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/ofp-errors.h" #include "openvswitch/compiler.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "unaligned.h" +#include "internal/unaligned.h" VLOG_DEFINE_THIS_MODULE(ox_stat); Index: openvswitch-2.17.2/lib/packets.c =================================================================== --- openvswitch-2.17.2.orig/lib/packets.c +++ openvswitch-2.17.2/lib/packets.c @@ -15,7 +15,7 @@ */ #include -#include "packets.h" +#include "internal/packets.h" #include #include #include @@ -24,16 +24,16 @@ #include #include #include -#include "byte-order.h" -#include "csum.h" -#include "crc32c.h" -#include "flow.h" +#include "internal/byte-order.h" +#include "internal/csum.h" +#include "internal/crc32c.h" +#include "internal/flow.h" #include "openvswitch/hmap.h" #include "openvswitch/dynamic-string.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "odp-util.h" -#include "dp-packet.h" -#include "unaligned.h" +#include "internal/dp-packet.h" +#include "internal/unaligned.h" const struct in6_addr in6addr_exact = IN6ADDR_EXACT_INIT; const struct in6_addr in6addr_all_hosts = IN6ADDR_ALL_HOSTS_INIT; Index: openvswitch-2.17.2/lib/pcap-file.c =================================================================== --- openvswitch-2.17.2.orig/lib/pcap-file.c +++ openvswitch-2.17.2/lib/pcap-file.c @@ -21,15 +21,15 @@ #include #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "openvswitch/compiler.h" -#include "dp-packet.h" -#include "flow.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" #include "openvswitch/hmap.h" -#include "packets.h" -#include "timeval.h" -#include "unaligned.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(pcap); Index: openvswitch-2.17.2/lib/perf-counter.c =================================================================== --- openvswitch-2.17.2.orig/lib/perf-counter.c +++ openvswitch-2.17.2/lib/perf-counter.c @@ -29,7 +29,7 @@ #include "openvswitch/dynamic-string.h" #include "perf-counter.h" #include "openvswitch/shash.h" -#include "util.h" +#include "internal/util.h" static struct shash perf_counters = SHASH_INITIALIZER(&perf_counters); static int fd__ = 0; Index: openvswitch-2.17.2/lib/poll-loop.c =================================================================== --- openvswitch-2.17.2.orig/lib/poll-loop.c +++ openvswitch-2.17.2/lib/poll-loop.c @@ -21,17 +21,17 @@ #include #include #include -#include "coverage.h" +#include "internal/coverage.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/list.h" -#include "ovs-thread.h" -#include "seq.h" -#include "socket-util.h" -#include "timeval.h" +#include "openvswitch/ovs-thread.h" +#include "internal/seq.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" #include "openvswitch/vlog.h" #include "openvswitch/hmap.h" -#include "hash.h" +#include "internal/hash.h" VLOG_DEFINE_THIS_MODULE(poll_loop); Index: openvswitch-2.17.2/lib/process.c =================================================================== --- openvswitch-2.17.2.orig/lib/process.c +++ openvswitch-2.17.2/lib/process.c @@ -15,7 +15,7 @@ */ #include -#include "process.h" +#include "internal/process.h" #include #include #include @@ -25,16 +25,16 @@ #include #include #include -#include "coverage.h" +#include "internal/coverage.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/list.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" #include "signals.h" -#include "socket-util.h" -#include "timeval.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(process); Index: openvswitch-2.17.2/lib/pvector.c =================================================================== --- openvswitch-2.17.2.orig/lib/pvector.c +++ openvswitch-2.17.2/lib/pvector.c @@ -15,7 +15,7 @@ */ #include -#include "pvector.h" +#include "internal/pvector.h" /* Writers will preallocate space for some entries at the end to avoid future * reallocations. */ Index: openvswitch-2.17.2/lib/random.c =================================================================== --- openvswitch-2.17.2.orig/lib/random.c +++ openvswitch-2.17.2/lib/random.c @@ -15,17 +15,17 @@ */ #include -#include "random.h" +#include "internal/random.h" #include #include #include #include "entropy.h" -#include "hash.h" -#include "ovs-thread.h" -#include "timeval.h" -#include "util.h" +#include "internal/hash.h" +#include "openvswitch/ovs-thread.h" +#include "internal/timeval.h" +#include "internal/util.h" /* This is the 32-bit PRNG recommended in G. Marsaglia, "Xorshift RNGs", * _Journal of Statistical Software_ 8:14 (July 2003). According to the paper, Index: openvswitch-2.17.2/lib/rconn.c =================================================================== --- openvswitch-2.17.2.orig/lib/rconn.c +++ openvswitch-2.17.2/lib/rconn.c @@ -20,7 +20,7 @@ #include #include #include -#include "coverage.h" +#include "internal/coverage.h" #include "openflow/openflow.h" #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofp-util.h" @@ -29,10 +29,10 @@ #include "openvswitch/vlog.h" #include "openvswitch/poll-loop.h" #include "sat-math.h" -#include "stream.h" -#include "timeval.h" -#include "util.h" -#include "ovs-thread.h" +#include "internal/stream.h" +#include "internal/timeval.h" +#include "internal/util.h" +#include "openvswitch/ovs-thread.h" VLOG_DEFINE_THIS_MODULE(rconn); Index: openvswitch-2.17.2/lib/reconnect.c =================================================================== --- openvswitch-2.17.2.orig/lib/reconnect.c +++ openvswitch-2.17.2/lib/reconnect.c @@ -20,7 +20,7 @@ #include #include "openvswitch/poll-loop.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(reconnect); Index: openvswitch-2.17.2/lib/route-table-bsd.c =================================================================== --- openvswitch-2.17.2.orig/lib/route-table-bsd.c +++ openvswitch-2.17.2/lib/route-table-bsd.c @@ -32,9 +32,9 @@ #include #include "ovs-router.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(route_table_bsd); Index: openvswitch-2.17.2/lib/route-table.c =================================================================== --- openvswitch-2.17.2.orig/lib/route-table.c +++ openvswitch-2.17.2/lib/route-table.c @@ -26,14 +26,14 @@ #include #include -#include "hash.h" -#include "netdev.h" -#include "netlink.h" +#include "internal/hash.h" +#include "internal/netdev.h" +#include "internal/netlink.h" #include "netlink-notifier.h" #include "netlink-socket.h" #include "openvswitch/ofpbuf.h" #include "ovs-router.h" -#include "packets.h" +#include "internal/packets.h" #include "rtnetlink.h" #include "tnl-ports.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/rstp-common.h =================================================================== --- openvswitch-2.17.2.orig/lib/rstp-common.h +++ openvswitch-2.17.2/lib/rstp-common.h @@ -35,8 +35,8 @@ #include #include "openvswitch/hmap.h" #include "openvswitch/list.h" -#include "ovs-atomic.h" -#include "packets.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/packets.h" enum admin_port_state { RSTP_ADMIN_BRIDGE_PORT_STATE_DISABLED = 0, Index: openvswitch-2.17.2/lib/rstp-state-machines.c =================================================================== --- openvswitch-2.17.2.orig/lib/rstp-state-machines.c +++ openvswitch-2.17.2/lib/rstp-state-machines.c @@ -36,14 +36,14 @@ #include #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "connectivity.h" #include "openvswitch/ofpbuf.h" -#include "dp-packet.h" -#include "packets.h" -#include "seq.h" -#include "unixctl.h" -#include "util.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" +#include "internal/seq.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(rstp_sm); Index: openvswitch-2.17.2/lib/rstp.c =================================================================== --- openvswitch-2.17.2.orig/lib/rstp.c +++ openvswitch-2.17.2/lib/rstp.c @@ -37,15 +37,15 @@ #include #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "connectivity.h" #include "openvswitch/ofpbuf.h" #include "ofproto/ofproto.h" -#include "dp-packet.h" -#include "packets.h" -#include "seq.h" -#include "unixctl.h" -#include "util.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" +#include "internal/seq.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(rstp); Index: openvswitch-2.17.2/lib/rstp.h =================================================================== --- openvswitch-2.17.2.orig/lib/rstp.h +++ openvswitch-2.17.2/lib/rstp.h @@ -34,7 +34,7 @@ #include #include #include "openvswitch/compiler.h" -#include "util.h" +#include "internal/util.h" /* Thread Safety: Callers passing in RSTP and RSTP port object * pointers must hold a reference to the passed object to ensure that Index: openvswitch-2.17.2/lib/rtbsd.c =================================================================== --- openvswitch-2.17.2.orig/lib/rtbsd.c +++ openvswitch-2.17.2/lib/rtbsd.c @@ -25,8 +25,8 @@ #include #include -#include "coverage.h" -#include "socket-util.h" +#include "internal/coverage.h" +#include "internal/socket-util.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/rtnetlink.c =================================================================== --- openvswitch-2.17.2.orig/lib/rtnetlink.c +++ openvswitch-2.17.2/lib/rtnetlink.c @@ -22,10 +22,10 @@ #include #include -#include "netlink.h" +#include "internal/netlink.h" #include "netlink-notifier.h" #include "openvswitch/ofpbuf.h" -#include "packets.h" +#include "internal/packets.h" #if IFLA_INFO_MAX < 5 #define IFLA_INFO_SLAVE_KIND 4 Index: openvswitch-2.17.2/lib/seq.c =================================================================== --- openvswitch-2.17.2.orig/lib/seq.c +++ openvswitch-2.17.2/lib/seq.c @@ -16,16 +16,16 @@ #include -#include "seq.h" +#include "internal/seq.h" #include -#include "coverage.h" -#include "hash.h" +#include "internal/coverage.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "latch.h" +#include "internal/latch.h" #include "openvswitch/list.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" COVERAGE_DEFINE(seq_change); Index: openvswitch-2.17.2/lib/sflow_agent.c =================================================================== --- openvswitch-2.17.2.orig/lib/sflow_agent.c +++ openvswitch-2.17.2/lib/sflow_agent.c @@ -6,7 +6,7 @@ */ #include "sflow_api.h" -#include "util.h" +#include "internal/util.h" static void * sflAlloc(SFLAgent *agent, size_t bytes); static void sflFree(SFLAgent *agent, void *obj); Index: openvswitch-2.17.2/lib/sha1.c =================================================================== --- openvswitch-2.17.2.orig/lib/sha1.c +++ openvswitch-2.17.2/lib/sha1.c @@ -34,7 +34,7 @@ #include #include #include "openvswitch/compiler.h" -#include "util.h" +#include "internal/util.h" /* a bit faster & bigger, if defined */ #define UNROLL_LOOPS Index: openvswitch-2.17.2/lib/shash.c =================================================================== --- openvswitch-2.17.2.orig/lib/shash.c +++ openvswitch-2.17.2/lib/shash.c @@ -16,7 +16,7 @@ #include #include "openvswitch/shash.h" -#include "hash.h" +#include "internal/hash.h" static struct shash_node *shash_find__(const struct shash *, const char *name, size_t name_len, Index: openvswitch-2.17.2/lib/signals.c =================================================================== --- openvswitch-2.17.2.orig/lib/signals.c +++ openvswitch-2.17.2/lib/signals.c @@ -22,9 +22,9 @@ #include #include #include "openvswitch/poll-loop.h" -#include "socket-util.h" +#include "internal/socket-util.h" #include "openvswitch/type-props.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(signals); Index: openvswitch-2.17.2/lib/simap.c =================================================================== --- openvswitch-2.17.2.orig/lib/simap.c +++ openvswitch-2.17.2/lib/simap.c @@ -15,8 +15,8 @@ */ #include -#include "simap.h" -#include "hash.h" +#include "internal/simap.h" +#include "internal/hash.h" static size_t hash_name(const char *, size_t length); static struct simap_node *simap_find__(const struct simap *, Index: openvswitch-2.17.2/lib/skiplist.c =================================================================== --- openvswitch-2.17.2.orig/lib/skiplist.c +++ openvswitch-2.17.2/lib/skiplist.c @@ -25,9 +25,9 @@ #include #include -#include "skiplist.h" -#include "random.h" -#include "util.h" +#include "internal/skiplist.h" +#include "internal/random.h" +#include "internal/util.h" /* * A maximum height level of 32 should be more than sufficient for Index: openvswitch-2.17.2/lib/smap.c =================================================================== --- openvswitch-2.17.2.orig/lib/smap.c +++ openvswitch-2.17.2/lib/smap.c @@ -13,15 +13,15 @@ * limitations under the License. */ #include -#include "smap.h" +#include "internal/smap.h" #include -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/json.h" -#include "packets.h" -#include "util.h" -#include "uuid.h" +#include "internal/packets.h" +#include "internal/util.h" +#include "internal/uuid.h" static struct smap_node *smap_add__(struct smap *, char *, void *, size_t hash); Index: openvswitch-2.17.2/lib/socket-util-unix.c =================================================================== --- openvswitch-2.17.2.orig/lib/socket-util-unix.c +++ openvswitch-2.17.2/lib/socket-util-unix.c @@ -15,7 +15,7 @@ */ #include -#include "socket-util.h" +#include "internal/socket-util.h" #include #include #include @@ -25,9 +25,9 @@ #include #include #include -#include "fatal-signal.h" -#include "random.h" -#include "util.h" +#include "internal/fatal-signal.h" +#include "internal/random.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(socket_util_unix); Index: openvswitch-2.17.2/lib/socket-util.c =================================================================== --- openvswitch-2.17.2.orig/lib/socket-util.c +++ openvswitch-2.17.2/lib/socket-util.c @@ -15,7 +15,7 @@ */ #include -#include "socket-util.h" +#include "internal/socket-util.h" #include #include #include @@ -36,16 +36,16 @@ #include #include #include "openvswitch/dynamic-string.h" -#include "ovs-thread.h" -#include "packets.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" #ifdef __linux__ #include #endif #ifdef HAVE_NETLINK -#include "netlink-protocol.h" +#include "internal/netlink-protocol.h" #include "netlink-socket.h" #endif #include "dns-resolve.h" Index: openvswitch-2.17.2/lib/sort.c =================================================================== --- openvswitch-2.17.2.orig/lib/sort.c +++ openvswitch-2.17.2/lib/sort.c @@ -15,9 +15,9 @@ #include -#include "sort.h" +#include "internal/sort.h" -#include "random.h" +#include "internal/random.h" static size_t partition(size_t p, size_t r, Index: openvswitch-2.17.2/lib/sset.c =================================================================== --- openvswitch-2.17.2.orig/lib/sset.c +++ openvswitch-2.17.2/lib/sset.c @@ -16,10 +16,10 @@ #include -#include "sset.h" +#include "internal/sset.h" #include "openvswitch/dynamic-string.h" -#include "hash.h" +#include "internal/hash.h" static uint32_t hash_name__(const char *name, size_t length) Index: openvswitch-2.17.2/lib/stopwatch.c =================================================================== --- openvswitch-2.17.2.orig/lib/stopwatch.c +++ openvswitch-2.17.2/lib/stopwatch.c @@ -15,17 +15,17 @@ #include -#include "stopwatch.h" +#include "internal/stopwatch.h" #include "openvswitch/shash.h" #include "openvswitch/vlog.h" -#include "unixctl.h" +#include "internal/unixctl.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/poll-loop.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include -#include "socket-util.h" -#include "util.h" -#include "latch.h" +#include "internal/socket-util.h" +#include "internal/util.h" +#include "internal/latch.h" #include "guarded-list.h" VLOG_DEFINE_THIS_MODULE(stopwatch); Index: openvswitch-2.17.2/lib/stp.c =================================================================== --- openvswitch-2.17.2.orig/lib/stp.c +++ openvswitch-2.17.2/lib/stp.c @@ -25,15 +25,15 @@ #include #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "connectivity.h" #include "openvswitch/ofpbuf.h" -#include "ovs-atomic.h" -#include "dp-packet.h" -#include "packets.h" -#include "seq.h" -#include "unixctl.h" -#include "util.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" +#include "internal/seq.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(stp); Index: openvswitch-2.17.2/lib/stp.h =================================================================== --- openvswitch-2.17.2.orig/lib/stp.h +++ openvswitch-2.17.2/lib/stp.h @@ -23,7 +23,7 @@ #include #include #include "openvswitch/compiler.h" -#include "util.h" +#include "internal/util.h" struct dp_packet; Index: openvswitch-2.17.2/lib/stream-fd.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream-fd.c +++ openvswitch-2.17.2/lib/stream-fd.c @@ -23,12 +23,12 @@ #include #include #include -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/poll-loop.h" -#include "socket-util.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/util.h" #include "stream-provider.h" -#include "stream.h" +#include "internal/stream.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(stream_fd); Index: openvswitch-2.17.2/lib/stream-nossl.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream-nossl.c +++ openvswitch-2.17.2/lib/stream-nossl.c @@ -15,7 +15,7 @@ */ #include -#include "stream-ssl.h" +#include "internal/stream-ssl.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(stream_nossl); Index: openvswitch-2.17.2/lib/stream-provider.h =================================================================== --- openvswitch-2.17.2.orig/lib/stream-provider.h +++ openvswitch-2.17.2/lib/stream-provider.h @@ -19,7 +19,7 @@ #include #include "ovs-replay.h" -#include "stream.h" +#include "internal/stream.h" /* Active stream connection. */ Index: openvswitch-2.17.2/lib/stream-replay.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream-replay.c +++ openvswitch-2.17.2/lib/stream-replay.c @@ -23,11 +23,11 @@ #include #include #include -#include "ovs-atomic.h" +#include "openvswitch/ovs-atomic.h" #include "ovs-replay.h" -#include "util.h" +#include "internal/util.h" #include "stream-provider.h" -#include "stream.h" +#include "internal/stream.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/stream-ssl.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream-ssl.c +++ openvswitch-2.17.2/lib/stream-ssl.c @@ -15,8 +15,8 @@ */ #include -#include "stream-ssl.h" -#include "dhparams.h" +#include "internal/stream-ssl.h" +#include "internal/dhparams.h" #include #include #include @@ -32,19 +32,19 @@ #include #include #include -#include "coverage.h" +#include "internal/coverage.h" #include "openvswitch/dynamic-string.h" #include "entropy.h" #include "openvswitch/ofpbuf.h" #include "openflow/openflow.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "socket-util.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/util.h" #include "stream-provider.h" -#include "stream.h" -#include "timeval.h" +#include "internal/stream.h" +#include "internal/timeval.h" #include "openvswitch/vlog.h" #ifdef _WIN32 Index: openvswitch-2.17.2/lib/stream-tcp.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream-tcp.c +++ openvswitch-2.17.2/lib/stream-tcp.c @@ -15,7 +15,7 @@ */ #include -#include "stream.h" +#include "internal/stream.h" #include #include #include @@ -26,9 +26,9 @@ #include #include #include "openvswitch/dynamic-string.h" -#include "packets.h" -#include "socket-util.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/socket-util.h" +#include "internal/util.h" #include "stream-provider.h" #include "stream-fd.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/stream-unix.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream-unix.c +++ openvswitch-2.17.2/lib/stream-unix.c @@ -15,7 +15,7 @@ */ #include -#include "stream.h" +#include "internal/stream.h" #include #include #include @@ -26,12 +26,12 @@ #include #include #include -#include "ovs-atomic.h" -#include "packets.h" +#include "openvswitch/ovs-atomic.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "socket-util.h" -#include "dirs.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/dirs.h" +#include "internal/util.h" #include "stream-provider.h" #include "stream-fd.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/stream-windows.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream-windows.c +++ openvswitch-2.17.2/lib/stream-windows.c @@ -21,9 +21,9 @@ #include #include #include "openvswitch/poll-loop.h" -#include "dirs.h" -#include "fatal-signal.h" -#include "util.h" +#include "internal/dirs.h" +#include "internal/fatal-signal.h" +#include "internal/util.h" #include "stream-provider.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/stream.c =================================================================== --- openvswitch-2.17.2.orig/lib/stream.c +++ openvswitch-2.17.2/lib/stream.c @@ -23,10 +23,10 @@ #include #include #include -#include "coverage.h" -#include "fatal-signal.h" -#include "flow.h" -#include "jsonrpc.h" +#include "internal/coverage.h" +#include "internal/fatal-signal.h" +#include "internal/flow.h" +#include "internal/jsonrpc.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" #include "openvswitch/dynamic-string.h" @@ -34,12 +34,12 @@ #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" #include "ovs-replay.h" -#include "ovs-thread.h" -#include "packets.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "random.h" -#include "socket-util.h" -#include "util.h" +#include "internal/random.h" +#include "internal/socket-util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(stream); Index: openvswitch-2.17.2/lib/string.c =================================================================== --- openvswitch-2.17.2.orig/lib/string.c +++ openvswitch-2.17.2/lib/string.c @@ -18,7 +18,7 @@ #include #include -#include "util.h" +#include "internal/util.h" #ifndef HAVE_STRNLEN size_t Index: openvswitch-2.17.2/lib/strsep.c =================================================================== --- openvswitch-2.17.2.orig/lib/strsep.c +++ openvswitch-2.17.2/lib/strsep.c @@ -28,7 +28,7 @@ */ #include -#include "util.h" +#include "internal/util.h" /* * Get next token from string *stringp, where tokens are possibly-empty Index: openvswitch-2.17.2/lib/svec.c =================================================================== --- openvswitch-2.17.2.orig/lib/svec.c +++ openvswitch-2.17.2/lib/svec.c @@ -15,13 +15,13 @@ */ #include -#include "svec.h" +#include "internal/svec.h" #include #include #include #include "openvswitch/dynamic-string.h" -#include "random.h" -#include "util.h" +#include "internal/random.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(svec); Index: openvswitch-2.17.2/lib/syslog-direct.c =================================================================== --- openvswitch-2.17.2.orig/lib/syslog-direct.c +++ openvswitch-2.17.2/lib/syslog-direct.c @@ -22,9 +22,9 @@ #include "openvswitch/compiler.h" #include "openvswitch/dynamic-string.h" -#include "socket-util.h" +#include "internal/socket-util.h" #include "syslog-provider.h" -#include "util.h" +#include "internal/util.h" #define FACILITY_MASK 0x03f8 Index: openvswitch-2.17.2/lib/syslog-libc.c =================================================================== --- openvswitch-2.17.2.orig/lib/syslog-libc.c +++ openvswitch-2.17.2/lib/syslog-libc.c @@ -23,9 +23,9 @@ #include "openvswitch/compiler.h" #include "openvswitch/dynamic-string.h" -#include "socket-util.h" +#include "internal/socket-util.h" #include "syslog-provider.h" -#include "util.h" +#include "internal/util.h" static void syslog_libc_open(struct syslogger *this, int facility); Index: openvswitch-2.17.2/lib/syslog-null.c =================================================================== --- openvswitch-2.17.2.orig/lib/syslog-null.c +++ openvswitch-2.17.2/lib/syslog-null.c @@ -19,7 +19,7 @@ #include "openvswitch/compiler.h" #include "syslog-provider.h" -#include "util.h" +#include "internal/util.h" static void syslog_null_open(struct syslogger *this, int facility); static void syslog_null_log(struct syslogger *this, int pri, const char *msg); Index: openvswitch-2.17.2/lib/table.c =================================================================== --- openvswitch-2.17.2.orig/lib/table.c +++ openvswitch-2.17.2/lib/table.c @@ -16,14 +16,14 @@ #include -#include "table.h" +#include "internal/table.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "timeval.h" -#include "util.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "internal/timeval.h" +#include "internal/util.h" struct column { char *heading; Index: openvswitch-2.17.2/lib/tc.c =================================================================== --- openvswitch-2.17.2.orig/lib/tc.c +++ openvswitch-2.17.2/lib/tc.c @@ -35,15 +35,15 @@ #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "netlink-socket.h" -#include "netlink.h" +#include "internal/netlink.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/util.h" #include "openvswitch/vlog.h" -#include "packets.h" -#include "timeval.h" -#include "unaligned.h" +#include "internal/packets.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" #define MAX_PEDIT_OFFSETS 32 Index: openvswitch-2.17.2/lib/timer.c =================================================================== --- openvswitch-2.17.2.orig/lib/timer.c +++ openvswitch-2.17.2/lib/timer.c @@ -16,10 +16,10 @@ #include -#include "timer.h" +#include "internal/timer.h" #include "openvswitch/poll-loop.h" -#include "timeval.h" +#include "internal/timeval.h" /* Returns the number of milliseconds until 'timer' expires. */ long long int Index: openvswitch-2.17.2/lib/timeval.c =================================================================== --- openvswitch-2.17.2.orig/lib/timeval.c +++ openvswitch-2.17.2/lib/timeval.c @@ -15,7 +15,7 @@ */ #include -#include "timeval.h" +#include "internal/timeval.h" #include #include #include @@ -25,18 +25,18 @@ #include #include #include -#include "coverage.h" +#include "internal/coverage.h" #include "dummy.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" #include "signals.h" -#include "seq.h" -#include "unixctl.h" -#include "util.h" +#include "internal/seq.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(timeval); Index: openvswitch-2.17.2/lib/tnl-neigh-cache.c =================================================================== --- openvswitch-2.17.2.orig/lib/tnl-neigh-cache.c +++ openvswitch-2.17.2/lib/tnl-neigh-cache.c @@ -24,24 +24,24 @@ #include #include -#include "bitmap.h" -#include "cmap.h" -#include "coverage.h" +#include "internal/bitmap.h" +#include "internal/cmap.h" +#include "internal/coverage.h" #include "dpif-netdev.h" #include "openvswitch/dynamic-string.h" #include "errno.h" -#include "flow.h" -#include "netdev.h" -#include "ovs-atomic.h" -#include "ovs-thread.h" -#include "packets.h" +#include "internal/flow.h" +#include "internal/netdev.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "seq.h" -#include "socket-util.h" -#include "timeval.h" -#include "unaligned.h" -#include "unixctl.h" -#include "util.h" +#include "internal/seq.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/tnl-neigh-cache.h =================================================================== --- openvswitch-2.17.2.orig/lib/tnl-neigh-cache.h +++ openvswitch-2.17.2/lib/tnl-neigh-cache.h @@ -26,10 +26,10 @@ #include #include -#include "flow.h" -#include "netdev.h" -#include "packets.h" -#include "util.h" +#include "internal/flow.h" +#include "internal/netdev.h" +#include "internal/packets.h" +#include "internal/util.h" int tnl_neigh_snoop(const struct flow *flow, struct flow_wildcards *wc, const char dev_name[IFNAMSIZ], bool allow_update); Index: openvswitch-2.17.2/lib/tnl-ports.c =================================================================== --- openvswitch-2.17.2.orig/lib/tnl-ports.c +++ openvswitch-2.17.2/lib/tnl-ports.c @@ -22,16 +22,16 @@ #include #include -#include "classifier.h" +#include "internal/classifier.h" #include "openvswitch/dynamic-string.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/list.h" -#include "netdev.h" +#include "internal/netdev.h" #include "openvswitch/ofpbuf.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "odp-util.h" -#include "unixctl.h" -#include "util.h" +#include "internal/unixctl.h" +#include "internal/util.h" static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER; static struct classifier cls; /* Tunnel ports. */ Index: openvswitch-2.17.2/lib/tnl-ports.h =================================================================== --- openvswitch-2.17.2.orig/lib/tnl-ports.h +++ openvswitch-2.17.2/lib/tnl-ports.h @@ -20,9 +20,9 @@ #include #include -#include "flow.h" -#include "packets.h" -#include "util.h" +#include "internal/flow.h" +#include "internal/packets.h" +#include "internal/util.h" odp_port_t tnl_port_map_lookup(struct flow *flow, struct flow_wildcards *wc); Index: openvswitch-2.17.2/lib/token-bucket.c =================================================================== --- openvswitch-2.17.2.orig/lib/token-bucket.c +++ openvswitch-2.17.2/lib/token-bucket.c @@ -20,8 +20,8 @@ #include "openvswitch/poll-loop.h" #include "sat-math.h" -#include "timeval.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/util.h" /* Initializes 'tb' to accumulate 'rate' tokens per millisecond, with a * maximum of 'burst' tokens. Index: openvswitch-2.17.2/lib/tun-metadata.c =================================================================== --- openvswitch-2.17.2.orig/lib/tun-metadata.c +++ openvswitch-2.17.2/lib/tun-metadata.c @@ -18,17 +18,17 @@ #include #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "openvswitch/compiler.h" #include "openvswitch/hmap.h" #include "openvswitch/match.h" -#include "nx-match.h" +#include "internal/nx-match.h" #include "odp-netlink.h" #include "openvswitch/ofp-match.h" -#include "ovs-rcu.h" -#include "packets.h" -#include "tun-metadata.h" -#include "util.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/packets.h" +#include "internal/tun-metadata-private.h" +#include "internal/util.h" struct tun_meta_entry { struct hmap_node node; /* In struct tun_table's key_hmap. */ Index: openvswitch-2.17.2/lib/unicode.c =================================================================== --- openvswitch-2.17.2.orig/lib/unicode.c +++ openvswitch-2.17.2/lib/unicode.c @@ -21,7 +21,7 @@ #include #include "openvswitch/dynamic-string.h" -#include "util.h" +#include "internal/util.h" /* Returns the unicode code point corresponding to leading surrogate 'leading' * and trailing surrogate 'trailing'. The return value will not make any Index: openvswitch-2.17.2/lib/unixctl.c =================================================================== --- openvswitch-2.17.2.orig/lib/unixctl.c +++ openvswitch-2.17.2/lib/unixctl.c @@ -15,20 +15,20 @@ */ #include -#include "unixctl.h" +#include "internal/unixctl.h" #include #include -#include "coverage.h" -#include "dirs.h" +#include "internal/coverage.h" +#include "internal/dirs.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include "openvswitch/list.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "stream.h" +#include "internal/stream.h" #include "stream-provider.h" -#include "svec.h" +#include "internal/svec.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(unixctl); Index: openvswitch-2.17.2/lib/userspace-tso.c =================================================================== --- openvswitch-2.17.2.orig/lib/userspace-tso.c +++ openvswitch-2.17.2/lib/userspace-tso.c @@ -16,8 +16,8 @@ #include -#include "smap.h" -#include "ovs-thread.h" +#include "internal/smap.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/vlog.h" #include "dpdk.h" #include "userspace-tso.h" Index: openvswitch-2.17.2/lib/util.c =================================================================== --- openvswitch-2.17.2.orig/lib/util.c +++ openvswitch-2.17.2/lib/util.c @@ -15,7 +15,7 @@ */ #include -#include "util.h" +#include "internal/util.h" #include #include #include @@ -27,13 +27,13 @@ #include #include #include -#include "bitmap.h" -#include "byte-order.h" -#include "coverage.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" -#include "socket-util.h" -#include "timeval.h" +#include "internal/bitmap.h" +#include "internal/byte-order.h" +#include "internal/coverage.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" #include "openvswitch/vlog.h" #ifdef HAVE_PTHREAD_SET_NAME_NP #include Index: openvswitch-2.17.2/lib/util.h =================================================================== --- openvswitch-2.17.2.orig/lib/util.h +++ openvswitch-2.17.2/lib/util.h @@ -27,7 +27,6 @@ #include #include #include "openvswitch/compiler.h" -#include "util.h" #include "openvswitch/util.h" #if defined(__aarch64__) && __GNUC__ >= 6 #include Index: openvswitch-2.17.2/lib/uuid.c =================================================================== --- openvswitch-2.17.2.orig/lib/uuid.c +++ openvswitch-2.17.2/lib/uuid.c @@ -15,7 +15,7 @@ #include -#include "uuid.h" +#include "internal/uuid.h" #include #include @@ -26,13 +26,13 @@ #include "aes128.h" #include "entropy.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/vlog.h" #include "ovs-replay.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "sha1.h" -#include "timeval.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(uuid); Index: openvswitch-2.17.2/lib/vconn-provider.h =================================================================== --- openvswitch-2.17.2.orig/lib/vconn-provider.h +++ openvswitch-2.17.2/lib/vconn-provider.h @@ -21,7 +21,7 @@ * OpenFlow device. */ #include "openvswitch/vconn.h" -#include "util.h" +#include "internal/util.h" #include "openflow/openflow-common.h" /* Active virtual connection to an OpenFlow device. */ Index: openvswitch-2.17.2/lib/vconn-stream.c =================================================================== --- openvswitch-2.17.2.orig/lib/vconn-stream.c +++ openvswitch-2.17.2/lib/vconn-stream.c @@ -21,13 +21,13 @@ #include #include #include -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/ofpbuf.h" #include "openflow/openflow.h" #include "openvswitch/poll-loop.h" -#include "socket-util.h" -#include "stream.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/stream.h" +#include "internal/util.h" #include "vconn-provider.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/lib/vconn.c =================================================================== --- openvswitch-2.17.2.orig/lib/vconn.c +++ openvswitch-2.17.2/lib/vconn.c @@ -23,9 +23,9 @@ #include #include #include -#include "coverage.h" -#include "fatal-signal.h" -#include "flow.h" +#include "internal/coverage.h" +#include "internal/fatal-signal.h" +#include "internal/flow.h" #include "openflow/nicira-ext.h" #include "openflow/openflow.h" #include "openvswitch/dynamic-string.h" @@ -36,11 +36,11 @@ #include "openvswitch/ofp-util.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "random.h" -#include "util.h" -#include "socket-util.h" +#include "internal/random.h" +#include "internal/util.h" +#include "internal/socket-util.h" VLOG_DEFINE_THIS_MODULE(vconn); Index: openvswitch-2.17.2/lib/vl-mff-map.h =================================================================== --- openvswitch-2.17.2.orig/lib/vl-mff-map.h +++ openvswitch-2.17.2/lib/vl-mff-map.h @@ -17,7 +17,7 @@ #ifndef VL_MFF_MAP_H #define VL_MFF_MAP_H 1 -#include "cmap.h" +#include "internal/cmap.h" #include "openvswitch/thread.h" /* Variable length mf_fields mapping map. This is a single writer, Index: openvswitch-2.17.2/lib/vlan-bitmap.h =================================================================== --- openvswitch-2.17.2.orig/lib/vlan-bitmap.h +++ openvswitch-2.17.2/lib/vlan-bitmap.h @@ -18,7 +18,7 @@ #include #include -#include "bitmap.h" +#include "internal/bitmap.h" /* A "VLAN bitmap" is a 4096-bit bitmap that represents a set. A 1-bit * indicates that the respective VLAN is a member of the set, a 0-bit indicates Index: openvswitch-2.17.2/lib/vlog.c =================================================================== --- openvswitch-2.17.2.orig/lib/vlog.c +++ openvswitch-2.17.2/lib/vlog.c @@ -29,21 +29,21 @@ #include #include #include "async-append.h" -#include "coverage.h" -#include "dirs.h" +#include "internal/coverage.h" +#include "internal/dirs.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/ofpbuf.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "sat-math.h" -#include "socket-util.h" -#include "svec.h" +#include "internal/socket-util.h" +#include "internal/svec.h" #include "syslog-direct.h" #include "syslog-libc.h" #include "syslog-null.h" #include "syslog-provider.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(vlog); Index: openvswitch-2.17.2/lib/wmi.c =================================================================== --- openvswitch-2.17.2.orig/lib/wmi.c +++ openvswitch-2.17.2/lib/wmi.c @@ -20,7 +20,7 @@ #include #include #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(wmi); Index: openvswitch-2.17.2/ofproto/bond.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/bond.c +++ openvswitch-2.17.2/ofproto/bond.c @@ -24,12 +24,12 @@ #include #include "connectivity.h" -#include "coverage.h" -#include "dp-packet.h" -#include "flow.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" #include "openvswitch/hmap.h" #include "lacp.h" -#include "netdev.h" +#include "internal/netdev.h" #include "odp-util.h" #include "ofproto/ofproto-dpif.h" #include "ofproto/ofproto-dpif-rid.h" @@ -40,13 +40,13 @@ #include "openvswitch/ofp-actions.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "seq.h" +#include "internal/seq.h" #include "openvswitch/shash.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(bond); Index: openvswitch-2.17.2/ofproto/bond.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/bond.h +++ openvswitch-2.17.2/ofproto/bond.h @@ -20,7 +20,7 @@ #include #include #include "ofproto-provider.h" -#include "packets.h" +#include "internal/packets.h" struct flow; struct netdev; Index: openvswitch-2.17.2/ofproto/bundles.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/bundles.c +++ openvswitch-2.17.2/ofproto/bundles.c @@ -19,7 +19,7 @@ #include #include "bundles.h" -#include "coverage.h" +#include "internal/coverage.h" #include "fail-open.h" #include "in-band.h" #include "odp-util.h" @@ -33,9 +33,9 @@ #include "openvswitch/poll-loop.h" #include "openvswitch/rconn.h" #include "openvswitch/shash.h" -#include "simap.h" -#include "stream.h" -#include "timeval.h" +#include "internal/simap.h" +#include "internal/stream.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(bundles); Index: openvswitch-2.17.2/ofproto/bundles.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/bundles.h +++ openvswitch-2.17.2/ofproto/bundles.h @@ -24,7 +24,7 @@ #include "connmgr.h" #include "ofproto-provider.h" #include "openvswitch/ofp-msgs.h" -#include "util.h" +#include "internal/util.h" #ifdef __cplusplus extern "C" { Index: openvswitch-2.17.2/ofproto/collectors.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/collectors.c +++ openvswitch-2.17.2/ofproto/collectors.c @@ -23,9 +23,9 @@ #include #include -#include "socket-util.h" -#include "sset.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/sset.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(collectors); Index: openvswitch-2.17.2/ofproto/connmgr.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/connmgr.c +++ openvswitch-2.17.2/ofproto/connmgr.c @@ -20,7 +20,7 @@ #include "bundles.h" #include "connmgr.h" -#include "coverage.h" +#include "internal/coverage.h" #include "fail-open.h" #include "in-band.h" #include "odp-util.h" @@ -32,16 +32,16 @@ #include "openvswitch/ofpbuf.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" -#include "ovs-atomic.h" +#include "openvswitch/ovs-atomic.h" #include "pinsched.h" #include "openvswitch/poll-loop.h" #include "openvswitch/rconn.h" #include "openvswitch/shash.h" #include "sat-math.h" -#include "simap.h" -#include "stream.h" -#include "timeval.h" -#include "util.h" +#include "internal/simap.h" +#include "internal/stream.h" +#include "internal/timeval.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(connmgr); static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); Index: openvswitch-2.17.2/ofproto/connmgr.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/connmgr.h +++ openvswitch-2.17.2/ofproto/connmgr.h @@ -17,7 +17,7 @@ #ifndef CONNMGR_H #define CONNMGR_H 1 -#include "classifier.h" +#include "internal/classifier.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" #include "openvswitch/match.h" Index: openvswitch-2.17.2/ofproto/fail-open.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/fail-open.c +++ openvswitch-2.17.2/ofproto/fail-open.c @@ -17,11 +17,11 @@ #include #include #include -#include "classifier.h" +#include "internal/classifier.h" #include "connmgr.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "fail-open.h" -#include "flow.h" +#include "internal/flow.h" #include "mac-learning.h" #include "odp-util.h" #include "openvswitch/ofp-actions.h" @@ -32,7 +32,7 @@ #include "ofproto-provider.h" #include "openvswitch/poll-loop.h" #include "openvswitch/rconn.h" -#include "timeval.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(fail_open); Index: openvswitch-2.17.2/ofproto/in-band.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/in-band.c +++ openvswitch-2.17.2/ofproto/in-band.c @@ -24,12 +24,12 @@ #include #include #include -#include "classifier.h" -#include "dhcp.h" -#include "flow.h" +#include "internal/classifier.h" +#include "internal/dhcp.h" +#include "internal/flow.h" #include "in-band.h" -#include "netdev.h" -#include "netlink.h" +#include "internal/netdev.h" +#include "internal/netlink.h" #include "odp-util.h" #include "ofproto.h" #include "ofproto-provider.h" @@ -37,9 +37,9 @@ #include "openvswitch/ofp-actions.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "timeval.h" +#include "internal/timeval.h" VLOG_DEFINE_THIS_MODULE(in_band); Index: openvswitch-2.17.2/ofproto/in-band.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/in-band.h +++ openvswitch-2.17.2/ofproto/in-band.h @@ -22,7 +22,7 @@ #include #include #include -#include "flow.h" +#include "internal/flow.h" struct flow; struct in_band; Index: openvswitch-2.17.2/ofproto/netflow.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/netflow.c +++ openvswitch-2.17.2/ofproto/netflow.c @@ -22,19 +22,19 @@ #include #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "collectors.h" #include "dpif.h" -#include "flow.h" +#include "internal/flow.h" #include "lib/netflow.h" #include "openvswitch/ofpbuf.h" #include "ofproto.h" #include "ofproto/netflow.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "socket-util.h" -#include "timeval.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(netflow); Index: openvswitch-2.17.2/ofproto/netflow.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/netflow.h +++ openvswitch-2.17.2/ofproto/netflow.h @@ -18,8 +18,8 @@ #define OFPROTO_NETFLOW_H 1 #include -#include "flow.h" -#include "sset.h" +#include "internal/flow.h" +#include "internal/sset.h" /* Default active timeout interval, in seconds. * Index: openvswitch-2.17.2/ofproto/ofproto-dpif-ipfix.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-ipfix.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-ipfix.c @@ -17,23 +17,23 @@ #include #include "ofproto-dpif-ipfix.h" #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "collectors.h" -#include "flow.h" -#include "hash.h" +#include "internal/flow.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "netdev.h" +#include "internal/netdev.h" #include "openvswitch/list.h" #include "openvswitch/ofp-ipfix.h" #include "openvswitch/ofpbuf.h" #include "ofproto.h" #include "ofproto-dpif.h" -#include "dp-packet.h" -#include "packets.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "sset.h" -#include "util.h" -#include "timeval.h" +#include "internal/sset.h" +#include "internal/util.h" +#include "internal/timeval.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ipfix); Index: openvswitch-2.17.2/ofproto/ofproto-dpif-mirror.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-mirror.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-mirror.c @@ -18,8 +18,8 @@ #include -#include "cmap.h" -#include "hmapx.h" +#include "internal/cmap.h" +#include "internal/hmapx.h" #include "ofproto.h" #include "vlan-bitmap.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/ofproto/ofproto-dpif-mirror.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-mirror.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif-mirror.h @@ -17,7 +17,7 @@ #include -#include "util.h" +#include "internal/util.h" #define MAX_MIRRORS 32 typedef uint32_t mirror_mask_t; Index: openvswitch-2.17.2/ofproto/ofproto-dpif-monitor.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-monitor.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-monitor.c @@ -21,20 +21,20 @@ #include "bfd.h" #include "cfm.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "guarded-list.h" -#include "hash.h" +#include "internal/hash.h" #include "heap.h" #include "openvswitch/hmap.h" -#include "latch.h" +#include "internal/latch.h" #include "openvswitch/ofpbuf.h" #include "ofproto-dpif.h" #include "ovs-lldp.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" -#include "seq.h" -#include "timeval.h" -#include "util.h" +#include "internal/seq.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ofproto_dpif_monitor); Index: openvswitch-2.17.2/ofproto/ofproto-dpif-monitor.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-monitor.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif-monitor.h @@ -18,7 +18,7 @@ #include #include "openflow/openflow.h" -#include "packets.h" +#include "internal/packets.h" struct bfd; struct cfm; Index: openvswitch-2.17.2/ofproto/ofproto-dpif-rid.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-rid.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif-rid.h @@ -20,13 +20,13 @@ #include #include -#include "cmap.h" +#include "internal/cmap.h" #include "ofproto-dpif-mirror.h" #include "ofproto/ofproto-provider.h" #include "openvswitch/list.h" #include "openvswitch/ofp-actions.h" -#include "ovs-thread.h" -#include "uuid.h" +#include "openvswitch/ovs-thread.h" +#include "internal/uuid.h" struct ofproto_dpif; struct rule; Index: openvswitch-2.17.2/ofproto/ofproto-dpif-sflow.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-sflow.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-sflow.c @@ -25,22 +25,22 @@ #include "collectors.h" #include "openvswitch/compiler.h" #include "dpif.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "netdev.h" -#include "netlink.h" +#include "internal/netdev.h" +#include "internal/netlink.h" #include "openvswitch/ofpbuf.h" #include "ofproto.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" #include "ovs-router.h" #include "route-table.h" #include "sflow_api.h" -#include "socket-util.h" -#include "timeval.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" #include "openvswitch/vlog.h" #include "lib/odp-util.h" -#include "lib/unaligned.h" +#include "internal/unaligned.h" #include "ofproto-provider.h" #include "lacp.h" Index: openvswitch-2.17.2/ofproto/ofproto-dpif-sflow.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-sflow.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif-sflow.h @@ -19,7 +19,7 @@ #define OFPROTO_DPIF_SFLOW_H 1 #include -#include "svec.h" +#include "internal/svec.h" #include "lib/odp-util.h" struct dpif; Index: openvswitch-2.17.2/ofproto/ofproto-dpif-trace.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-trace.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-trace.c @@ -21,7 +21,7 @@ #include "conntrack.h" #include "dpif.h" #include "ofproto-dpif-xlate.h" -#include "unixctl.h" +#include "internal/unixctl.h" static void oftrace_node_destroy(struct oftrace_node *); Index: openvswitch-2.17.2/ofproto/ofproto-dpif-trace.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-trace.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif-trace.h @@ -32,7 +32,7 @@ #include "ofproto/ofproto-dpif.h" #include "openvswitch/compiler.h" #include "openvswitch/list.h" -#include "flow.h" +#include "internal/flow.h" /* Type of a node within a trace. */ enum oftrace_node_type { Index: openvswitch-2.17.2/ofproto/ofproto-dpif-upcall.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-upcall.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-upcall.c @@ -20,28 +20,28 @@ #include #include "connmgr.h" -#include "coverage.h" -#include "cmap.h" +#include "internal/coverage.h" +#include "internal/cmap.h" #include "lib/dpif-provider.h" #include "dpif.h" #include "openvswitch/dynamic-string.h" #include "fail-open.h" #include "guarded-list.h" -#include "latch.h" +#include "internal/latch.h" #include "openvswitch/list.h" -#include "netlink.h" +#include "internal/netlink.h" #include "openvswitch/ofpbuf.h" #include "ofproto-dpif-ipfix.h" #include "ofproto-dpif-sflow.h" #include "ofproto-dpif-xlate.h" #include "ofproto-dpif-xlate-cache.h" #include "ofproto-dpif-trace.h" -#include "ovs-rcu.h" -#include "packets.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "seq.h" +#include "internal/seq.h" #include "tunnel.h" -#include "unixctl.h" +#include "internal/unixctl.h" #include "openvswitch/vlog.h" #include "lib/netdev-provider.h" Index: openvswitch-2.17.2/ofproto/ofproto-dpif-xlate-cache.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-xlate-cache.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-xlate-cache.c @@ -24,13 +24,13 @@ #include #include "bfd.h" -#include "bitmap.h" +#include "internal/bitmap.h" #include "bond.h" -#include "bundle.h" -#include "byte-order.h" +#include "internal/bundle.h" +#include "internal/byte-order.h" #include "connmgr.h" -#include "coverage.h" -#include "dp-packet.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" #include "dpif.h" #include "learn.h" #include "mac-learning.h" @@ -42,9 +42,9 @@ #include "openvswitch/dynamic-string.h" #include "openvswitch/vlog.h" #include "ovs-router.h" -#include "packets.h" +#include "internal/packets.h" #include "tnl-neigh-cache.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofproto_xlate_cache); Index: openvswitch-2.17.2/ofproto/ofproto-dpif-xlate-cache.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-xlate-cache.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif-xlate-cache.h @@ -21,7 +21,7 @@ #include #include "openvswitch/types.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "odp-util.h" #include "ofproto/ofproto-dpif-mirror.h" #include "openvswitch/ofpbuf.h" Index: openvswitch-2.17.2/ofproto/ofproto-dpif-xlate.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-xlate.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif-xlate.c @@ -24,25 +24,25 @@ #include #include "bfd.h" -#include "bitmap.h" +#include "internal/bitmap.h" #include "bond.h" -#include "bundle.h" -#include "byte-order.h" +#include "internal/bundle.h" +#include "internal/byte-order.h" #include "cfm.h" #include "connmgr.h" -#include "coverage.h" -#include "csum.h" -#include "dp-packet.h" +#include "internal/coverage.h" +#include "internal/csum.h" +#include "internal/dp-packet.h" #include "dpif.h" #include "in-band.h" #include "lacp.h" #include "learn.h" #include "mac-learning.h" -#include "mcast-snooping.h" +#include "internal/mcast-snooping.h" #include "multipath.h" #include "netdev-vport.h" -#include "netlink.h" -#include "nx-match.h" +#include "internal/netlink.h" +#include "internal/nx-match.h" #include "odp-execute.h" #include "ofproto/ofproto-dpif-ipfix.h" #include "ofproto/ofproto-dpif-mirror.h" @@ -60,12 +60,12 @@ #include "openvswitch/vlog.h" #include "ovs-lldp.h" #include "ovs-router.h" -#include "packets.h" +#include "internal/packets.h" #include "tnl-neigh-cache.h" #include "tnl-ports.h" #include "tunnel.h" -#include "util.h" -#include "uuid.h" +#include "internal/util.h" +#include "internal/uuid.h" COVERAGE_DEFINE(xlate_actions); COVERAGE_DEFINE(xlate_actions_oversize); Index: openvswitch-2.17.2/ofproto/ofproto-dpif-xlate.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif-xlate.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif-xlate.h @@ -15,8 +15,8 @@ #ifndef OFPROTO_DPIF_XLATE_H #define OFPROTO_DPIF_XLATE_H 1 -#include "dp-packet.h" -#include "flow.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" #include "openvswitch/meta-flow.h" #include "odp-util.h" #include "openvswitch/ofpbuf.h" @@ -26,7 +26,7 @@ #include "ofproto.h" #include "stp.h" #include "ovs-lldp.h" -#include "uuid.h" +#include "internal/uuid.h" struct bfd; struct bond; Index: openvswitch-2.17.2/ofproto/ofproto-dpif.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif.c +++ openvswitch-2.17.2/ofproto/ofproto-dpif.c @@ -18,26 +18,26 @@ #include "bfd.h" #include "bond.h" -#include "bundle.h" -#include "byte-order.h" +#include "internal/bundle.h" +#include "internal/byte-order.h" #include "connectivity.h" #include "connmgr.h" -#include "coverage.h" +#include "internal/coverage.h" #include "cfm.h" #include "ct-dpif.h" #include "fail-open.h" #include "guarded-list.h" -#include "hmapx.h" +#include "internal/hmapx.h" #include "lacp.h" #include "learn.h" #include "mac-learning.h" #include "math.h" -#include "mcast-snooping.h" +#include "internal/mcast-snooping.h" #include "multipath.h" #include "netdev-vport.h" -#include "netdev.h" -#include "netlink.h" -#include "nx-match.h" +#include "internal/netdev.h" +#include "internal/netlink.h" +#include "internal/nx-match.h" #include "odp-util.h" #include "odp-execute.h" #include "ofproto/ofproto-dpif.h" @@ -59,18 +59,18 @@ #include "openvswitch/uuid.h" #include "openvswitch/vlog.h" #include "ovs-lldp.h" -#include "ovs-rcu.h" +#include "openvswitch/ovs-rcu.h" #include "ovs-router.h" #include "openvswitch/poll-loop.h" -#include "seq.h" -#include "simap.h" -#include "smap.h" -#include "timer.h" +#include "internal/seq.h" +#include "internal/simap.h" +#include "internal/smap.h" +#include "internal/timer.h" #include "tunnel.h" -#include "unaligned.h" -#include "unixctl.h" -#include "util.h" -#include "uuid.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" +#include "internal/util.h" +#include "internal/uuid.h" #include "vlan-bitmap.h" VLOG_DEFINE_THIS_MODULE(ofproto_dpif); Index: openvswitch-2.17.2/ofproto/ofproto-dpif.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-dpif.h +++ openvswitch-2.17.2/ofproto/ofproto-dpif.h @@ -48,12 +48,12 @@ #include "dpif.h" #include "fail-open.h" -#include "hmapx.h" +#include "internal/hmapx.h" #include "odp-util.h" -#include "id-pool.h" -#include "ovs-thread.h" +#include "internal/id-pool.h" +#include "openvswitch/ovs-thread.h" #include "ofproto-provider.h" -#include "util.h" +#include "internal/util.h" struct dpif_flow_stats; struct ofproto_async_msg; Index: openvswitch-2.17.2/ofproto/ofproto-provider.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto-provider.h +++ openvswitch-2.17.2/ofproto/ofproto-provider.h @@ -34,10 +34,10 @@ */ #include "cfm.h" -#include "classifier.h" +#include "internal/classifier.h" #include "guarded-list.h" #include "heap.h" -#include "hindex.h" +#include "internal/hindex.h" #include "object-collection.h" #include "ofproto/ofproto.h" #include "openvswitch/list.h" @@ -49,14 +49,14 @@ #include "openvswitch/ofp-port.h" #include "openvswitch/ofp-switch.h" #include "openvswitch/ofp-table.h" -#include "ovs-atomic.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/shash.h" -#include "simap.h" -#include "timeval.h" -#include "tun-metadata.h" -#include "versions.h" +#include "internal/simap.h" +#include "internal/timeval.h" +#include "internal/tun-metadata-private.h" +#include "internal/versions.h" #include "vl-mff-map.h" struct match; Index: openvswitch-2.17.2/ofproto/ofproto.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto.c +++ openvswitch-2.17.2/ofproto/ofproto.c @@ -22,18 +22,18 @@ #include #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "bundles.h" -#include "byte-order.h" -#include "classifier.h" +#include "internal/byte-order.h" +#include "internal/classifier.h" #include "connectivity.h" #include "connmgr.h" -#include "coverage.h" -#include "dp-packet.h" -#include "hash.h" +#include "internal/coverage.h" +#include "internal/dp-packet.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "netdev.h" -#include "nx-match.h" +#include "internal/netdev.h" +#include "internal/nx-match.h" #include "ofproto.h" #include "ofproto-provider.h" #include "openflow/nicira-ext.h" @@ -51,21 +51,21 @@ #include "openvswitch/ofp-util.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "ovs-rcu.h" -#include "packets.h" +#include "openvswitch/ovs-rcu.h" +#include "internal/packets.h" #include "pinsched.h" #include "openvswitch/poll-loop.h" -#include "random.h" -#include "seq.h" +#include "internal/random.h" +#include "internal/seq.h" #include "openvswitch/shash.h" -#include "simap.h" -#include "smap.h" -#include "sset.h" -#include "timeval.h" -#include "tun-metadata.h" -#include "unaligned.h" -#include "unixctl.h" -#include "util.h" +#include "internal/simap.h" +#include "internal/smap.h" +#include "internal/sset.h" +#include "internal/timeval.h" +#include "internal/tun-metadata-private.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofproto); Index: openvswitch-2.17.2/ofproto/ofproto.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/ofproto.h +++ openvswitch-2.17.2/ofproto/ofproto.h @@ -23,13 +23,13 @@ #include #include #include "cfm.h" -#include "classifier.h" -#include "flow.h" +#include "internal/classifier.h" +#include "internal/flow.h" #include "openvswitch/meta-flow.h" #include "netflow.h" #include "rstp.h" -#include "smap.h" -#include "sset.h" +#include "internal/smap.h" +#include "internal/sset.h" #include "stp.h" #include "lacp.h" Index: openvswitch-2.17.2/ofproto/pinsched.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/pinsched.c +++ openvswitch-2.17.2/ofproto/pinsched.c @@ -21,16 +21,16 @@ #include #include #include -#include "flow.h" -#include "hash.h" +#include "internal/flow.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "openvswitch/ofpbuf.h" #include "openflow/openflow.h" #include "openvswitch/poll-loop.h" -#include "random.h" +#include "internal/random.h" #include "openvswitch/rconn.h" #include "sat-math.h" -#include "timeval.h" +#include "internal/timeval.h" #include "openvswitch/token-bucket.h" #include "openvswitch/vconn.h" Index: openvswitch-2.17.2/ofproto/pinsched.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/pinsched.h +++ openvswitch-2.17.2/ofproto/pinsched.h @@ -18,7 +18,7 @@ #define PINSCHED_H_H 1 #include -#include "flow.h" +#include "internal/flow.h" struct ovs_list; struct ofpbuf; Index: openvswitch-2.17.2/ofproto/tunnel.c =================================================================== --- openvswitch-2.17.2.orig/ofproto/tunnel.c +++ openvswitch-2.17.2/ofproto/tunnel.c @@ -15,27 +15,27 @@ #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "connectivity.h" -#include "csum.h" +#include "internal/csum.h" #include "dpif.h" #include "openvswitch/dynamic-string.h" #include "fat-rwlock.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "netdev.h" +#include "internal/netdev.h" #include "odp-util.h" #include "openvswitch/ofpbuf.h" -#include "packets.h" +#include "internal/packets.h" #include "route-table.h" -#include "seq.h" -#include "smap.h" -#include "socket-util.h" +#include "internal/seq.h" +#include "internal/smap.h" +#include "internal/socket-util.h" #include "tnl-ports.h" #include "tunnel.h" #include "openvswitch/vlog.h" -#include "unaligned.h" -#include "unixctl.h" +#include "internal/unaligned.h" +#include "internal/unixctl.h" #include "ofproto-dpif.h" #include "netdev-vport.h" Index: openvswitch-2.17.2/ofproto/tunnel.h =================================================================== --- openvswitch-2.17.2.orig/ofproto/tunnel.h +++ openvswitch-2.17.2/ofproto/tunnel.h @@ -18,7 +18,7 @@ #include #include -#include "flow.h" +#include "internal/flow.h" /* Tunnel port emulation layer. * Index: openvswitch-2.17.2/ovsdb/column.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/column.c +++ openvswitch-2.17.2/ovsdb/column.c @@ -22,10 +22,10 @@ #include "column.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "table.h" -#include "util.h" +#include "internal/util.h" struct ovsdb_column * ovsdb_column_create(const char *name, Index: openvswitch-2.17.2/ovsdb/column.h =================================================================== --- openvswitch-2.17.2.orig/ovsdb/column.h +++ openvswitch-2.17.2/ovsdb/column.h @@ -18,7 +18,7 @@ #include #include "openvswitch/compiler.h" -#include "ovsdb-types.h" +#include "openvswitch/ovsdb-types.h" struct ovsdb_table; struct ovsdb_table_schema; Index: openvswitch-2.17.2/ovsdb/condition.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/condition.c +++ openvswitch-2.17.2/ovsdb/condition.c @@ -21,13 +21,13 @@ #include "column.h" #include "openvswitch/json.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "row.h" #include #include "table.h" -#include "util.h" +#include "internal/util.h" static struct ovsdb_error * ovsdb_clause_from_json(const struct ovsdb_table_schema *ts, Index: openvswitch-2.17.2/ovsdb/condition.h =================================================================== --- openvswitch-2.17.2.orig/ovsdb/condition.h +++ openvswitch-2.17.2/ovsdb/condition.h @@ -18,9 +18,9 @@ #include #include "openvswitch/compiler.h" -#include "ovsdb-data.h" -#include "bitmap.h" -#include "ovsdb-condition.h" +#include "openvswitch/ovsdb-data.h" +#include "internal/bitmap.h" +#include "openvswitch/ovsdb-condition.h" struct json; struct ovsdb_table_schema; Index: openvswitch-2.17.2/ovsdb/execution.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/execution.c +++ openvswitch-2.17.2/ovsdb/execution.c @@ -24,15 +24,15 @@ #include "file.h" #include "openvswitch/json.h" #include "mutation.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "query.h" #include "rbac.h" #include "row.h" #include "server.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" struct ovsdb_execution { Index: openvswitch-2.17.2/ovsdb/file.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/file.c +++ openvswitch-2.17.2/ovsdb/file.c @@ -21,22 +21,22 @@ #include #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "column.h" #include "log.h" #include "openvswitch/json.h" #include "lockfile.h" #include "ovsdb.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "row.h" -#include "socket-util.h" +#include "internal/socket-util.h" #include "storage.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" -#include "unixctl.h" -#include "uuid.h" -#include "util.h" +#include "internal/unixctl.h" +#include "internal/uuid.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovsdb_file); Index: openvswitch-2.17.2/ovsdb/jsonrpc-server.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/jsonrpc-server.c +++ openvswitch-2.17.2/ovsdb/jsonrpc-server.c @@ -19,28 +19,28 @@ #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "column.h" #include "openvswitch/dynamic-string.h" #include "monitor.h" #include "openvswitch/json.h" -#include "jsonrpc.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "internal/jsonrpc.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "ovsdb.h" #include "condition.h" #include "openvswitch/poll-loop.h" #include "reconnect.h" #include "row.h" #include "server.h" -#include "simap.h" +#include "internal/simap.h" #include "storage.h" -#include "stream.h" +#include "internal/stream.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" #include "trigger.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovsdb_jsonrpc_server); Index: openvswitch-2.17.2/ovsdb/log.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/log.c +++ openvswitch-2.17.2/ovsdb/log.c @@ -28,17 +28,17 @@ #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" #include "openvswitch/vlog.h" -#include "ovs-atomic.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" -#include "ovsdb-error.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" +#include "openvswitch/ovsdb-error.h" #include "ovsdb.h" #include "openvswitch/poll-loop.h" -#include "seq.h" +#include "internal/seq.h" #include "sha1.h" -#include "socket-util.h" +#include "internal/socket-util.h" #include "transaction.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ovsdb_log); Index: openvswitch-2.17.2/ovsdb/monitor.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/monitor.c +++ openvswitch-2.17.2/ovsdb/monitor.c @@ -18,24 +18,24 @@ #include -#include "bitmap.h" +#include "internal/bitmap.h" #include "column.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "jsonrpc.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "internal/jsonrpc.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "ovsdb.h" #include "row.h" #include "condition.h" -#include "simap.h" -#include "hash.h" +#include "internal/simap.h" +#include "internal/hash.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" #include "jsonrpc-server.h" #include "monitor.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovsdb_monitor); Index: openvswitch-2.17.2/ovsdb/mutation.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/mutation.c +++ openvswitch-2.17.2/ovsdb/mutation.c @@ -21,14 +21,14 @@ #include #include "column.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "openvswitch/json.h" #include "row.h" #include #include "table.h" -#include "util.h" +#include "internal/util.h" struct ovsdb_error * ovsdb_mutator_from_string(const char *name, enum ovsdb_mutator *mutator) Index: openvswitch-2.17.2/ovsdb/mutation.h =================================================================== --- openvswitch-2.17.2.orig/ovsdb/mutation.h +++ openvswitch-2.17.2/ovsdb/mutation.h @@ -18,7 +18,7 @@ #include #include "openvswitch/compiler.h" -#include "ovsdb-data.h" +#include "openvswitch/ovsdb-data.h" struct json; struct ovsdb_table_schema; Index: openvswitch-2.17.2/ovsdb/ovsdb-client.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/ovsdb-client.c +++ openvswitch-2.17.2/ovsdb/ovsdb-client.c @@ -26,37 +26,37 @@ #include #include -#include "command-line.h" +#include "internal/command-line.h" #include "column.h" #include "openvswitch/compiler.h" -#include "daemon.h" -#include "dirs.h" +#include "internal/daemon.h" +#include "internal/dirs.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "file.h" #include "openvswitch/json.h" -#include "jsonrpc.h" -#include "lib/table.h" +#include "internal/jsonrpc.h" +#include "internal/table.h" #include "log.h" #include "ovs-replay.h" #include "ovsdb.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" #include "ovsdb-session.h" #include "openvswitch/poll-loop.h" #include "row.h" -#include "sort.h" -#include "svec.h" +#include "internal/sort.h" +#include "internal/svec.h" #include "storage.h" -#include "stream.h" -#include "stream-ssl.h" +#include "internal/stream.h" +#include "internal/stream-ssl.h" #include "table.h" #include "transaction.h" #include "monitor.h" #include "condition.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(ovsdb_client); Index: openvswitch-2.17.2/ovsdb/ovsdb-idlc.in =================================================================== --- openvswitch-2.17.2.orig/ovsdb/ovsdb-idlc.in +++ openvswitch-2.17.2/ovsdb/ovsdb-idlc.in @@ -193,10 +193,10 @@ def printCIDLHeader(schemaFile): #include #include #include "openvswitch/json.h" -#include "ovsdb-data.h" -#include "ovsdb-idl-provider.h" -#include "smap.h" -#include "uuid.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-idl-provider.h" +#include "internal/smap.h" +#include "internal/uuid.h" #ifdef __cplusplus extern "C" { @@ -484,10 +484,10 @@ def printCIDLSource(schemaFile): #include #include %(header)s #include -#include "ovs-thread.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "internal/util.h" %(cDecls)s Index: openvswitch-2.17.2/ovsdb/ovsdb-server.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/ovsdb-server.c +++ openvswitch-2.17.2/ovsdb/ovsdb-server.c @@ -23,42 +23,42 @@ #include #include "column.h" -#include "command-line.h" -#include "daemon.h" -#include "dirs.h" +#include "internal/command-line.h" +#include "internal/daemon.h" +#include "internal/dirs.h" #include "dns-resolve.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "file.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/json.h" -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include "jsonrpc-server.h" #include "openvswitch/list.h" -#include "memory.h" +#include "internal/memory.h" #include "monitor.h" #include "ovs-replay.h" #include "ovsdb.h" -#include "ovsdb-data.h" -#include "ovsdb-types.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-types.h" +#include "openvswitch/ovsdb-error.h" #include "openvswitch/poll-loop.h" -#include "process.h" +#include "internal/process.h" #include "replication.h" #include "relay.h" #include "row.h" -#include "simap.h" +#include "internal/simap.h" #include "openvswitch/shash.h" -#include "stream-ssl.h" -#include "stream.h" -#include "sset.h" +#include "internal/stream-ssl.h" +#include "internal/stream.h" +#include "internal/sset.h" #include "storage.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" #include "trigger.h" -#include "util.h" -#include "unixctl.h" +#include "internal/util.h" +#include "internal/unixctl.h" #include "perf-counter.h" #include "ovsdb-util.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/ovsdb/ovsdb-tool.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/ovsdb-tool.c +++ openvswitch-2.17.2/ovsdb/ovsdb-tool.c @@ -23,29 +23,30 @@ #include #include "column.h" +#include "internal/command-line.h" #include "openvswitch/compiler.h" -#include "dirs.h" +#include "internal/dirs.h" #include "openvswitch/dynamic-string.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "file.h" -#include "hash.h" +#include "internal/hash.h" #include "lockfile.h" #include "log.h" #include "openvswitch/hmap.h" #include "openvswitch/json.h" #include "ovsdb.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "raft.h" #include "raft-private.h" -#include "smap.h" -#include "socket-util.h" +#include "internal/smap.h" +#include "internal/socket-util.h" #include "storage.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/vlog.h" /* -m, --more: Verbosity level for "show-log" command output. */ Index: openvswitch-2.17.2/ovsdb/ovsdb-util.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/ovsdb-util.c +++ openvswitch-2.17.2/ovsdb/ovsdb-util.c @@ -15,7 +15,7 @@ #include #include "row.h" -#include "sset.h" +#include "internal/sset.h" #include "table.h" #include "ovsdb-util.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/ovsdb/ovsdb.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/ovsdb.c +++ openvswitch-2.17.2/ovsdb/ovsdb.c @@ -25,13 +25,13 @@ #include "file.h" #include "monitor.h" #include "openvswitch/json.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" -#include "ovsdb-types.h" -#include "simap.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" +#include "openvswitch/ovsdb-types.h" +#include "internal/simap.h" #include "storage.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" #include "transaction-forward.h" #include "trigger.h" Index: openvswitch-2.17.2/ovsdb/raft-private.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/raft-private.c +++ openvswitch-2.17.2/ovsdb/raft-private.c @@ -18,12 +18,12 @@ #include "raft-private.h" -#include "coverage.h" +#include "internal/coverage.h" #include "openvswitch/dynamic-string.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" -#include "socket-util.h" -#include "sset.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" +#include "internal/socket-util.h" +#include "internal/sset.h" COVERAGE_DEFINE(raft_entry_serialize); Index: openvswitch-2.17.2/ovsdb/raft-private.h =================================================================== --- openvswitch-2.17.2.orig/ovsdb/raft-private.h +++ openvswitch-2.17.2/ovsdb/raft-private.h @@ -23,7 +23,7 @@ #include #include "openvswitch/hmap.h" #include "openvswitch/uuid.h" -#include "sset.h" +#include "internal/sset.h" struct ds; struct ovsdb_parser; Index: openvswitch-2.17.2/ovsdb/raft-rpc.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/raft-rpc.c +++ openvswitch-2.17.2/ovsdb/raft-rpc.c @@ -20,13 +20,13 @@ #include #include #include "openvswitch/compiler.h" -#include "jsonrpc.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "internal/jsonrpc.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" #include "openvswitch/vlog.h" -#include "sset.h" +#include "internal/sset.h" VLOG_DEFINE_THIS_MODULE(raft_rpc); Index: openvswitch-2.17.2/ovsdb/raft-rpc.h =================================================================== --- openvswitch-2.17.2.orig/ovsdb/raft-rpc.h +++ openvswitch-2.17.2/ovsdb/raft-rpc.h @@ -24,7 +24,7 @@ #include "openvswitch/uuid.h" #include "raft.h" #include "raft-private.h" -#include "sset.h" +#include "internal/sset.h" struct ds; Index: openvswitch-2.17.2/ovsdb/raft.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/raft.c +++ openvswitch-2.17.2/ovsdb/raft.c @@ -22,8 +22,8 @@ #include #include -#include "hash.h" -#include "jsonrpc.h" +#include "internal/hash.h" +#include "internal/jsonrpc.h" #include "lockfile.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" @@ -31,19 +31,19 @@ #include "openvswitch/list.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "ovsdb/log.h" #include "raft-rpc.h" -#include "random.h" -#include "simap.h" -#include "socket-util.h" -#include "stream.h" -#include "timeval.h" +#include "internal/random.h" +#include "internal/simap.h" +#include "internal/socket-util.h" +#include "internal/stream.h" +#include "internal/timeval.h" #include "unicode.h" -#include "unixctl.h" -#include "util.h" -#include "uuid.h" +#include "internal/unixctl.h" +#include "internal/util.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(raft); Index: openvswitch-2.17.2/ovsdb/raft.h =================================================================== --- openvswitch-2.17.2.orig/ovsdb/raft.h +++ openvswitch-2.17.2/ovsdb/raft.h @@ -62,7 +62,7 @@ #include #include #include "openvswitch/compiler.h" -#include "uuid.h" +#include "internal/uuid.h" struct json; struct ovsdb_log; Index: openvswitch-2.17.2/ovsdb/rbac.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/rbac.c +++ openvswitch-2.17.2/ovsdb/rbac.c @@ -24,16 +24,16 @@ #include "file.h" #include "mutation.h" #include "openvswitch/vlog.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" #include "ovsdb-util.h" #include "ovsdb.h" #include "query.h" #include "row.h" #include "server.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" VLOG_DEFINE_THIS_MODULE(ovsdb_rbac); Index: openvswitch-2.17.2/ovsdb/relay.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/relay.c +++ openvswitch-2.17.2/ovsdb/relay.c @@ -18,8 +18,8 @@ #include "relay.h" -#include "coverage.h" -#include "jsonrpc.h" +#include "internal/coverage.h" +#include "internal/jsonrpc.h" #include "openvswitch/hmap.h" #include "openvswitch/json.h" #include "openvswitch/list.h" @@ -27,14 +27,14 @@ #include "openvswitch/shash.h" #include "openvswitch/vlog.h" #include "ovsdb.h" -#include "ovsdb-cs.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-cs.h" +#include "openvswitch/ovsdb-error.h" #include "row.h" #include "table.h" -#include "timeval.h" +#include "internal/timeval.h" #include "transaction.h" #include "transaction-forward.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(relay); Index: openvswitch-2.17.2/ovsdb/replication.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/replication.c +++ openvswitch-2.17.2/ovsdb/replication.c @@ -19,22 +19,22 @@ #include "condition.h" -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/hmap.h" #include "openvswitch/json.h" #include "openvswitch/vlog.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "ovsdb.h" #include "query.h" #include "replication.h" #include "row.h" -#include "sset.h" -#include "stream.h" -#include "svec.h" +#include "internal/sset.h" +#include "internal/stream.h" +#include "internal/svec.h" #include "table.h" #include "transaction.h" -#include "uuid.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(replication); Index: openvswitch-2.17.2/ovsdb/row.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/row.c +++ openvswitch-2.17.2/ovsdb/row.c @@ -21,11 +21,11 @@ #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "openvswitch/shash.h" -#include "sort.h" +#include "internal/sort.h" #include "table.h" -#include "util.h" +#include "internal/util.h" static struct ovsdb_row * allocate_row(const struct ovsdb_table *table) Index: openvswitch-2.17.2/ovsdb/row.h =================================================================== --- openvswitch-2.17.2.orig/ovsdb/row.h +++ openvswitch-2.17.2/ovsdb/row.h @@ -21,7 +21,7 @@ #include "column.h" #include "openvswitch/hmap.h" #include "openvswitch/list.h" -#include "ovsdb-data.h" +#include "openvswitch/ovsdb-data.h" struct ovsdb_column_set; Index: openvswitch-2.17.2/ovsdb/server.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/server.c +++ openvswitch-2.17.2/ovsdb/server.c @@ -17,9 +17,9 @@ #include "server.h" -#include "hash.h" +#include "internal/hash.h" #include "ovsdb.h" -#include "uuid.h" +#include "internal/uuid.h" /* Initializes 'session' as a session within 'server'. */ void Index: openvswitch-2.17.2/ovsdb/storage.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/storage.c +++ openvswitch-2.17.2/ovsdb/storage.c @@ -19,16 +19,16 @@ #include "storage.h" #include #include "log.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "openvswitch/json.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" #include "ovsdb.h" #include "raft.h" -#include "random.h" -#include "simap.h" -#include "timeval.h" -#include "util.h" +#include "internal/random.h" +#include "internal/simap.h" +#include "internal/timeval.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(storage); Index: openvswitch-2.17.2/ovsdb/table.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/table.c +++ openvswitch-2.17.2/ovsdb/table.c @@ -21,9 +21,9 @@ #include "openvswitch/json.h" #include "column.h" -#include "ovsdb-error.h" -#include "ovsdb-parser.h" -#include "ovsdb-types.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-parser.h" +#include "openvswitch/ovsdb-types.h" #include "row.h" #include "transaction.h" Index: openvswitch-2.17.2/ovsdb/transaction-forward.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/transaction-forward.c +++ openvswitch-2.17.2/ovsdb/transaction-forward.c @@ -18,16 +18,16 @@ #include "transaction-forward.h" -#include "coverage.h" -#include "jsonrpc.h" +#include "internal/coverage.h" +#include "internal/jsonrpc.h" #include "openvswitch/hmap.h" #include "openvswitch/json.h" #include "openvswitch/list.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" #include "ovsdb.h" -#include "ovsdb-cs.h" -#include "util.h" +#include "openvswitch/ovsdb-cs.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(transaction_forward); Index: openvswitch-2.17.2/ovsdb/transaction.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/transaction.c +++ openvswitch-2.17.2/ovsdb/transaction.c @@ -17,22 +17,22 @@ #include "transaction.h" -#include "bitmap.h" +#include "internal/bitmap.h" #include "openvswitch/dynamic-string.h" #include "file.h" -#include "hash.h" +#include "internal/hash.h" #include "monitor.h" #include "openvswitch/hmap.h" #include "openvswitch/json.h" #include "openvswitch/list.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vlog.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "ovsdb.h" #include "row.h" #include "storage.h" #include "table.h" -#include "uuid.h" +#include "internal/uuid.h" VLOG_DEFINE_THIS_MODULE(transaction); Index: openvswitch-2.17.2/ovsdb/trigger.c =================================================================== --- openvswitch-2.17.2.orig/ovsdb/trigger.c +++ openvswitch-2.17.2/ovsdb/trigger.c @@ -22,15 +22,15 @@ #include "file.h" #include "openvswitch/json.h" -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include "ovsdb.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "openvswitch/poll-loop.h" #include "server.h" #include "transaction.h" #include "transaction-forward.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(trigger); Index: openvswitch-2.17.2/tests/oss-fuzz/flow_extract_target.c =================================================================== --- openvswitch-2.17.2.orig/tests/oss-fuzz/flow_extract_target.c +++ openvswitch-2.17.2/tests/oss-fuzz/flow_extract_target.c @@ -1,9 +1,9 @@ #include -#include "classifier.h" +#include "internal/classifier.h" #include #include "fuzzer.h" -#include "dp-packet.h" -#include "flow.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" #include "openvswitch/ofp-match.h" #include "openvswitch/ofp-print.h" #include "openvswitch/match.h" Index: openvswitch-2.17.2/tests/oss-fuzz/json_parser_target.c =================================================================== --- openvswitch-2.17.2.orig/tests/oss-fuzz/json_parser_target.c +++ openvswitch-2.17.2/tests/oss-fuzz/json_parser_target.c @@ -1,8 +1,8 @@ #include #include "fuzzer.h" -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include "openvswitch/json.h" -#include "ovsdb-error.h" +#include "openvswitch/ovsdb-error.h" #include "ovsdb/table.h" #include #include Index: openvswitch-2.17.2/tests/oss-fuzz/miniflow_target.c =================================================================== --- openvswitch-2.17.2.orig/tests/oss-fuzz/miniflow_target.c +++ openvswitch-2.17.2/tests/oss-fuzz/miniflow_target.c @@ -1,13 +1,13 @@ #include -#include "classifier.h" +#include "internal/classifier.h" #include "fuzzer.h" -#include "dp-packet.h" -#include "flow.h" +#include "internal/dp-packet.h" +#include "internal/flow.h" #include "openvswitch/ofp-match.h" #include "openvswitch/ofp-print.h" #include "openvswitch/match.h" #include "classifier-private.h" -#include "util.h" +#include "internal/util.h" /* Returns a copy of 'src'. The caller must eventually free the returned * miniflow with free(). */ Index: openvswitch-2.17.2/tests/oss-fuzz/odp_target.c =================================================================== --- openvswitch-2.17.2.orig/tests/oss-fuzz/odp_target.c +++ openvswitch-2.17.2/tests/oss-fuzz/odp_target.c @@ -4,10 +4,10 @@ #include "odp-util.h" #include #include "openvswitch/dynamic-string.h" -#include "flow.h" +#include "internal/flow.h" #include "openvswitch/match.h" #include "openvswitch/ofpbuf.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/ofp-flow.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/tests/oss-fuzz/ofctl_parse_target.c =================================================================== --- openvswitch-2.17.2.orig/tests/oss-fuzz/ofctl_parse_target.c +++ openvswitch-2.17.2/tests/oss-fuzz/ofctl_parse_target.c @@ -6,7 +6,7 @@ #include "openflow/openflow.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" -#include "util.h" +#include "internal/util.h" static void ofctl_parse_flows__(struct ofputil_flow_mod *fms, size_t n_fms, Index: openvswitch-2.17.2/tests/oss-fuzz/ofp_print_target.c =================================================================== --- openvswitch-2.17.2.orig/tests/oss-fuzz/ofp_print_target.c +++ openvswitch-2.17.2/tests/oss-fuzz/ofp_print_target.c @@ -1,6 +1,6 @@ #include #include "fuzzer.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/tests/ovstest.c =================================================================== --- openvswitch-2.17.2.orig/tests/ovstest.c +++ openvswitch-2.17.2/tests/ovstest.c @@ -21,10 +21,10 @@ #include #include #include -#include "command-line.h" +#include "internal/command-line.h" #include "openvswitch/dynamic-string.h" #include "ovstest.h" -#include "util.h" +#include "internal/util.h" static struct ovs_cmdl_command *commands = NULL; static size_t n_commands = 0; Index: openvswitch-2.17.2/tests/ovstest.h =================================================================== --- openvswitch-2.17.2.orig/tests/ovstest.h +++ openvswitch-2.17.2/tests/ovstest.h @@ -19,7 +19,7 @@ #include "openvswitch/compiler.h" -#include "command-line.h" +#include "internal/command-line.h" /* Overview * ======== Index: openvswitch-2.17.2/tests/test-aes128.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-aes128.c +++ openvswitch-2.17.2/tests/test-aes128.c @@ -19,7 +19,7 @@ #include "aes128.h" #include #include "ovstest.h" -#include "util.h" +#include "internal/util.h" static void hex_to_uint8(const char *input, uint8_t *output, size_t n) Index: openvswitch-2.17.2/tests/test-atomic.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-atomic.c +++ openvswitch-2.17.2/tests/test-atomic.c @@ -16,12 +16,12 @@ #include #undef NDEBUG -#include "fatal-signal.h" -#include "ovs-atomic.h" +#include "internal/fatal-signal.h" +#include "openvswitch/ovs-atomic.h" #include "ovstest.h" -#include "ovs-thread.h" -#include "timeval.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(test_atomic); Index: openvswitch-2.17.2/tests/test-barrier.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-barrier.c +++ openvswitch-2.17.2/tests/test-barrier.c @@ -18,11 +18,11 @@ #include -#include "ovs-thread.h" -#include "ovs-rcu.h" +#include "openvswitch/ovs-thread.h" +#include "openvswitch/ovs-rcu.h" #include "ovstest.h" -#include "random.h" -#include "util.h" +#include "internal/random.h" +#include "internal/util.h" #define DEFAULT_N_THREADS 4 #define NB_STEPS 4 Index: openvswitch-2.17.2/tests/test-bitmap.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-bitmap.c +++ openvswitch-2.17.2/tests/test-bitmap.c @@ -16,11 +16,11 @@ #include #undef NDEBUG -#include "bitmap.h" +#include "internal/bitmap.h" #include -#include "command-line.h" +#include "internal/command-line.h" #include "ovstest.h" -#include "timeval.h" +#include "internal/timeval.h" enum { MAX_BITS = 20 * BITMAP_ULONG_BITS }; Index: openvswitch-2.17.2/tests/test-bundle.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-bundle.c +++ openvswitch-2.17.2/tests/test-bundle.c @@ -17,12 +17,12 @@ #undef NDEBUG #include #include -#include "bundle.h" -#include "flow.h" +#include "internal/bundle.h" +#include "internal/flow.h" #include "openvswitch/ofp-actions.h" #include "openvswitch/ofpbuf.h" #include "ovstest.h" -#include "util.h" +#include "internal/util.h" #define N_FLOWS 50000 #define MAX_MEMBERS 8 /* Maximum supported by this test framework. */ Index: openvswitch-2.17.2/tests/test-byte-order.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-byte-order.c +++ openvswitch-2.17.2/tests/test-byte-order.c @@ -16,7 +16,7 @@ #include #undef NDEBUG -#include "byte-order.h" +#include "internal/byte-order.h" #include #include #include "ovstest.h" Index: openvswitch-2.17.2/tests/test-ccmap.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-ccmap.c +++ openvswitch-2.17.2/tests/test-ccmap.c @@ -23,16 +23,16 @@ #include #include #include -#include "bitmap.h" -#include "command-line.h" +#include "internal/bitmap.h" +#include "internal/command-line.h" #include "fat-rwlock.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "ovstest.h" -#include "ovs-thread.h" -#include "random.h" -#include "timeval.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/random.h" +#include "internal/timeval.h" +#include "internal/util.h" typedef size_t hash_func(int value); Index: openvswitch-2.17.2/tests/test-classifier.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-classifier.c +++ openvswitch-2.17.2/tests/test-classifier.c @@ -28,23 +28,23 @@ #include #undef NDEBUG -#include "classifier.h" +#include "internal/classifier.h" #include #include #include -#include "byte-order.h" +#include "internal/byte-order.h" #include "classifier-private.h" -#include "command-line.h" -#include "fatal-signal.h" -#include "flow.h" +#include "internal/command-line.h" +#include "internal/fatal-signal.h" +#include "internal/flow.h" #include "ovstest.h" -#include "ovs-atomic.h" -#include "ovs-thread.h" -#include "packets.h" -#include "random.h" -#include "timeval.h" -#include "unaligned.h" -#include "util.h" +#include "openvswitch/ovs-atomic.h" +#include "openvswitch/ovs-thread.h" +#include "internal/packets.h" +#include "internal/random.h" +#include "internal/timeval.h" +#include "internal/unaligned.h" +#include "internal/util.h" static bool versioned = false; Index: openvswitch-2.17.2/tests/test-cmap.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-cmap.c +++ openvswitch-2.17.2/tests/test-cmap.c @@ -19,20 +19,20 @@ #include #undef NDEBUG -#include "cmap.h" +#include "internal/cmap.h" #include #include #include -#include "bitmap.h" -#include "command-line.h" +#include "internal/bitmap.h" +#include "internal/command-line.h" #include "fat-rwlock.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" #include "ovstest.h" -#include "ovs-thread.h" -#include "random.h" -#include "timeval.h" -#include "util.h" +#include "openvswitch/ovs-thread.h" +#include "internal/random.h" +#include "internal/timeval.h" +#include "internal/util.h" /* Sample cmap element. */ struct element { Index: openvswitch-2.17.2/tests/test-conntrack.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-conntrack.c +++ openvswitch-2.17.2/tests/test-conntrack.c @@ -17,14 +17,14 @@ #include #include "conntrack.h" -#include "dp-packet.h" -#include "fatal-signal.h" -#include "flow.h" -#include "netdev.h" -#include "ovs-thread.h" +#include "internal/dp-packet.h" +#include "internal/fatal-signal.h" +#include "internal/flow.h" +#include "internal/netdev.h" +#include "openvswitch/ovs-thread.h" #include "ovstest.h" #include "pcap-file.h" -#include "timeval.h" +#include "internal/timeval.h" static const char payload[] = "50540000000a50540000000908004500001c0000000000" "11a4cd0a0101010a0101020001000200080000"; Index: openvswitch-2.17.2/tests/test-csum.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-csum.c +++ openvswitch-2.17.2/tests/test-csum.c @@ -16,7 +16,7 @@ #include #undef NDEBUG -#include "csum.h" +#include "internal/csum.h" #include #include #include @@ -25,12 +25,12 @@ #include #include #include -#include "crc32c.h" +#include "internal/crc32c.h" #include "ovstest.h" -#include "packets.h" -#include "random.h" -#include "unaligned.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/random.h" +#include "internal/unaligned.h" +#include "internal/util.h" struct test_case { char *data; Index: openvswitch-2.17.2/tests/test-flows.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-flows.c +++ openvswitch-2.17.2/tests/test-flows.c @@ -16,22 +16,22 @@ #include #undef NDEBUG -#include "flow.h" +#include "internal/flow.h" #include #include #include #include -#include "classifier.h" +#include "internal/classifier.h" #include "openflow/openflow.h" #include "openvswitch/ofp-match.h" #include "openvswitch/ofp-print.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/vlog.h" #include "ovstest.h" -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "pcap-file.h" -#include "timeval.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/util.h" static void test_flows_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED) Index: openvswitch-2.17.2/tests/test-hash.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-hash.c +++ openvswitch-2.17.2/tests/test-hash.c @@ -16,7 +16,7 @@ #include #undef NDEBUG -#include "hash.h" +#include "internal/hash.h" #include #include #include Index: openvswitch-2.17.2/tests/test-heap.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-heap.c +++ openvswitch-2.17.2/tests/test-heap.c @@ -23,10 +23,10 @@ #include #include #include -#include "command-line.h" +#include "internal/command-line.h" #include "ovstest.h" -#include "random.h" -#include "util.h" +#include "internal/random.h" +#include "internal/util.h" /* Sample heap element. */ struct element { Index: openvswitch-2.17.2/tests/test-hindex.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-hindex.c +++ openvswitch-2.17.2/tests/test-hindex.c @@ -19,13 +19,13 @@ #include #undef NDEBUG -#include "hindex.h" +#include "internal/hindex.h" #include #include -#include "hash.h" +#include "internal/hash.h" #include "ovstest.h" -#include "random.h" -#include "util.h" +#include "internal/random.h" +#include "internal/util.h" /* Sample hindex element. */ struct element { Index: openvswitch-2.17.2/tests/test-hmap.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-hmap.c +++ openvswitch-2.17.2/tests/test-hmap.c @@ -22,10 +22,10 @@ #include "openvswitch/hmap.h" #include #include -#include "hash.h" +#include "internal/hash.h" #include "ovstest.h" -#include "random.h" -#include "util.h" +#include "internal/random.h" +#include "internal/util.h" /* Sample hmap element. */ struct element { Index: openvswitch-2.17.2/tests/test-id-fpool.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-id-fpool.c +++ openvswitch-2.17.2/tests/test-id-fpool.c @@ -21,18 +21,18 @@ #include -#include "command-line.h" +#include "internal/command-line.h" #include "id-fpool.h" -#include "id-pool.h" +#include "internal/id-pool.h" #include "openvswitch/vlog.h" #include "openvswitch/util.h" -#include "ovs-thread.h" -#include "ovs-rcu.h" -#include "ovs-numa.h" +#include "openvswitch/ovs-thread.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-numa.h" #include "ovstest.h" -#include "random.h" -#include "timeval.h" -#include "util.h" +#include "internal/random.h" +#include "internal/timeval.h" +#include "internal/util.h" static void test_id_fpool_alloc(void) Index: openvswitch-2.17.2/tests/test-json.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-json.c +++ openvswitch-2.17.2/tests/test-json.c @@ -22,9 +22,9 @@ #include #include #include "ovstest.h" -#include "random.h" -#include "timeval.h" -#include "util.h" +#include "internal/random.h" +#include "internal/timeval.h" +#include "internal/util.h" /* --pretty: If set, the JSON output is pretty-printed, instead of printed as * compactly as possible. */ Index: openvswitch-2.17.2/tests/test-jsonrpc.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-jsonrpc.c +++ openvswitch-2.17.2/tests/test-jsonrpc.c @@ -16,21 +16,21 @@ #include #undef NDEBUG -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include #include #include #include #include -#include "command-line.h" -#include "daemon.h" +#include "internal/command-line.h" +#include "internal/daemon.h" #include "openvswitch/json.h" #include "ovstest.h" #include "openvswitch/poll-loop.h" -#include "stream-ssl.h" -#include "stream.h" -#include "timeval.h" -#include "util.h" +#include "internal/stream-ssl.h" +#include "internal/stream.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" OVS_NO_RETURN static void usage(void); Index: openvswitch-2.17.2/tests/test-lockfile.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-lockfile.c +++ openvswitch-2.17.2/tests/test-lockfile.c @@ -23,9 +23,9 @@ #include #include #include "ovstest.h" -#include "process.h" -#include "timeval.h" -#include "util.h" +#include "internal/process.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" struct test { Index: openvswitch-2.17.2/tests/test-mpsc-queue.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-mpsc-queue.c +++ openvswitch-2.17.2/tests/test-mpsc-queue.c @@ -21,17 +21,17 @@ #include -#include "command-line.h" +#include "internal/command-line.h" #include "guarded-list.h" #include "mpsc-queue.h" #include "openvswitch/list.h" #include "openvswitch/util.h" #include "openvswitch/vlog.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" #include "ovstest.h" -#include "timeval.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/util.h" struct element { union { Index: openvswitch-2.17.2/tests/test-multipath.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-multipath.c +++ openvswitch-2.17.2/tests/test-multipath.c @@ -21,11 +21,11 @@ #include #include #include -#include "flow.h" +#include "internal/flow.h" #include "multipath.h" #include "openvswitch/ofp-actions.h" #include "ovstest.h" -#include "util.h" +#include "internal/util.h" static void test_multipath_main(int argc, char *argv[]) Index: openvswitch-2.17.2/tests/test-netflow.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-netflow.c +++ openvswitch-2.17.2/tests/test-netflow.c @@ -22,16 +22,16 @@ #include #include #include -#include "command-line.h" -#include "daemon.h" +#include "internal/command-line.h" +#include "internal/daemon.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/ofpbuf.h" #include "ovstest.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "socket-util.h" -#include "unixctl.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" OVS_NO_RETURN static void usage(void); Index: openvswitch-2.17.2/tests/test-netlink-policy.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-netlink-policy.c +++ openvswitch-2.17.2/tests/test-netlink-policy.c @@ -18,11 +18,11 @@ #include -#include "netlink.h" +#include "internal/netlink.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/types.h" #include "ovstest.h" -#include "util.h" +#include "internal/util.h" struct nlattr_fixture { struct nlattr nlattr; Index: openvswitch-2.17.2/tests/test-odp.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-odp.c +++ openvswitch-2.17.2/tests/test-odp.c @@ -19,11 +19,11 @@ #include "odp-util.h" #include #include "openvswitch/dynamic-string.h" -#include "flow.h" +#include "internal/flow.h" #include "openvswitch/match.h" #include "openvswitch/ofpbuf.h" #include "ovstest.h" -#include "util.h" +#include "internal/util.h" #include "openvswitch/ofp-flow.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/tests/test-ofpbuf.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-ofpbuf.c +++ openvswitch-2.17.2/tests/test-ofpbuf.c @@ -19,7 +19,7 @@ #include #include "openvswitch/ofpbuf.h" #include "ovstest.h" -#include "util.h" +#include "internal/util.h" #define BUF_SIZE 100 #define HDR_OFS 10 Index: openvswitch-2.17.2/tests/test-ovsdb.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-ovsdb.c +++ openvswitch-2.17.2/tests/test-ovsdb.c @@ -23,15 +23,15 @@ #include #include -#include "byte-order.h" -#include "command-line.h" +#include "internal/byte-order.h" +#include "internal/command-line.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "jsonrpc.h" -#include "ovsdb-data.h" -#include "ovsdb-error.h" -#include "ovsdb-idl.h" -#include "ovsdb-types.h" +#include "internal/jsonrpc.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-error.h" +#include "openvswitch/ovsdb-idl.h" +#include "openvswitch/ovsdb-types.h" #include "ovsdb/column.h" #include "ovsdb/condition.h" #include "ovsdb/file.h" @@ -46,11 +46,11 @@ #include "ovsdb/transaction.h" #include "ovsdb/trigger.h" #include "openvswitch/poll-loop.h" -#include "stream.h" -#include "svec.h" +#include "internal/stream.h" +#include "internal/svec.h" #include "tests/idltest.h" -#include "timeval.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(test_ovsdb); Index: openvswitch-2.17.2/tests/test-packets.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-packets.c +++ openvswitch-2.17.2/tests/test-packets.c @@ -16,7 +16,7 @@ #include #undef NDEBUG -#include "packets.h" +#include "internal/packets.h" #include #include #include Index: openvswitch-2.17.2/tests/test-random.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-random.c +++ openvswitch-2.17.2/tests/test-random.c @@ -16,7 +16,7 @@ #include #undef NDEBUG -#include "random.h" +#include "internal/random.h" #include #include #include "ovstest.h" Index: openvswitch-2.17.2/tests/test-rcu.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-rcu.c +++ openvswitch-2.17.2/tests/test-rcu.c @@ -16,11 +16,11 @@ #include #undef NDEBUG -#include "fatal-signal.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" +#include "internal/fatal-signal.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" #include "ovstest.h" -#include "util.h" +#include "internal/util.h" static void * quiescer_main(void *aux OVS_UNUSED) Index: openvswitch-2.17.2/tests/test-reconnect.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-reconnect.c +++ openvswitch-2.17.2/tests/test-reconnect.c @@ -21,11 +21,11 @@ #include #include #include +#include "internal/command-line.h" #include "openvswitch/compiler.h" -#include "command-line.h" #include "ovstest.h" -#include "svec.h" -#include "util.h" +#include "internal/svec.h" +#include "internal/util.h" #include "openvswitch/vlog.h" static struct reconnect *reconnect; Index: openvswitch-2.17.2/tests/test-rstp.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-rstp.c +++ openvswitch-2.17.2/tests/test-rstp.c @@ -9,8 +9,8 @@ #include #include "openvswitch/ofpbuf.h" #include "ovstest.h" -#include "dp-packet.h" -#include "packets.h" +#include "internal/dp-packet.h" +#include "internal/packets.h" #include "openvswitch/vlog.h" #define MAX_PORTS 10 Index: openvswitch-2.17.2/tests/test-sflow.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-sflow.c +++ openvswitch-2.17.2/tests/test-sflow.c @@ -27,16 +27,16 @@ #include #include #include -#include "command-line.h" -#include "daemon.h" +#include "internal/command-line.h" +#include "internal/daemon.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/ofpbuf.h" #include "ovstest.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "socket-util.h" -#include "unixctl.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" OVS_NO_RETURN static void usage(void); Index: openvswitch-2.17.2/tests/test-sha1.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-sha1.c +++ openvswitch-2.17.2/tests/test-sha1.c @@ -23,8 +23,8 @@ #include #include #include "ovstest.h" -#include "random.h" -#include "util.h" +#include "internal/random.h" +#include "internal/util.h" struct test_vector { char *data; Index: openvswitch-2.17.2/tests/test-skiplist.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-skiplist.c +++ openvswitch-2.17.2/tests/test-skiplist.c @@ -22,9 +22,9 @@ #include #include #include "ovstest.h" -#include "skiplist.h" -#include "random.h" -#include "util.h" +#include "internal/skiplist.h" +#include "internal/random.h" +#include "internal/util.h" static void test_skiplist_main(int argc OVS_UNUSED, char *argv[] OVS_UNUSED); Index: openvswitch-2.17.2/tests/test-stopwatch.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-stopwatch.c +++ openvswitch-2.17.2/tests/test-stopwatch.c @@ -16,12 +16,12 @@ #include #undef NDEBUG -#include "stopwatch.h" +#include "internal/stopwatch.h" #include #include #include #include "ovstest.h" -#include "util.h" +#include "internal/util.h" #define MAX_SAMPLES 100 #define UNIT SW_MS Index: openvswitch-2.17.2/tests/test-stp.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-stp.c +++ openvswitch-2.17.2/tests/test-stp.c @@ -23,10 +23,10 @@ #include #include #include -#include "dp-packet.h" +#include "internal/dp-packet.h" #include "openvswitch/ofpbuf.h" #include "ovstest.h" -#include "packets.h" +#include "internal/packets.h" #include "openvswitch/vlog.h" struct bpdu { Index: openvswitch-2.17.2/tests/test-stream.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-stream.c +++ openvswitch-2.17.2/tests/test-stream.c @@ -16,10 +16,10 @@ #include -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "openvswitch/vlog.h" -#include "stream.h" -#include "util.h" +#include "internal/stream.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(test_stream); Index: openvswitch-2.17.2/tests/test-unix-socket.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-unix-socket.c +++ openvswitch-2.17.2/tests/test-unix-socket.c @@ -16,12 +16,12 @@ #include #undef NDEBUG -#include "socket-util.h" +#include "internal/socket-util.h" #include #include #include #include "ovstest.h" -#include "util.h" +#include "internal/util.h" static void test_unix_socket_main(int argc, char *argv[]) Index: openvswitch-2.17.2/tests/test-unixctl.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-unixctl.c +++ openvswitch-2.17.2/tests/test-unixctl.c @@ -17,14 +17,14 @@ #include -#include "command-line.h" -#include "daemon.h" -#include "fatal-signal.h" +#include "internal/command-line.h" +#include "internal/daemon.h" +#include "internal/fatal-signal.h" #include "openvswitch/vlog.h" #include "ovstest.h" #include "openvswitch/poll-loop.h" -#include "unixctl.h" -#include "util.h" +#include "internal/unixctl.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(test_unixctl); Index: openvswitch-2.17.2/tests/test-util.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-util.c +++ openvswitch-2.17.2/tests/test-util.c @@ -16,17 +16,17 @@ #include #undef NDEBUG -#include "util.h" +#include "internal/util.h" #include #include #include #include #include #include -#include "byte-order.h" -#include "command-line.h" +#include "internal/byte-order.h" +#include "internal/command-line.h" #include "ovstest.h" -#include "random.h" +#include "internal/random.h" #include "sat-math.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/tests/test-uuid.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-uuid.c +++ openvswitch-2.17.2/tests/test-uuid.c @@ -16,8 +16,8 @@ #include #undef NDEBUG -#include "util.h" -#include "uuid.h" +#include "internal/util.h" +#include "internal/uuid.h" #include #include "ovstest.h" Index: openvswitch-2.17.2/tests/test-vconn.c =================================================================== --- openvswitch-2.17.2.orig/tests/test-vconn.c +++ openvswitch-2.17.2/tests/test-vconn.c @@ -22,8 +22,8 @@ #include #include #include -#include "command-line.h" -#include "fatal-signal.h" +#include "internal/command-line.h" +#include "internal/fatal-signal.h" #include "openflow/openflow.h" #include "openvswitch/ofp-msgs.h" #include "openvswitch/ofpbuf.h" @@ -31,11 +31,11 @@ #include "openvswitch/vlog.h" #include "ovstest.h" #include "openvswitch/poll-loop.h" -#include "socket-util.h" -#include "stream.h" -#include "stream-ssl.h" -#include "timeval.h" -#include "util.h" +#include "internal/socket-util.h" +#include "internal/stream.h" +#include "internal/stream-ssl.h" +#include "internal/timeval.h" +#include "internal/util.h" #define TIMEOUT 10 Index: openvswitch-2.17.2/utilities/nlmon.c =================================================================== --- openvswitch-2.17.2.orig/utilities/nlmon.c +++ openvswitch-2.17.2/utilities/nlmon.c @@ -23,13 +23,13 @@ #include #include #include -#include "netlink.h" +#include "internal/netlink.h" #include "netlink-socket.h" #include "netnsid.h" #include "openvswitch/ofpbuf.h" #include "openvswitch/poll-loop.h" -#include "timeval.h" -#include "util.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" static const struct nl_policy rtnlgrp_link_policy[] = { Index: openvswitch-2.17.2/utilities/ovs-appctl.c =================================================================== --- openvswitch-2.17.2.orig/utilities/ovs-appctl.c +++ openvswitch-2.17.2/utilities/ovs-appctl.c @@ -22,15 +22,15 @@ #include #include -#include "command-line.h" -#include "daemon.h" -#include "dirs.h" +#include "internal/command-line.h" +#include "internal/daemon.h" +#include "internal/dirs.h" #include "openvswitch/dynamic-string.h" -#include "jsonrpc.h" -#include "process.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/jsonrpc.h" +#include "internal/process.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/vlog.h" static void usage(void); Index: openvswitch-2.17.2/utilities/ovs-dpctl.c =================================================================== --- openvswitch-2.17.2.orig/utilities/ovs-dpctl.c +++ openvswitch-2.17.2/utilities/ovs-dpctl.c @@ -32,14 +32,14 @@ #include #include "openvswitch/compiler.h" -#include "command-line.h" -#include "dirs.h" +#include "internal/command-line.h" +#include "internal/dirs.h" #include "dpctl.h" -#include "fatal-signal.h" +#include "internal/fatal-signal.h" #include "odp-util.h" -#include "packets.h" -#include "timeval.h" -#include "util.h" +#include "internal/packets.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vlog.h" static struct dpctl_params dpctl_p; Index: openvswitch-2.17.2/utilities/ovs-ofctl.c =================================================================== --- openvswitch-2.17.2.orig/utilities/ovs-ofctl.c +++ openvswitch-2.17.2/utilities/ovs-ofctl.c @@ -29,16 +29,16 @@ #include #include -#include "byte-order.h" -#include "classifier.h" -#include "command-line.h" -#include "daemon.h" -#include "colors.h" +#include "internal/byte-order.h" +#include "internal/classifier.h" +#include "internal/daemon.h" +#include "internal/command-line.h" +#include "internal/colors.h" #include "openvswitch/compiler.h" -#include "dirs.h" -#include "dp-packet.h" -#include "fatal-signal.h" -#include "nx-match.h" +#include "internal/dirs.h" +#include "internal/dp-packet.h" +#include "internal/fatal-signal.h" +#include "internal/nx-match.h" #include "odp-util.h" #include "ofp-version-opt.h" #include "ofproto/ofproto.h" @@ -65,16 +65,16 @@ #include "openvswitch/shash.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" -#include "packets.h" +#include "internal/packets.h" #include "pcap-file.h" #include "openvswitch/poll-loop.h" -#include "random.h" -#include "sort.h" -#include "stream-ssl.h" -#include "socket-util.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/random.h" +#include "internal/sort.h" +#include "internal/stream-ssl.h" +#include "internal/socket-util.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(ofctl); Index: openvswitch-2.17.2/utilities/ovs-testcontroller.c =================================================================== --- openvswitch-2.17.2.orig/utilities/ovs-testcontroller.c +++ openvswitch-2.17.2/utilities/ovs-testcontroller.c @@ -24,25 +24,25 @@ #include #include +#include "internal/command-line.h" #include "openvswitch/compiler.h" -#include "command-line.h" -#include "daemon.h" -#include "fatal-signal.h" +#include "internal/daemon.h" +#include "internal/fatal-signal.h" #include "learning-switch.h" #include "ofp-version-opt.h" #include "openvswitch/ofpbuf.h" #include "openflow/openflow.h" #include "openvswitch/poll-loop.h" #include "openvswitch/rconn.h" -#include "simap.h" -#include "stream-ssl.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/simap.h" +#include "internal/stream-ssl.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" +#include "internal/util.h" #include "openvswitch/ofp-flow.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" -#include "socket-util.h" +#include "internal/socket-util.h" VLOG_DEFINE_THIS_MODULE(controller); Index: openvswitch-2.17.2/utilities/ovs-vsctl.c =================================================================== --- openvswitch-2.17.2.orig/utilities/ovs-vsctl.c +++ openvswitch-2.17.2/utilities/ovs-vsctl.c @@ -27,32 +27,32 @@ #include #include -#include "db-ctl-base.h" +#include "internal/db-ctl-base.h" #include "openvswitch/compiler.h" -#include "command-line.h" -#include "dirs.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/command-line.h" +#include "internal/dirs.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" #include "openvswitch/ofp-parse.h" #include "openvswitch/poll-loop.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" -#include "ovsdb-data.h" -#include "ovsdb-idl.h" -#include "process.h" -#include "simap.h" -#include "stream.h" -#include "stream-ssl.h" -#include "smap.h" -#include "sset.h" -#include "svec.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-idl.h" +#include "internal/process.h" +#include "internal/simap.h" +#include "internal/stream.h" +#include "internal/stream-ssl.h" +#include "internal/smap.h" +#include "internal/sset.h" +#include "internal/svec.h" #include "lib/vswitch-idl.h" -#include "table.h" -#include "timeval.h" -#include "util.h" +#include "internal/table.h" +#include "internal/timeval.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(vsctl); Index: openvswitch-2.17.2/vswitchd/bridge.c =================================================================== --- openvswitch-2.17.2.orig/vswitchd/bridge.c +++ openvswitch-2.17.2/vswitchd/bridge.c @@ -21,25 +21,25 @@ #include "async-append.h" #include "bfd.h" -#include "bitmap.h" +#include "internal/bitmap.h" #include "cfm.h" #include "connectivity.h" -#include "coverage.h" -#include "daemon.h" -#include "dirs.h" +#include "internal/coverage.h" +#include "internal/daemon.h" +#include "internal/dirs.h" #include "dpif.h" #include "dpdk.h" -#include "hash.h" +#include "internal/hash.h" #include "openvswitch/hmap.h" -#include "hmapx.h" +#include "internal/hmapx.h" #include "if-notifier.h" -#include "jsonrpc.h" +#include "internal/jsonrpc.h" #include "lacp.h" #include "mac-learning.h" -#include "mcast-snooping.h" -#include "netdev.h" +#include "internal/mcast-snooping.h" +#include "internal/netdev.h" #include "netdev-offload.h" -#include "nx-match.h" +#include "internal/nx-match.h" #include "ofproto/bond.h" #include "ofproto/ofproto.h" #include "openvswitch/dynamic-string.h" @@ -50,24 +50,24 @@ #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" #include "ovs-lldp.h" -#include "ovs-numa.h" -#include "packets.h" +#include "openvswitch/ovs-numa.h" +#include "internal/packets.h" #include "openvswitch/poll-loop.h" -#include "seq.h" +#include "internal/seq.h" #include "sflow_api.h" #include "sha1.h" #include "openvswitch/shash.h" -#include "smap.h" -#include "socket-util.h" -#include "stream.h" -#include "stream-ssl.h" -#include "sset.h" +#include "internal/smap.h" +#include "internal/socket-util.h" +#include "internal/stream.h" +#include "internal/stream-ssl.h" +#include "internal/sset.h" #include "system-stats.h" -#include "timeval.h" +#include "internal/timeval.h" #include "tnl-ports.h" #include "userspace-tso.h" -#include "util.h" -#include "unixctl.h" +#include "internal/util.h" +#include "internal/unixctl.h" #include "lib/vswitch-idl.h" #include "xenserver.h" #include "vlan-bitmap.h" Index: openvswitch-2.17.2/vswitchd/ovs-vswitchd.c =================================================================== --- openvswitch-2.17.2.orig/vswitchd/ovs-vswitchd.c +++ openvswitch-2.17.2/vswitchd/ovs-vswitchd.c @@ -27,32 +27,32 @@ #include "bridge.h" #include "openvswitch/compiler.h" -#include "command-line.h" -#include "daemon.h" -#include "dirs.h" +#include "internal/command-line.h" +#include "internal/daemon.h" +#include "internal/dirs.h" #include "dpif.h" #include "dummy.h" -#include "fatal-signal.h" -#include "memory.h" -#include "netdev.h" +#include "internal/fatal-signal.h" +#include "internal/memory.h" +#include "internal/netdev.h" #include "openflow/openflow.h" -#include "ovsdb-idl.h" -#include "ovs-rcu.h" +#include "openvswitch/ovsdb-idl.h" +#include "openvswitch/ovs-rcu.h" #include "ovs-router.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" -#include "simap.h" -#include "stream-ssl.h" -#include "stream.h" -#include "svec.h" -#include "timeval.h" -#include "unixctl.h" -#include "util.h" +#include "internal/simap.h" +#include "internal/stream-ssl.h" +#include "internal/stream.h" +#include "internal/svec.h" +#include "internal/timeval.h" +#include "internal/unixctl.h" #include "openvswitch/usdt-probes.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" #include "lib/vswitch-idl.h" #include "lib/dns-resolve.h" +#include "internal/util.h" VLOG_DEFINE_THIS_MODULE(vswitchd); Index: openvswitch-2.17.2/vswitchd/system-stats.c =================================================================== --- openvswitch-2.17.2.orig/vswitchd/system-stats.c +++ openvswitch-2.17.2/vswitchd/system-stats.c @@ -31,19 +31,19 @@ #endif #include -#include "daemon.h" -#include "dirs.h" +#include "internal/daemon.h" +#include "internal/dirs.h" #include "openvswitch/dynamic-string.h" #include "openvswitch/json.h" -#include "latch.h" +#include "internal/latch.h" #include "openvswitch/ofpbuf.h" -#include "ovs-rcu.h" -#include "ovs-thread.h" +#include "openvswitch/ovs-rcu.h" +#include "openvswitch/ovs-thread.h" #include "openvswitch/poll-loop.h" #include "openvswitch/shash.h" -#include "process.h" -#include "smap.h" -#include "timeval.h" +#include "internal/process.h" +#include "internal/smap.h" +#include "internal/timeval.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(system_stats); Index: openvswitch-2.17.2/vswitchd/xenserver.c =================================================================== --- openvswitch-2.17.2.orig/vswitchd/xenserver.c +++ openvswitch-2.17.2/vswitchd/xenserver.c @@ -22,8 +22,8 @@ #include #include #include "openvswitch/dynamic-string.h" -#include "process.h" -#include "util.h" +#include "internal/process.h" +#include "internal/util.h" #include "openvswitch/vlog.h" VLOG_DEFINE_THIS_MODULE(xenserver); Index: openvswitch-2.17.2/vtep/vtep-ctl.c =================================================================== --- openvswitch-2.17.2.orig/vtep/vtep-ctl.c +++ openvswitch-2.17.2/vtep/vtep-ctl.c @@ -27,27 +27,27 @@ #include #include -#include "db-ctl-base.h" +#include "internal/db-ctl-base.h" #include "openvswitch/compiler.h" #include "openvswitch/dynamic-string.h" -#include "command-line.h" -#include "fatal-signal.h" -#include "hash.h" +#include "internal/command-line.h" +#include "internal/fatal-signal.h" +#include "internal/hash.h" #include "openvswitch/json.h" -#include "ovsdb-data.h" -#include "ovsdb-idl.h" +#include "openvswitch/ovsdb-data.h" +#include "openvswitch/ovsdb-idl.h" #include "openvswitch/poll-loop.h" -#include "process.h" -#include "stream.h" -#include "stream-ssl.h" -#include "smap.h" -#include "sset.h" -#include "svec.h" +#include "internal/process.h" +#include "internal/stream.h" +#include "internal/stream-ssl.h" +#include "internal/smap.h" +#include "internal/sset.h" +#include "internal/svec.h" #include "vtep/vtep-idl.h" -#include "table.h" -#include "timeval.h" -#include "util.h" +#include "internal/table.h" +#include "internal/timeval.h" +#include "internal/util.h" #include "openvswitch/vconn.h" #include "openvswitch/vlog.h" Index: openvswitch-2.17.2/include/internal/bundle.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/bundle.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2011, 2012, 2013, 2014, 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. + */ + +#ifndef BUNDLE_H +#define BUNDLE_H 1 + +#include +#include +#include +#include +#include +#include + +#include "openvswitch/compiler.h" +#include "openflow/nicira-ext.h" +#include "openvswitch/ofp-errors.h" +#include "openvswitch/types.h" + +struct ds; +struct flow; +struct flow_wildcards; +struct match; +struct ofpact_bundle; +struct ofpbuf; +struct ofputil_port_map; + +/* NXAST_BUNDLE helper functions. + * + * See lib/ofp-actions.c for NXAST_BUNDLE specification. */ + +#define BUNDLE_MAX_MEMBERS 2048 + +ofp_port_t bundle_execute(const struct ofpact_bundle *, const struct flow *, + struct flow_wildcards *wc, + bool (*member_enabled)(ofp_port_t ofp_port, void *aux), + void *aux); +enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports, + const struct match *); +char *bundle_parse(const char *, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) OVS_WARN_UNUSED_RESULT; +char *bundle_parse_load(const char *, const struct ofputil_port_map *port_map, + struct ofpbuf *ofpacts) + OVS_WARN_UNUSED_RESULT; +void bundle_format(const struct ofpact_bundle *, + const struct ofputil_port_map *, struct ds *); + +#endif /* bundle.h */ Index: openvswitch-2.17.2/include/internal/byte-order.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/byte-order.h @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2008, 2010, 2011, 2013, 2016 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 BYTE_ORDER_H +#define BYTE_ORDER_H 1 + +#include +#include +#include +#include +#include "openvswitch/types.h" + +#ifndef __CHECKER__ +#if !(defined(_WIN32) || defined(htonll)) +static inline ovs_be64 +htonll(uint64_t n) +{ + return htonl(1) == 1 ? n : ((uint64_t) htonl(n) << 32) | htonl(n >> 32); +} + +static inline uint64_t +ntohll(ovs_be64 n) +{ + return htonl(1) == 1 ? n : ((uint64_t) ntohl(n) << 32) | ntohl(n >> 32); +} +#endif /* !(defined(_WIN32) || defined(htonll)) */ +#else +/* Making sparse happy with these functions also makes them unreadable, so + * don't bother to show it their implementations. */ +ovs_be64 htonll(uint64_t); +uint64_t ntohll(ovs_be64); +#endif + +static inline ovs_be128 +hton128(const ovs_u128 src) +{ + ovs_be128 dst; + + dst.be64.hi = htonll(src.u64.hi); + dst.be64.lo = htonll(src.u64.lo); + return dst; +} + +static inline ovs_u128 +ntoh128(const ovs_be128 src) +{ + ovs_u128 dst; + + dst.u64.hi = ntohll(src.be64.hi); + dst.u64.lo = ntohll(src.be64.lo); + return dst; +} + +static inline uint32_t +uint32_byteswap(uint32_t crc) { + return (((crc & 0x000000ff) << 24) | + ((crc & 0x0000ff00) << 8) | + ((crc & 0x00ff0000) >> 8) | + ((crc & 0xff000000) >> 24)); +} + +/* These macros may substitute for htons(), htonl(), and htonll() in contexts + * where function calls are not allowed, such as case labels. They should not + * be used elsewhere because all of them evaluate their argument many times. */ +#if defined(WORDS_BIGENDIAN) || __CHECKER__ +#define CONSTANT_HTONS(VALUE) ((OVS_FORCE ovs_be16) ((VALUE) & 0xffff)) +#define CONSTANT_HTONL(VALUE) ((OVS_FORCE ovs_be32) ((VALUE) & 0xffffffff)) +#define CONSTANT_HTONLL(VALUE) \ + ((OVS_FORCE ovs_be64) ((VALUE) & UINT64_C(0xffffffffffffffff))) +#else +#define CONSTANT_HTONS(VALUE) \ + (((((ovs_be16) (VALUE)) & 0xff00) >> 8) | \ + ((((ovs_be16) (VALUE)) & 0x00ff) << 8)) +#define CONSTANT_HTONL(VALUE) \ + (((((ovs_be32) (VALUE)) & 0x000000ff) << 24) | \ + ((((ovs_be32) (VALUE)) & 0x0000ff00) << 8) | \ + ((((ovs_be32) (VALUE)) & 0x00ff0000) >> 8) | \ + ((((ovs_be32) (VALUE)) & 0xff000000) >> 24)) +#define CONSTANT_HTONLL(VALUE) \ + (((((ovs_be64) (VALUE)) & UINT64_C(0x00000000000000ff)) << 56) | \ + ((((ovs_be64) (VALUE)) & UINT64_C(0x000000000000ff00)) << 40) | \ + ((((ovs_be64) (VALUE)) & UINT64_C(0x0000000000ff0000)) << 24) | \ + ((((ovs_be64) (VALUE)) & UINT64_C(0x00000000ff000000)) << 8) | \ + ((((ovs_be64) (VALUE)) & UINT64_C(0x000000ff00000000)) >> 8) | \ + ((((ovs_be64) (VALUE)) & UINT64_C(0x0000ff0000000000)) >> 24) | \ + ((((ovs_be64) (VALUE)) & UINT64_C(0x00ff000000000000)) >> 40) | \ + ((((ovs_be64) (VALUE)) & UINT64_C(0xff00000000000000)) >> 56)) +#endif + +/* Returns the ovs_be32 that you would get from: + * + * union { uint8_t b[4]; ovs_be32 be32; } x = { .b = { b0, b1, b2, b3 } }; + * return x.be32; + * + * but without the undefined behavior. */ +static inline ovs_be32 +bytes_to_be32(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) +{ +#if WORDS_BIGENDIAN + uint32_t x = ((uint32_t) b0 << 24) | (b1 << 16) | (b2 << 8) | b3; +#else + uint32_t x = ((uint32_t) b3 << 24) | (b2 << 16) | (b1 << 8) | b0; +#endif + return (OVS_FORCE ovs_be32) x; +} + +/* These functions zero-extend big-endian values to longer ones, + * or truncate long big-endian value to shorter ones. */ +#ifndef __CHECKER__ +#if WORDS_BIGENDIAN +static inline ovs_be32 be16_to_be32(ovs_be16 x) { return x; } +static inline ovs_be64 be16_to_be64(ovs_be16 x) { return x; } +static inline ovs_be64 be32_to_be64(ovs_be32 x) { return x; } +static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x; } +static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x; } +static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x; } +#else /* !WORDS_BIGENDIAN */ +static inline ovs_be32 be16_to_be32(ovs_be16 x) { return (ovs_be32) x << 16; } +static inline ovs_be64 be16_to_be64(ovs_be16 x) { return (ovs_be64) x << 48; } +static inline ovs_be64 be32_to_be64(ovs_be32 x) { return (ovs_be64) x << 32; } +static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x >> 32; } +static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x >> 48; } +static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x >> 16; } +#endif /* !WORDS_BIGENDIAN */ +#else /* __CHECKER__ */ +/* Making sparse happy with these functions also makes them unreadable, so + * don't bother to show it their implementations. */ +ovs_be32 be16_to_be32(ovs_be16); +ovs_be64 be16_to_be64(ovs_be16); +ovs_be64 be32_to_be64(ovs_be32); +ovs_be32 be64_to_be32(ovs_be64); +ovs_be16 be64_to_be16(ovs_be64); +ovs_be16 be32_to_be16(ovs_be32); +#endif + +#endif /* byte-order.h */ Index: openvswitch-2.17.2/include/internal/colors.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/colors.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016 6WIND S.A. + * + * 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 COLORS_H +#define COLORS_H 1 + +#include + +struct colors { + /* Color codes for various situation. Each of these is a fully formed + * Select Graphic Rendition (SGR, "\33[...m") start string for the + * appropriate color. + */ + char *actions; + char *drop; + char *learn; + char *param; + char *paren; + char *special; + char *value; + + /* SGR end string. */ + char *end; +}; +extern struct colors colors; + +void colors_init(bool enable_color); + +#endif /* colors.h */ Index: openvswitch-2.17.2/include/internal/command-line.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/command-line.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2008, 2009, 2010 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 COMMAND_LINE_H +#define COMMAND_LINE_H 1 + +/* Utilities for command-line parsing. */ + +#include "openvswitch/compiler.h" + +struct option; + +/* Command handler context */ +struct ovs_cmdl_context { + /* number of command line arguments */ + int argc; + /* array of command line arguments */ + char **argv; + /* private context data defined by the API user */ + void *pvt; +}; + +typedef void (*ovs_cmdl_handler)(struct ovs_cmdl_context *); + +struct ovs_cmdl_command { + const char *name; + const char *usage; + int min_args; + int max_args; + ovs_cmdl_handler handler; + enum { OVS_RO, OVS_RW } mode; /* Does this command modify things? */ +}; + +char *ovs_cmdl_long_options_to_short_options(const struct option *options); + +struct ovs_cmdl_parsed_option { + const struct option *o; + char *arg; +}; +char *ovs_cmdl_parse_all(int argc, char *argv[], const struct option *, + struct ovs_cmdl_parsed_option **, size_t *) + OVS_WARN_UNUSED_RESULT; + +char **ovs_cmdl_env_parse_all(int *argcp, char *argv_[], + const char *env_options); + +void ovs_cmdl_print_options(const struct option *options); +void ovs_cmdl_print_commands(const struct ovs_cmdl_command *commands); + +void ovs_cmdl_run_command(struct ovs_cmdl_context *, + const struct ovs_cmdl_command[]); +void ovs_cmdl_run_command_read_only(struct ovs_cmdl_context *, + const struct ovs_cmdl_command[]); + +void ovs_cmdl_proctitle_init(int argc, char **argv); +#if defined(__FreeBSD__) || defined(__NetBSD__) +#define ovs_cmdl_proctitle_set setproctitle +#else +void ovs_cmdl_proctitle_set(const char *, ...) + OVS_PRINTF_FORMAT(1, 2); +#endif +void ovs_cmdl_proctitle_restore(void); + +#endif /* command-line.h */ Index: openvswitch-2.17.2/include/internal/crc32c.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/crc32c.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2012 The University of Waikato. + * Author: Joe Stringer + * + * 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 CRC32C_H +#define CRC32C_H 1 + +#include "openvswitch/types.h" + +ovs_be32 crc32c(const uint8_t *data, size_t); + +#endif /* crc32c.h */ Index: openvswitch-2.17.2/include/internal/csum.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/csum.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2008, 2011, 2015 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef CSUM_H +#define CSUM_H 1 + +#include +#include +#include "openvswitch/types.h" + +struct in6_addr; + +ovs_be16 csum(const void *, size_t); +uint32_t csum_continue(uint32_t partial, const void *, size_t); +ovs_be16 csum_finish(uint32_t partial); +ovs_be16 recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 new_u16); +ovs_be16 recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32); +ovs_be16 recalc_csum48(ovs_be16 old_csum, const struct eth_addr old_mac, + const struct eth_addr new_mac); +ovs_be16 recalc_csum128(ovs_be16 old_csum, ovs_16aligned_be32 old_u32[4], + const struct in6_addr *); + +#ifndef __CHECKER__ +/* Adds the 16 bits in 'new' to the partial IP checksum 'partial' and returns + * the updated checksum. (To start a new checksum, pass 0 for 'partial'. To + * obtain the finished checksum, pass the return value to csum_finish().) */ +static inline uint32_t +csum_add16(uint32_t partial, ovs_be16 new) +{ + return partial + new; +} + +/* Adds the 32 bits in 'new' to the partial IP checksum 'partial' and returns + * the updated checksum. (To start a new checksum, pass 0 for 'partial'. To + * obtain the finished checksum, pass the return value to csum_finish().) */ +static inline uint32_t +csum_add32(uint32_t partial, ovs_be32 new) +{ + return partial + (new >> 16) + (new & 0xffff); +} +#else +uint32_t csum_add16(uint32_t partial, ovs_be16); +uint32_t csum_add32(uint32_t partial, ovs_be32); +#endif + +#endif /* csum.h */ Index: openvswitch-2.17.2/include/internal/daemon.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/daemon.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DAEMON_H +#define DAEMON_H 1 + +#include +#include +#include + +/* This file provides an interface for utilities to run in the background + * as daemons on POSIX platforms like Linux or as services on Windows platform. + * Some of the functionalities defined in this file are only applicable to + * POSIX platforms and some are applicable only on Windows. As such, the + * function definitions unique to each platform are separated out with + * ifdef macros. More descriptive comments on individual functions are provided + * in daemon-unix.c (for POSIX platforms) and daemon-windows.c (for Windows). + + * The DAEMON_OPTION_ENUMS, DAEMON_LONG_OPTIONS and DAEMON_OPTION_HANDLERS + * macros are useful for parsing command-line options in individual utilities. + * For e.g., the command-line option "--monitor" is recognized on Linux + * and results in calling the daemon_set_monitor() function. The same option is + * not recognized on Windows platform. + */ + +#ifndef _WIN32 +#define DAEMON_OPTION_ENUMS \ + OPT_DETACH, \ + OPT_NO_SELF_CONFINEMENT, \ + OPT_NO_CHDIR, \ + OPT_OVERWRITE_PIDFILE, \ + OPT_PIDFILE, \ + OPT_MONITOR, \ + OPT_USER_GROUP + +#define DAEMON_LONG_OPTIONS \ + {"detach", no_argument, NULL, OPT_DETACH}, \ + {"no-self-confinement", no_argument, NULL, OPT_NO_SELF_CONFINEMENT}, \ + {"no-chdir", no_argument, NULL, OPT_NO_CHDIR}, \ + {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \ + {"overwrite-pidfile", no_argument, NULL, OPT_OVERWRITE_PIDFILE}, \ + {"monitor", no_argument, NULL, OPT_MONITOR}, \ + {"user", required_argument, NULL, OPT_USER_GROUP} + +#define DAEMON_OPTION_HANDLERS \ + case OPT_DETACH: \ + set_detach(); \ + break; \ + \ + case OPT_NO_SELF_CONFINEMENT: \ + daemon_disable_self_confinement(); \ + break; \ + \ + case OPT_NO_CHDIR: \ + set_no_chdir(); \ + break; \ + \ + case OPT_PIDFILE: \ + set_pidfile(optarg); \ + break; \ + \ + case OPT_OVERWRITE_PIDFILE: \ + ignore_existing_pidfile(); \ + break; \ + \ + case OPT_MONITOR: \ + daemon_set_monitor(); \ + break; \ + \ + case OPT_USER_GROUP: \ + daemon_set_new_user(optarg); \ + break; + +#define DAEMON_OPTION_CASES \ + case OPT_DETACH: \ + case OPT_NO_SELF_CONFINEMENT: \ + case OPT_NO_CHDIR: \ + case OPT_PIDFILE: \ + case OPT_OVERWRITE_PIDFILE: \ + case OPT_MONITOR: \ + case OPT_USER_GROUP: + +void set_detach(void); +void daemon_set_monitor(void); +void set_no_chdir(void); +void ignore_existing_pidfile(void); +pid_t read_pidfile(const char *name); +#else +#define DAEMON_OPTION_ENUMS \ + OPT_DETACH, \ + OPT_NO_SELF_CONFINEMENT, \ + OPT_NO_CHDIR, \ + OPT_PIDFILE, \ + OPT_PIPE_HANDLE, \ + OPT_SERVICE, \ + OPT_SERVICE_MONITOR, \ + OPT_USER_GROUP + +#define DAEMON_LONG_OPTIONS \ + {"detach", no_argument, NULL, OPT_DETACH}, \ + {"no-self-confinement", no_argument, NULL, OPT_NO_SELF_CONFINEMENT}, \ + {"no-chdir", no_argument, NULL, OPT_NO_CHDIR}, \ + {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \ + {"pipe-handle", required_argument, NULL, OPT_PIPE_HANDLE}, \ + {"service", no_argument, NULL, OPT_SERVICE}, \ + {"service-monitor", no_argument, NULL, OPT_SERVICE_MONITOR}, \ + {"user", required_argument, NULL, OPT_USER_GROUP} + +#define DAEMON_OPTION_HANDLERS \ + case OPT_DETACH: \ + set_detach(); \ + break; \ + \ + case OPT_NO_SELF_CONFINEMENT: \ + daemon_disable_self_confinement(); \ + break; \ + \ + case OPT_NO_CHDIR: \ + break; \ + \ + case OPT_PIDFILE: \ + set_pidfile(optarg); \ + break; \ + \ + case OPT_PIPE_HANDLE: \ + set_pipe_handle(optarg); \ + break; \ + \ + case OPT_SERVICE: \ + set_detach(); \ + break; \ + \ + case OPT_SERVICE_MONITOR: \ + break; \ + \ + case OPT_USER_GROUP: \ + daemon_set_new_user(optarg); + +#define DAEMON_OPTION_CASES \ + case OPT_DETACH: \ + case OPT_NO_SELF_CONFINEMENT: \ + case OPT_NO_CHDIR: \ + case OPT_PIDFILE: \ + case OPT_PIPE_HANDLE: \ + case OPT_SERVICE: \ + case OPT_SERVICE_MONITOR: \ + case OPT_USER_GROUP: + +void control_handler(DWORD request); +void set_pipe_handle(const char *pipe_handle); +void set_detach(void); +#endif /* _WIN32 */ + +bool get_detach(void); +void daemon_save_fd(int fd); +void daemonize(void); +void daemonize_start(bool access_datapath); +void daemonize_complete(void); +void daemon_set_new_user(const char * user_spec); +void daemon_become_new_user(bool access_datapath); +void daemon_usage(void); +void daemon_disable_self_confinement(void); +bool daemon_should_self_confine(void); +void service_start(int *argcp, char **argvp[]); +void service_stop(void); +bool should_service_stop(void); +void set_pidfile(const char *name); +void close_standard_fds(void); + +#endif /* daemon.h */ Index: openvswitch-2.17.2/include/internal/db-ctl-base.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/db-ctl-base.h @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2015, 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. + */ + +#ifndef DB_CTL_BASE_H +#define DB_CTL_BASE_H 1 + +#include "openvswitch/compiler.h" +#include "openvswitch/dynamic-string.h" +#include "openvswitch/shash.h" + +struct ctl_context; +struct option; +struct ovsdb_idl; +struct ovsdb_idl_row; +struct ovsdb_idl_txn; +struct ovsdb_symbol_table; +struct table; + +/* This library module contains the common parts for ovsdb manipulation + * (structs, commands and functions). To utilize this module, user must + * define the following: + * + * - the command syntaxes for each command. (See 'struct ctl_command_syntax' + * for more info) and regiters them using ctl_register_commands(). + * + * - the *ctl command context by inheriting the 'struct ctl_context' for + * additional commands implemented by user. (See 'struct ctl_context' for + * more info) +*/ + +/* ctl_fatal() also logs the error, so it is preferred in this file. */ +#define ovs_fatal please_use_ctl_fatal_instead_of_ovs_fatal + +struct ctl_table_class; +struct ovsdb_idl_class; +struct ovsdb_idl_table_class; +struct cmd_show_table; + +/* ctl_init() figures out the number of tables on its own and flags an error if + * 'ctl_classes' was defined with the wrong number of elements. */ +#define ctl_init(idl_class, table_classes, ctl_classes, cmd_show_table, \ + ctl_exit_func) \ + (BUILD_ASSERT(ARRAY_SIZE(table_classes) == ARRAY_SIZE(ctl_classes)), \ + ctl_init__(idl_class, ctl_classes, cmd_show_table, ctl_exit_func)) +void ctl_init__(const struct ovsdb_idl_class *, const struct ctl_table_class *, + const struct cmd_show_table *cmd_show_tables, + void (*ctl_exit_func)(int status)); +char *ctl_default_db(void); +void ctl_error(struct ctl_context *, const char *, ...) +OVS_PRINTF_FORMAT(2, 3); +OVS_NO_RETURN void ctl_fatal(const char *, ...) OVS_PRINTF_FORMAT(1, 2); + +/* *ctl command syntax structure, to be defined by each command implementation. + * + * Execution Path + * ============== + * + * Three stylized functions accompany each of these data structures: + * + * "pre-run" "run" "post-run" + * --------------- ------------ ----------------- + * *ctl ->prerequisites ->run ->postprocess + * + * Any *ctl command implementation should go through the following execution + * path: + * + * 1. parses user command-line input and finds the corresponding syntax + * structures. + * + * 2. calls prerequisites() for getting the columns or tables used by each + * command. + * + * 3. calls run() to execute each command and to generate output. + * + * 4. calls postprocess() after output has been committed. (Only needed + * by 'create' command sofar) + * + * Execution Context + * ================= + * + * Each of the stylized functions requires the 'struct ctl_context' as input + * to provide context e.g. command-line arguments, table to be modified. User + * may define more specific context (by inheriting 'struct ctl_context') and + * write stylized functions that use it. In that case, CONTAINER_OF() can + * be used to cast the generic context to the specific one. + * + * */ +struct ctl_command_syntax { + const char *name; /* e.g. "add-br" */ + int min_args; /* Min number of arguments following name. */ + int max_args; /* Max number of arguments following name. */ + + /* Names that roughly describe the arguments that the command + * uses. These should be similar to the names displayed in the + * man page or in the help output. */ + const char *arguments; + + /* If nonnull, calls ovsdb_idl_add_column() or ovsdb_idl_add_table() for + * each column or table in ctx->idl that it uses. */ + void (*prerequisites)(struct ctl_context *ctx); + + /* Does the actual work of the command and puts the command's output, if + * any, in ctx->output or ctx->table. + * + * Alternatively, if some prerequisite of the command is not met and the + * caller should wait for something to change and then retry, it may set + * ctx->try_again to true. (Only the "wait-until" command currently does + * this.) */ + void (*run)(struct ctl_context *ctx); + + /* If nonnull, called after the transaction has been successfully + * committed. ctx->output is the output from the "run" function, which + * this function may modify and otherwise postprocess as needed. (Only the + * "create" command currently does any postprocessing.) */ + void (*postprocess)(struct ctl_context *ctx); + + /* A comma-separated list of supported options, e.g. "--a,--b", or the + * empty string if the command does not support any options. + * + * Arguments are determined by appending special characters to option + * names: + * + * - Append "=" (e.g. "--id=") for a required argument. + * + * - Append "?" (e.g. "--ovs?") for an optional argument. + * + * - Otherwise an option does not accept an argument. */ + const char *options; + + enum { RO, RW } mode; /* Does this command modify the database? */ +}; + +/* A command extracted from command-line input plus the structs for + * output generation. */ +struct ctl_command { + /* Data that remains constant after initialization. */ + const struct ctl_command_syntax *syntax; + int argc; + char **argv; + struct shash options; + + /* Data modified by commands. */ + struct ds output; + struct table *table; +}; + +bool ctl_might_write_to_db(const struct ctl_command *, size_t n); +const char *ctl_get_db_cmd_usage(void); + +const char *ctl_list_db_tables_usage(void); +void ctl_print_commands(void); +void ctl_print_options(const struct option *); +void ctl_add_cmd_options(struct option **, size_t *n_options_p, + size_t *allocated_options_p, int opt_val); +void ctl_register_commands(const struct ctl_command_syntax *); +char * OVS_WARN_UNUSED_RESULT ctl_parse_commands( + int argc, char *argv[], struct shash *local_options, + struct ctl_command **commandsp, size_t *n_commandsp); + +/* Sometimes, it is desirable to print the table with weak reference to + * rows in a 'cmd_show_table' table. In that case, the 'weak_ref_table' + * should be used and user must define all variables. */ +struct weak_ref_table { + const struct ovsdb_idl_table_class *table; + const struct ovsdb_idl_column *name_column; + /* This colum must be a weak reference to the owning + * 'struct cmd_show_table''s table row. */ + const struct ovsdb_idl_column *wref_column; +}; + +/* This struct is for organizing the 'show' command output where: + * + * - 'table' is the table to show. + * + * - if 'name_column' is not null, it is used as the name for each row + * in 'table'. + * + * - 'columns[]' allows user to specify the print of additional columns + * in 'table'. + * + * - if 'wref_table' is populated, print 'wref_table.name_column' for + * each row in table 'wref_table.table' that has a reference to 'table' + * in 'wref_table.wref_column'. Every field must be populated. + * + * */ +struct cmd_show_table { + const struct ovsdb_idl_table_class *table; + const struct ovsdb_idl_column *name_column; + const struct ovsdb_idl_column *columns[4]; /* Seems like a good number. */ + const struct weak_ref_table wref_table; +}; + + +/* The base context struct for conducting the common database + * operations (commands listed in 'db_ctl_commands'). User should + * define the per-schema context by inheriting this struct as base. + * + * Database Caches + * =============== + * + * User may implement caches for contents of the database to facilitate + * specific commands. In that case, the common commands defined in + * 'db_ctl_commands' that may invalidate the cache must call the + * invalidate_cache(). + * + **/ +struct ctl_context { + /* Read-only. */ + int argc; + char **argv; + struct shash options; + + /* Modifiable state. */ + char *error; + struct ds output; + struct table *table; + struct ovsdb_idl *idl; + struct ovsdb_idl_txn *txn; + struct ovsdb_symbol_table *symtab; + + /* For implementation with a cache of the contents of the database, + * this function will be called when the database is changed and the + * change makes the cache no longer valid. */ + void (*invalidate_cache_cb)(struct ctl_context *); + + /* A command may set this member to true if some prerequisite is not met + * and the caller should wait for something to change and then retry. */ + bool try_again; +}; + +void ctl_context_init_command(struct ctl_context *, struct ctl_command *); +void ctl_context_init(struct ctl_context *, struct ctl_command *, + struct ovsdb_idl *, struct ovsdb_idl_txn *, + struct ovsdb_symbol_table *, + void (*invalidate_cache)(struct ctl_context *)); +void ctl_context_done_command(struct ctl_context *, struct ctl_command *); +void ctl_context_done(struct ctl_context *, struct ctl_command *); + +/* A way to identify a particular row in the database based on a user-provided + * string. If all fields are NULL, the struct is ignored. Otherwise, + * 'name_column' designates a column whose table is searched for rows that + * match with the user string. If 'key' is NULL, then 'name_column' should be + * a string or integer-valued column; otherwise it should be a map from a + * string to one of those types and the value corresponding to 'key' is what is + * matched. If a matching row is found, then: + * + * - If 'uuid_column' is NULL, the matching row is the final row. + * + * - Otherwise 'uuid_column' must designate a UUID-typed column whose value + * refers to exactly one row, which is the final row. + */ +struct ctl_row_id { + const struct ovsdb_idl_column *name_column; + const char *key; + const struct ovsdb_idl_column *uuid_column; +}; + +struct ctl_table_class { + struct ctl_row_id row_ids[4]; +}; + +char *ctl_get_row(struct ctl_context *, const struct ovsdb_idl_table_class *, + const char *record_id, bool must_exist, + const struct ovsdb_idl_row **); + +char *ctl_set_column(const char *table_name, const struct ovsdb_idl_row *, + const char *arg, struct ovsdb_symbol_table *); + +#endif /* db-ctl-base.h */ Index: openvswitch-2.17.2/include/internal/dhparams.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/dhparams.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2008, 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. + */ + +#ifndef DHPARAMS_H +#define DHPARAMS_H 1 + +#include +#include + +DH *get_dh2048(void); +DH *get_dh4096(void); + +#endif /* dhparams.h */ Index: openvswitch-2.17.2/include/internal/dirs.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/dirs.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef DIRS_H +#define DIRS_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +const char *ovs_sysconfdir(void); /* /usr/local/etc */ +const char *ovs_pkgdatadir(void); /* /usr/local/share/openvswitch */ +const char *ovs_rundir(void); /* /usr/local/var/run/openvswitch */ +const char *ovs_logdir(void); /* /usr/local/var/log/openvswitch */ +const char *ovs_dbdir(void); /* /usr/local/etc/openvswitch */ +const char *ovs_bindir(void); /* /usr/local/bin */ + +#ifdef __cplusplus +} +#endif + +#endif /* dirs.h */ Index: openvswitch-2.17.2/include/internal/fatal-signal.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/fatal-signal.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2013 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FATAL_SIGNAL_H +#define FATAL_SIGNAL_H 1 + +#ifndef _WIN32 +#include +#endif +#include + +/* Basic interface. */ +void fatal_signal_init(void); +void fatal_signal_add_hook(void (*hook_cb)(void *aux), + void (*cancel_cb)(void *aux), void *aux, + bool run_at_exit); +void fatal_signal_fork(void); +void fatal_signal_run(void); +void fatal_signal_wait(void); +void fatal_ignore_sigpipe(void); +void fatal_signal_atexit_handler(void); + +/* Convenience functions for unlinking files upon termination. + * + * These functions also unlink the files upon normal process termination via + * exit(). */ +void fatal_signal_add_file_to_unlink(const char *); +void fatal_signal_remove_file_to_unlink(const char *); +int fatal_signal_unlink_file_now(const char *); + +/* Interface for other code that catches one of our signals and needs to pass + * it through. */ +void fatal_signal_handler(int sig_nr); + +#ifndef _WIN32 +void fatal_signal_block(sigset_t *prev_mask); +#endif + +#endif /* fatal-signal.h */ Index: openvswitch-2.17.2/include/internal/hash-aarch64.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/hash-aarch64.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2019 Arm Limited + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header implements HASH operation primitives on aarch64. */ +#ifndef HASH_AARCH64_H +#define HASH_AARCH64_H 1 + +#ifndef HASH_H +#error "This header should only be included indirectly via hash.h." +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +static inline uint32_t hash_add(uint32_t hash, uint32_t data) +{ + return __crc32cw(hash, data); +} + +/* Add the halves of 'data' in the memory order. */ +static inline uint32_t hash_add64(uint32_t hash, uint64_t data) +{ + return __crc32cd(hash, data); +} + +static inline uint32_t hash_finish(uint32_t hash, uint64_t final) +{ + /* The finishing multiplier 0x805204f3 has been experimentally + * derived to pass the testsuite hash tests. */ + hash = __crc32cd(hash, final) * 0x805204f3; + return hash ^ hash >> 16; /* Increase entropy in LSBs. */ +} + +/* Returns the hash of the 'n' 32-bit words at 'p_', starting from 'basis'. + * We access 'p_' as a uint64_t pointer. + * + * This is inlined for the compiler to have access to the 'n_words', which + * in many cases is a constant. */ +static inline uint32_t +hash_words_inline(const uint32_t p_[], size_t n_words, uint32_t basis) +{ + const uint64_t *p = (const void *)p_; + uint32_t hash1 = basis; + uint32_t hash2 = 0; + uint32_t hash3 = n_words; + const uint32_t *endp = (const uint32_t *)p + n_words; + const uint64_t *limit = p + n_words / 2 - 3; + + while (p <= limit) { + hash1 = __crc32cd(hash1, p[0]); + hash2 = __crc32cd(hash2, p[1]); + hash3 = __crc32cd(hash3, p[2]); + p += 3; + } + switch (endp - (const uint32_t *)p) { + case 1: + hash1 = __crc32cw(hash1, *(const uint32_t *)&p[0]); + break; + case 2: + hash1 = __crc32cd(hash1, p[0]); + break; + case 3: + hash1 = __crc32cd(hash1, p[0]); + hash2 = __crc32cw(hash2, *(const uint32_t *)&p[1]); + break; + case 4: + hash1 = __crc32cd(hash1, p[0]); + hash2 = __crc32cd(hash2, p[1]); + break; + case 5: + hash1 = __crc32cd(hash1, p[0]); + hash2 = __crc32cd(hash2, p[1]); + hash3 = __crc32cw(hash3, *(const uint32_t *)&p[2]); + break; + } + return hash_finish(hash1, (uint64_t)hash2 << 32 | hash3); +} + +/* A simpler version for 64-bit data. + * 'n_words' is the count of 64-bit words, basis is 64 bits. */ +static inline uint32_t +hash_words64_inline(const uint64_t p[], size_t n_words, uint32_t basis) +{ + uint32_t hash1 = basis; + uint32_t hash2 = 0; + uint32_t hash3 = n_words; + const uint64_t *endp = p + n_words; + const uint64_t *limit = endp - 3; + + while (p <= limit) { + hash1 = __crc32cd(hash1, p[0]); + hash2 = __crc32cd(hash2, p[1]); + hash3 = __crc32cd(hash3, p[2]); + p += 3; + } + switch (endp - p) { + case 1: + hash1 = __crc32cd(hash1, p[0]); + break; + case 2: + hash1 = __crc32cd(hash1, p[0]); + hash2 = __crc32cd(hash2, p[1]); + break; + } + return hash_finish(hash1, (uint64_t)hash2 << 32 | hash3); +} + +static inline uint32_t hash_uint64_basis(const uint64_t x, + const uint32_t basis) +{ + /* '23' chosen to mix bits enough for the test-hash to pass. */ + return hash_finish(hash_add64(basis, x), 23); +} + +static inline uint32_t hash_uint64(const uint64_t x) +{ + return hash_uint64_basis(x, 0); +} + +static inline uint32_t hash_2words(uint32_t x, uint32_t y) +{ + return hash_uint64((uint64_t)y << 32 | x); +} + +static inline uint32_t hash_pointer(const void *p, uint32_t basis) +{ + return hash_uint64_basis((uint64_t) (uintptr_t) p, basis); +} + +#ifdef __cplusplus +} +#endif + +#endif /* hash-aarch64.h */ Index: openvswitch-2.17.2/include/internal/hmapx.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/hmapx.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011, 2016 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 HMAPX_H +#define HMAPX_H + +#include "openvswitch/hmap.h" + +struct hmapx_node { + struct hmap_node hmap_node; + void *data; +}; + +/* A set of "void *" pointers. */ +struct hmapx { + struct hmap map; +}; + +#define HMAPX_INITIALIZER(HMAPX) { HMAP_INITIALIZER(&(HMAPX)->map) } + +/* Basics. */ +void hmapx_init(struct hmapx *); +void hmapx_destroy(struct hmapx *); +void hmapx_clone(struct hmapx *, const struct hmapx *); +void hmapx_swap(struct hmapx *, struct hmapx *); +void hmapx_moved(struct hmapx *); + +/* Count. */ +bool hmapx_is_empty(const struct hmapx *); +size_t hmapx_count(const struct hmapx *); + +/* Insertion. */ +struct hmapx_node *hmapx_add(struct hmapx *, void *); +void hmapx_add_assert(struct hmapx *, void *); + +/* Deletion. */ +void hmapx_clear(struct hmapx *); +void hmapx_delete(struct hmapx *, struct hmapx_node *); +bool hmapx_find_and_delete(struct hmapx *, const void *); +void hmapx_find_and_delete_assert(struct hmapx *, const void *); + +/* Search. */ +struct hmapx_node *hmapx_find(const struct hmapx *, const void *); +bool hmapx_contains(const struct hmapx *, const void *); +bool hmapx_equals(const struct hmapx *, const struct hmapx *); + +/* Iteration. */ + +/* Iterates through every hmapx_node in HMAPX. */ +#define HMAPX_FOR_EACH(NODE, HMAPX) \ + HMAP_FOR_EACH_INIT(NODE, hmap_node, &(HMAPX)->map, \ + BUILD_ASSERT_TYPE(NODE, struct hmapx_node *), \ + BUILD_ASSERT_TYPE(HMAPX, struct hmapx *)) + +/* Safe when NODE may be freed (not needed when NODE may be removed from the + * hash map but its members remain accessible and intact). */ +#define HMAPX_FOR_EACH_SAFE_SHORT(NODE, HMAPX) \ + HMAP_FOR_EACH_SAFE_SHORT_INIT (NODE, hmap_node, &(HMAPX)->map, \ + BUILD_ASSERT_TYPE(NODE, struct hmapx_node *), \ + BUILD_ASSERT_TYPE(HMAPX, struct hmapx *)) + +#define HMAPX_FOR_EACH_SAFE_LONG(NODE, NEXT, HMAPX) \ + HMAP_FOR_EACH_SAFE_LONG_INIT (NODE, NEXT, hmap_node, &(HMAPX)->map, \ + BUILD_ASSERT_TYPE(NODE, struct hmapx_node *), \ + BUILD_ASSERT_TYPE(NEXT, struct hmapx_node *), \ + BUILD_ASSERT_TYPE(HMAPX, struct hmapx *)) + +#define HMAPX_FOR_EACH_SAFE(...) \ + OVERLOAD_SAFE_MACRO(HMAPX_FOR_EACH_SAFE_LONG, \ + HMAPX_FOR_EACH_SAFE_SHORT, \ + 3, __VA_ARGS__) + +#endif /* hmapx.h */ Index: openvswitch-2.17.2/include/internal/id-pool.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/id-pool.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2014 Nicira, Inc. + * Copyright (c) 2014 Netronome. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ID_POOL_H +#define ID_POOL_H + +#include +#include +#include + +struct id_pool; + +struct id_pool *id_pool_create(uint32_t base, uint32_t n_ids); +void id_pool_destroy(struct id_pool *); +bool id_pool_alloc_id(struct id_pool *, uint32_t *id); +void id_pool_free_id(struct id_pool *, uint32_t id); +void id_pool_add(struct id_pool *, uint32_t id); + +/* + * ID pool. + * ======== + * + * Pool of unique 32bit ids. + * Allocation always returns the lowest available id. + * + * Thread-safety + * ============= + * + * APIs are not thread safe. + */ +#endif /* id-pool.h */ Index: openvswitch-2.17.2/include/internal/jsonrpc.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/jsonrpc.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2009, 2010, 2012, 2013, 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. + */ + +#ifndef JSONRPC_H +#define JSONRPC_H 1 + +/* This is an implementation of the JSON-RPC 1.0 specification defined at + * http://json-rpc.org/wiki/specification. */ + +#include +#include +#include "openvswitch/types.h" + +struct json; +struct jsonrpc_msg; +struct pstream; +struct reconnect_stats; +struct stream; +struct svec; + +/* API for a JSON-RPC stream. */ + +/* Default port numbers. + * + * OVSDB_OLD_PORT defines the original port number used by OVS. + * OVSDB_PORT defines the official port number assigned by IANA. */ +#define OVSDB_OLD_PORT 6632 +#define OVSDB_PORT 6640 + +int jsonrpc_stream_open(const char *name, struct stream **, uint8_t dscp); +int jsonrpc_pstream_open(const char *name, struct pstream **, uint8_t dscp); + +struct jsonrpc *jsonrpc_open(struct stream *); +void jsonrpc_close(struct jsonrpc *); + +void jsonrpc_run(struct jsonrpc *); +void jsonrpc_wait(struct jsonrpc *); + +int jsonrpc_get_status(const struct jsonrpc *); +size_t jsonrpc_get_backlog(const struct jsonrpc *); +void jsonrpc_set_backlog_threshold(struct jsonrpc *, size_t max_n_msgs, + size_t max_backlog_bytes); + +unsigned int jsonrpc_get_received_bytes(const struct jsonrpc *); +const char *jsonrpc_get_name(const struct jsonrpc *); + +int jsonrpc_send(struct jsonrpc *, struct jsonrpc_msg *); +int jsonrpc_recv(struct jsonrpc *, struct jsonrpc_msg **); +void jsonrpc_recv_wait(struct jsonrpc *); + +int jsonrpc_send_block(struct jsonrpc *, struct jsonrpc_msg *); +int jsonrpc_recv_block(struct jsonrpc *, struct jsonrpc_msg **); +int jsonrpc_transact_block(struct jsonrpc *, struct jsonrpc_msg *, + struct jsonrpc_msg **); + +/* Messages. */ +enum jsonrpc_msg_type { + JSONRPC_REQUEST, /* Request. */ + JSONRPC_NOTIFY, /* Notification. */ + JSONRPC_REPLY, /* Successful reply. */ + JSONRPC_ERROR /* Error reply. */ +}; + +struct jsonrpc_msg { + enum jsonrpc_msg_type type; + char *method; /* Request or notification only. */ + struct json *params; /* Request or notification only. */ + struct json *result; /* Successful reply only. */ + struct json *error; /* Error reply only. */ + struct json *id; /* Request or reply only. */ +}; + +struct jsonrpc_msg *jsonrpc_create_request(const char *method, + struct json *params, + struct json **idp); +struct jsonrpc_msg *jsonrpc_create_notify(const char *method, + struct json *params); +struct jsonrpc_msg *jsonrpc_create_reply(struct json *result, + const struct json *id); +struct jsonrpc_msg *jsonrpc_create_error(struct json *error, + const struct json *id); + +struct jsonrpc_msg *jsonrpc_msg_clone(const struct jsonrpc_msg *); + +const char *jsonrpc_msg_type_to_string(enum jsonrpc_msg_type); +char *jsonrpc_msg_is_valid(const struct jsonrpc_msg *); +void jsonrpc_msg_destroy(struct jsonrpc_msg *); + +char *jsonrpc_msg_from_json(struct json *, struct jsonrpc_msg **); +struct json *jsonrpc_msg_to_json(struct jsonrpc_msg *); + +char *jsonrpc_msg_to_string(const struct jsonrpc_msg *); + +/* A JSON-RPC session with reconnection. */ + +struct jsonrpc_session *jsonrpc_session_open(const char *name, bool retry); +struct jsonrpc_session *jsonrpc_session_open_multiple(const struct svec *, + bool retry); +struct jsonrpc_session *jsonrpc_session_open_unreliably(struct jsonrpc *, + uint8_t); +void jsonrpc_session_close(struct jsonrpc_session *); + +struct jsonrpc *jsonrpc_session_steal(struct jsonrpc_session *); +void jsonrpc_session_replace(struct jsonrpc_session *, struct jsonrpc *); + +void jsonrpc_session_run(struct jsonrpc_session *); +void jsonrpc_session_wait(struct jsonrpc_session *); + +size_t jsonrpc_session_get_backlog(const struct jsonrpc_session *); +const char *jsonrpc_session_get_name(const struct jsonrpc_session *); +size_t jsonrpc_session_get_n_remotes(const struct jsonrpc_session *); + +int jsonrpc_session_send(struct jsonrpc_session *, struct jsonrpc_msg *); +struct jsonrpc_msg *jsonrpc_session_recv(struct jsonrpc_session *); +void jsonrpc_session_recv_wait(struct jsonrpc_session *); + +bool jsonrpc_session_is_alive(const struct jsonrpc_session *); +bool jsonrpc_session_is_connected(const struct jsonrpc_session *); +unsigned int jsonrpc_session_get_seqno(const struct jsonrpc_session *); +int jsonrpc_session_get_status(const struct jsonrpc_session *); +int jsonrpc_session_get_last_error(const struct jsonrpc_session *); +void jsonrpc_session_get_reconnect_stats(const struct jsonrpc_session *, + struct reconnect_stats *); + +void jsonrpc_session_enable_reconnect(struct jsonrpc_session *); +void jsonrpc_session_force_reconnect(struct jsonrpc_session *); +void jsonrpc_session_reset_backoff(struct jsonrpc_session *); + +void jsonrpc_session_set_max_backoff(struct jsonrpc_session *, + int max_backoff); +void jsonrpc_session_set_probe_interval(struct jsonrpc_session *, + int probe_interval); +void jsonrpc_session_set_dscp(struct jsonrpc_session *, + uint8_t dscp); +void jsonrpc_session_set_backlog_threshold(struct jsonrpc_session *, + size_t max_n_msgs, + size_t max_backlog_bytes); +const char *jsonrpc_session_get_id(const struct jsonrpc_session *); + +#endif /* jsonrpc.h */ Index: openvswitch-2.17.2/include/internal/memory.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/memory.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2012 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEMORY_H +#define MEMORY_H 1 + +/* Memory usage monitor. + * + * This is intended to be called as part of a daemon's main loop. After some + * time to allow the daemon to allocate an initial memory usage, it logs some + * memory usage information (most of which must actually be provided by the + * client). At intervals, if the daemon's memory usage has grown + * significantly, it again logs information. + * + * The monitor also has a unixctl interface. + * + * Intended usage in the program's main loop is like this: + * + * for (;;) { + * memory_run(); + * if (memory_should_report()) { + * struct simap usage; + * + * simap_init(&usage); + * ...fill in 'usage' with meaningful statistics... + * memory_report(&usage); + * simap_destroy(&usage); + * } + * + * ... + * + * memory_wait(); + * poll_block(); + * } + */ + +#include + +struct simap; + +void memory_run(void); +void memory_wait(void); + +bool memory_should_report(void); +void memory_report(const struct simap *usage); + +#endif /* memory.h */ Index: openvswitch-2.17.2/include/internal/netdev-afxdp.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/netdev-afxdp.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018, 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. + */ + +#ifndef NETDEV_AFXDP_H +#define NETDEV_AFXDP_H 1 + +#ifdef HAVE_AF_XDP + +#include +#include + +/* These functions are Linux AF_XDP specific, so they should be used directly + * only by Linux-specific code. */ + +enum afxdp_mode { + OVS_AF_XDP_MODE_UNSPEC, + OVS_AF_XDP_MODE_BEST_EFFORT, + OVS_AF_XDP_MODE_NATIVE_ZC, + OVS_AF_XDP_MODE_NATIVE, + OVS_AF_XDP_MODE_GENERIC, + OVS_AF_XDP_MODE_MAX, +}; + +struct dp_packet; +struct dp_packet_batch; +struct netdev; +struct netdev_afxdp_tx_lock; +struct netdev_custom_stats; +struct netdev_rxq; +struct netdev_stats; +struct smap; +struct xdp_umem; +struct xsk_socket_info; + +int netdev_afxdp_rxq_construct(struct netdev_rxq *rxq_); +void netdev_afxdp_rxq_destruct(struct netdev_rxq *rxq_); +int netdev_afxdp_init(void); +int netdev_afxdp_construct(struct netdev *netdev_); +void netdev_afxdp_destruct(struct netdev *netdev_); +int netdev_afxdp_verify_mtu_size(const struct netdev *netdev, int mtu); + +int netdev_afxdp_rxq_recv(struct netdev_rxq *rxq_, + struct dp_packet_batch *batch, + int *qfill); +int netdev_afxdp_batch_send(struct netdev *netdev_, int qid, + struct dp_packet_batch *batch, + bool concurrent_txq); +int netdev_afxdp_set_config(struct netdev *netdev, const struct smap *args, + char **errp); +int netdev_afxdp_get_config(const struct netdev *netdev, struct smap *args); +int netdev_afxdp_get_stats(const struct netdev *netdev_, + struct netdev_stats *stats); +int netdev_afxdp_get_custom_stats(const struct netdev *netdev, + struct netdev_custom_stats *custom_stats); + + +void free_afxdp_buf(struct dp_packet *p); +int netdev_afxdp_reconfigure(struct netdev *netdev); +void signal_remove_xdp(struct netdev *netdev); + +#else /* !HAVE_AF_XDP */ + +#include "openvswitch/compiler.h" + +struct dp_packet; + +static inline void +free_afxdp_buf(struct dp_packet *p OVS_UNUSED) +{ + /* Nothing. */ +} + +#endif /* HAVE_AF_XDP */ +#endif /* netdev-afxdp.h */ Index: openvswitch-2.17.2/include/internal/netdev-dpdk.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/netdev-dpdk.h @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2014, 2015, 2016 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 NETDEV_DPDK_H +#define NETDEV_DPDK_H + +#include + +#include "openvswitch/compiler.h" + +struct dp_packet; +struct netdev; + +#ifdef DPDK_NETDEV + +#include + +void netdev_dpdk_register(void); +void free_dpdk_buf(struct dp_packet *); + +bool netdev_dpdk_flow_api_supported(struct netdev *); + +int +netdev_dpdk_rte_flow_destroy(struct netdev *netdev, + struct rte_flow *rte_flow, + struct rte_flow_error *error); +struct rte_flow * +netdev_dpdk_rte_flow_create(struct netdev *netdev, + const struct rte_flow_attr *attr, + const struct rte_flow_item *items, + const struct rte_flow_action *actions, + struct rte_flow_error *error); +int +netdev_dpdk_rte_flow_query_count(struct netdev *netdev, + struct rte_flow *rte_flow, + struct rte_flow_query_count *query, + struct rte_flow_error *error); +int +netdev_dpdk_get_port_id(struct netdev *netdev); + +#ifdef ALLOW_EXPERIMENTAL_API + +int netdev_dpdk_rte_flow_tunnel_decap_set(struct netdev *, + struct rte_flow_tunnel *, + struct rte_flow_action **, + uint32_t *num_of_actions, + struct rte_flow_error *); +int netdev_dpdk_rte_flow_tunnel_match(struct netdev *, + struct rte_flow_tunnel *, + struct rte_flow_item **, + uint32_t *num_of_items, + struct rte_flow_error *); +int netdev_dpdk_rte_flow_get_restore_info(struct netdev *, + struct dp_packet *, + struct rte_flow_restore_info *, + struct rte_flow_error *); +int netdev_dpdk_rte_flow_tunnel_action_decap_release(struct netdev *, + struct rte_flow_action *, + uint32_t num_of_actions, + struct rte_flow_error *); +int netdev_dpdk_rte_flow_tunnel_item_release(struct netdev *, + struct rte_flow_item *, + uint32_t num_of_items, + struct rte_flow_error *); + +#else + +static inline void +set_error(struct rte_flow_error *error, enum rte_flow_error_type type) +{ + if (!error) { + return; + } + error->type = type; + error->cause = NULL; + error->message = NULL; +} + +static inline int +netdev_dpdk_rte_flow_tunnel_decap_set( + struct netdev *netdev OVS_UNUSED, + struct rte_flow_tunnel *tunnel OVS_UNUSED, + struct rte_flow_action **actions OVS_UNUSED, + uint32_t *num_of_actions OVS_UNUSED, + struct rte_flow_error *error) +{ + set_error(error, RTE_FLOW_ERROR_TYPE_ACTION); + return -1; +} + +static inline int +netdev_dpdk_rte_flow_tunnel_match(struct netdev *netdev OVS_UNUSED, + struct rte_flow_tunnel *tunnel OVS_UNUSED, + struct rte_flow_item **items OVS_UNUSED, + uint32_t *num_of_items OVS_UNUSED, + struct rte_flow_error *error) +{ + set_error(error, RTE_FLOW_ERROR_TYPE_ITEM); + return -1; +} + +static inline int +netdev_dpdk_rte_flow_get_restore_info( + struct netdev *netdev OVS_UNUSED, + struct dp_packet *p OVS_UNUSED, + struct rte_flow_restore_info *info OVS_UNUSED, + struct rte_flow_error *error) +{ + set_error(error, RTE_FLOW_ERROR_TYPE_ATTR); + return -1; +} + +static inline int +netdev_dpdk_rte_flow_tunnel_action_decap_release( + struct netdev *netdev OVS_UNUSED, + struct rte_flow_action *actions OVS_UNUSED, + uint32_t num_of_actions OVS_UNUSED, + struct rte_flow_error *error) +{ + set_error(error, RTE_FLOW_ERROR_TYPE_NONE); + return 0; +} + +static inline int +netdev_dpdk_rte_flow_tunnel_item_release( + struct netdev *netdev OVS_UNUSED, + struct rte_flow_item *items OVS_UNUSED, + uint32_t num_of_items OVS_UNUSED, + struct rte_flow_error *error) +{ + set_error(error, RTE_FLOW_ERROR_TYPE_NONE); + return 0; +} + +#endif /* ALLOW_EXPERIMENTAL_API */ + +#else + +static inline void +netdev_dpdk_register(void) +{ + /* Nothing */ +} +static inline void +free_dpdk_buf(struct dp_packet *buf OVS_UNUSED) +{ + /* Nothing */ +} + +#endif + +#endif /* netdev-dpdk.h */ Index: openvswitch-2.17.2/include/internal/ovs-atomic-c++.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-c++.h @@ -0,0 +1,67 @@ +/* This header implements atomic operation primitives on compilers that + * have built-in support for ++C11 */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#include + +#define ATOMIC(TYPE) std::atomic + +using std::atomic_init; + +using std::memory_order_relaxed; +using std::memory_order_consume; +using std::memory_order_acquire; +using std::memory_order_release; +using std::memory_order_acq_rel; +using std::memory_order_seq_cst; + +using std::atomic_thread_fence; +using std::atomic_signal_fence; +using std::atomic_is_lock_free; + +using std::atomic_store; +using std::atomic_store_explicit; + +using std::atomic_compare_exchange_strong; +using std::atomic_compare_exchange_strong_explicit; +using std::atomic_compare_exchange_weak; +using std::atomic_compare_exchange_weak_explicit; + +using std::atomic_exchange; +using std::atomic_exchange_explicit; + +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) +#define atomic_read_explicit(SRC, DST, ORDER) \ + (*(DST) = std::atomic_load_explicit(SRC, ORDER), \ + (void) 0) + +#define atomic_add(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_sub(RMW, ARG, ORIG) \ + atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_or(RMW, ARG, ORIG) \ + atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_xor(RMW, ARG, ORIG) \ + atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_and(RMW, ARG, ORIG) \ + atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = (*(RMW)).fetch_add(ARG, ORDER), (void) 0) +#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = (*(RMW)).fetch_sub(ARG, ORDER), (void) 0) +#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = (*(RMW)).fetch_or(ARG, ORDER), (void) 0) +#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = (*(RMW)).fetch_xor(ARG, ORDER), (void) 0) +#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = (*(RMW)).fetch_and(ARG, ORDER), (void) 0) + +using std::atomic_flag; +using std::atomic_flag_test_and_set_explicit; +using std::atomic_flag_test_and_set; +using std::atomic_flag_clear_explicit; +using std::atomic_flag_clear; Index: openvswitch-2.17.2/include/internal/ovs-atomic-c11.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-c11.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header implements atomic operation primitives on compilers that + * have built-in support for C11 */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#include + +#define OMIT_STANDARD_ATOMIC_TYPES 1 +#define ATOMIC(TYPE) _Atomic(TYPE) + +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) +#define atomic_read_explicit(SRC, DST, ORDER) \ + (*(DST) = atomic_load_explicit(SRC, ORDER), \ + (void) 0) + +#define atomic_add(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_sub(RMW, ARG, ORIG) \ + atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_or(RMW, ARG, ORIG) \ + atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_xor(RMW, ARG, ORIG) \ + atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) +#define atomic_and(RMW, ARG, ORIG) \ + atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = atomic_fetch_add_explicit(RMW, ARG, ORDER), (void) 0) +#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = atomic_fetch_sub_explicit(RMW, ARG, ORDER), (void) 0) +#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = atomic_fetch_or_explicit(RMW, ARG, ORDER), (void) 0) +#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = atomic_fetch_xor_explicit(RMW, ARG, ORDER), (void) 0) +#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ + (*(ORIG) = atomic_fetch_and_explicit(RMW, ARG, ORDER), (void) 0) Index: openvswitch-2.17.2/include/internal/ovs-atomic-flag-gcc4.7+.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-flag-gcc4.7+.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2013, 2014 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* This header implements atomic_flag on Clang and on GCC 4.7 and later. */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +/* atomic_flag */ + +typedef struct { + unsigned char b; +} atomic_flag; +#define ATOMIC_FLAG_INIT { .b = false } + +static inline bool +atomic_flag_test_and_set_explicit(volatile atomic_flag *object, + memory_order order) +{ + return __atomic_test_and_set(&object->b, order); +} + +static inline bool +atomic_flag_test_and_set(volatile atomic_flag *object) +{ + return atomic_flag_test_and_set_explicit(object, memory_order_seq_cst); +} + +static inline void +atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order) +{ + __atomic_clear(object, order); +} + +static inline void +atomic_flag_clear(volatile atomic_flag *object) +{ + atomic_flag_clear_explicit(object, memory_order_seq_cst); +} Index: openvswitch-2.17.2/include/internal/ovs-atomic-i586.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-i586.h @@ -0,0 +1,489 @@ +/* + * 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. + */ + +/* This header implements atomic operation primitives on 32-bit 586+ with GCC. + */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#define OVS_ATOMIC_I586_IMPL 1 + +/* + * These assumptions have been adopted from the x86_64 Memory model: + * + * - 1, 2, and 4 byte loads and stores are atomic on aligned memory. + * - Loads are not reordered with other loads. + * - Stores are not reordered with OLDER loads. + * - Loads may be reordered with OLDER stores to a different memory location, + * but not with OLDER stores to the same memory location. + * - Stores are not reordered with other stores, except maybe for special + * instructions not emitted by compilers, or by the stores performed by + * a single fast string operation (e.g., "stos"). As long as the atomic + * stores are not combined with any other stores, even the allowed reordering + * of the stores by a single fast string operation is not a problem. + * - Neither loads nor stores are reordered with locked instructions. + * - Stores by a single processor are observed in the same order by all + * processors. + * - (Unlocked) Stores from different processors are NOT ordered. + * - Memory ordering obeys causality (memory ordering respects transitive + * visibility). + * - Any two stores are seen in a consistent order by processors other than + * the those performing the stores. + * - Locked instructions have total order. + * + * These rules imply that: + * + * - Locked instructions are not needed for aligned loads or stores to make + * them atomic for sizes upto 4 bytes. 8 byte objects need locked + * instructions. + * - All stores have release semantics; none of the preceding stores or loads + * can be reordered with following stores. Following loads could still be + * reordered to happen before the store, but that is not a violation of the + * release semantics. + * - All loads from a given memory location have acquire semantics with + * respect to the stores on the same memory location; none of the following + * loads or stores can be reordered with the load. Preceding stores to a + * different memory location MAY be reordered with the load, but that is not + * a violation of the acquire semantics (i.e., the loads and stores of two + * critical sections guarded by a different memory location can overlap). + * - Locked instructions serve as CPU memory barriers by themselves. + * - Locked stores implement the sequential consistency memory order. Using + * locked instructions when seq_cst memory order is requested allows normal + * loads to observe the stores in the same (total) order without using CPU + * memory barrier after the loads. + * + * NOTE: Some older AMD Opteron processors have a bug that violates the + * acquire semantics described above. The bug manifests as an unlocked + * read-modify-write operation following a "semaphore operation" operating + * on data that existed before entering the critical section; i.e., the + * preceding "semaphore operation" fails to function as an acquire barrier. + * The affected CPUs are AMD family 15, models 32 to 63. + * + * Ref. http://support.amd.com/TechDocs/25759.pdf errata #147. + */ + +/* Barriers. */ + +#define compiler_barrier() asm volatile(" " : : : "memory") +#define cpu_barrier() asm volatile("lock; addl $0,(%%esp)" ::: "memory", "cc") + +/* + * The 'volatile' keyword prevents the compiler from keeping the atomic + * value in a register, and generates a new memory access for each atomic + * operation. This allows the implementations of memory_order_relaxed and + * memory_order_consume to avoid issuing a compiler memory barrier, allowing + * full optimization of all surrounding non-atomic variables. + * + * The placement of the 'volatile' keyword after the 'TYPE' below is highly + * significant when the TYPE is a pointer type. In that case we want the + * pointer to be declared volatile, not the data type that is being pointed + * at! + * + * Attribute aligned is used to tell the compiler to align 64-bit data + * on a 8-byte boundary. This allows more efficient atomic access, as the + * the CPU guarantees such memory accesses to be atomic. */ +#define ATOMIC(TYPE) TYPE volatile __attribute__((aligned(sizeof(TYPE)))) + +/* Memory ordering. Must be passed in as a constant. */ +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +} memory_order; + +#define ATOMIC_BOOL_LOCK_FREE 2 +#define ATOMIC_CHAR_LOCK_FREE 2 +#define ATOMIC_SHORT_LOCK_FREE 2 +#define ATOMIC_INT_LOCK_FREE 2 +#define ATOMIC_LONG_LOCK_FREE 2 +#define ATOMIC_LLONG_LOCK_FREE 2 +#define ATOMIC_POINTER_LOCK_FREE 2 + +#define IS_LOCKLESS_ATOMIC(OBJECT) \ + (sizeof(OBJECT) <= 8 && IS_POW2(sizeof(OBJECT))) + +#define ATOMIC_VAR_INIT(VALUE) VALUE +#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) + +/* + * The memory_model_relaxed does not need a compiler barrier, if the + * atomic operation can otherwise be guaranteed to not be moved with + * respect to other atomic operations on the same memory location. Using + * the 'volatile' keyword in the definition of the atomic types + * accomplishes this, as memory accesses to volatile data may not be + * optimized away, or be reordered with other volatile accesses. + * + * On x86 also memory_order_consume is automatic, and data dependency on a + * volatile atomic variable means that the compiler optimizations should not + * cause problems. That is, the compiler should not speculate the value of + * the atomic_read, as it is going to read it from the memory anyway. + * This allows omiting the compiler memory barrier on atomic_reads with + * memory_order_consume. This matches the definition of + * smp_read_barrier_depends() in Linux kernel as a nop for x86, and its usage + * in rcu_dereference(). + * + * We use this same logic below to choose inline assembly statements with or + * without a compiler memory barrier. + */ +static inline void +atomic_compiler_barrier(memory_order order) +{ + if (order > memory_order_consume) { + compiler_barrier(); + } +} + +static inline void +atomic_thread_fence(memory_order order) +{ + if (order == memory_order_seq_cst) { + cpu_barrier(); + } else { + atomic_compiler_barrier(order); + } +} + +static inline void +atomic_signal_fence(memory_order order) +{ + atomic_compiler_barrier(order); +} + +#define atomic_is_lock_free(OBJ) \ + ((void) *(OBJ), \ + IS_LOCKLESS_ATOMIC(*(OBJ)) ? 2 : 0) + +/* The 8-byte atomic exchange uses cmpxchg8b with the SRC (ax:dx) as + * the expected value (bx:cx), which will get replaced by the current + * value in the likely case it did not match, after which we keep + * trying until the swap succeeds. */ + +#if defined(__PIC__) +/* ebx may not be clobbered when compiled with -fPIC, must save and + * restore it. Furthermore, 'DST' may be addressed via ebx, so the + * address must be passed via a register so that it remains valid also + * after changing ebx. */ +#define atomic_exchange_8__(DST, SRC, CLOB) \ + uint32_t temp____; \ + \ + asm volatile(" movl %%ebx,%2 ; " \ + " movl %%eax,%%ebx ; " \ + " movl %%edx,%%ecx ; " \ + "1: " \ + "lock; cmpxchg8b (%0); " \ + " jne 1b ; " \ + " movl %2,%%ebx ; " \ + " # atomic_exchange_8__ " \ + : "+r" (DST), /* 0 */ \ + "+A" (SRC), /* 1 */ \ + "=mr" (temp____) /* 2 */ \ + :: "ecx", CLOB, "cc") + +#else +#define atomic_exchange_8__(DST, SRC, CLOB) \ + asm volatile(" movl %%eax,%%ebx ; " \ + " movl %%edx,%%ecx ; " \ + "1: " \ + "lock; cmpxchg8b %0 ; " \ + " jne 1b ; " \ + " # atomic_exchange_8__ " \ + : "+m" (*DST), /* 0 */ \ + "+A" (SRC) /* 1 */ \ + :: "ebx", "ecx", CLOB, "cc") +#endif + +#define atomic_exchange__(DST, SRC, ORDER) \ + ({ \ + typeof(DST) dst___ = (DST); \ + typeof(*(DST)) src___ = (SRC); \ + \ + if ((ORDER) > memory_order_consume) { \ + if (sizeof(*(DST)) == 8) { \ + atomic_exchange_8__(dst___, src___, "memory"); \ + } else { \ + asm volatile("xchg %1,%0 ; " \ + "# atomic_exchange__" \ + : "+r" (src___), /* 0 */ \ + "+m" (*dst___) /* 1 */ \ + :: "memory"); \ + } \ + } else { \ + if (sizeof(*(DST)) == 8) { \ + atomic_exchange_8__(dst___, src___, "cc"); \ + } else { \ + asm volatile("xchg %1,%0 ; " \ + "# atomic_exchange__" \ + : "+r" (src___), /* 0 */ \ + "+m" (*dst___)); /* 1 */ \ + } \ + } \ + src___; \ + }) + +#if defined(__SSE__) +/* SSE registers are 128-bit wide, and moving the lowest 64-bits of an SSE + * register to proerly aligned memory is atomic. See ATOMIC(TYPE) above. */ +#define atomic_store_8__(DST, SRC) \ + asm volatile("movq %1,%0 ; # atomic_store_8__" \ + : "=m" (*DST) /* 0 */ \ + : "x" (SRC)) /* 1, SSE */ +#else +/* Locked 64-bit exchange is available on all i586 CPUs. */ +#define atomic_store_8__(DST, SRC) \ + atomic_exchange_8__(DST, SRC, "cc") +#endif + +#define atomic_store_explicit(DST, SRC, ORDER) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(*(DST)) src__ = (SRC); \ + \ + if ((ORDER) != memory_order_seq_cst) { \ + atomic_compiler_barrier(ORDER); \ + if (sizeof(*(DST)) == 8) { \ + atomic_store_8__(dst__, src__); \ + } else { \ + *dst__ = src__; \ + } \ + } else { \ + atomic_exchange__(dst__, src__, ORDER); \ + } \ + (void) 0; \ + }) +#define atomic_store(DST, SRC) \ + atomic_store_explicit(DST, SRC, memory_order_seq_cst) + +#if defined(__SSE__) +/* SSE registers are 128-bit wide, and moving 64-bits from properly aligned + * memory to an SSE register is atomic. See ATOMIC(TYPE) above. */ +#define atomic_read_8__(SRC, DST) \ + ({ \ + typeof(*(DST)) res__; \ + \ + asm ("movq %1,%0 ; # atomic_read_8__" \ + : "=x" (res__) /* 0, SSE. */ \ + : "m" (*SRC)); /* 1 */ \ + *(DST) = res__; \ + }) +#else +/* Must use locked cmpxchg8b (available on all i586 CPUs) if compiled w/o sse + * support. Compare '*DST' to a random value in bx:cx and returns the actual + * value in ax:dx. The registers bx and cx are only read, so they are not + * clobbered. */ +#define atomic_read_8__(SRC, DST) \ + ({ \ + typeof(*(DST)) res__; \ + \ + asm (" movl %%ebx,%%eax ; " \ + " movl %%ecx,%%edx ; " \ + "lock; cmpxchg8b %1 ; " \ + "# atomic_read_8__ " \ + : "=&A" (res__), /* 0 */ \ + "+m" (*SRC) /* 1 */ \ + : : "cc"); \ + *(DST) = res__; \ + }) +#endif + +#define atomic_read_explicit(SRC, DST, ORDER) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(SRC) src__ = (SRC); \ + \ + if (sizeof(*(DST)) <= 4) { \ + *dst__ = *src__; \ + } else { \ + atomic_read_8__(SRC, DST); \ + } \ + atomic_compiler_barrier(ORDER); \ + (void) 0; \ + }) +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) + +#if defined(__PIC__) +/* ebx may not be used as an input when compiled with -fPIC, must save + * and restore it. Furthermore, 'DST' may be addressed via ebx, so + * the address must be passed via a register so that it remains valid + * also after changing ebx. */ +#define atomic_compare_exchange_8__(DST, EXP, SRC, RES, CLOB) \ + asm volatile(" xchgl %%ebx,%3 ; " \ + "lock; cmpxchg8b (%1) ; " \ + " xchgl %3,%%ebx ; " \ + " sete %0 " \ + "# atomic_compare_exchange_8__" \ + : "=q" (RES), /* 0 */ \ + "+r" (DST), /* 1 */ \ + "+A" (EXP) /* 2 */ \ + : "r" ((uint32_t)SRC), /* 3 */ \ + "c" ((uint32_t)((uint64_t)SRC >> 32)) /* 4 */ \ + : CLOB, "cc") +#else +#define atomic_compare_exchange_8__(DST, EXP, SRC, RES, CLOB) \ + asm volatile("lock; cmpxchg8b %1 ; " \ + " sete %0 " \ + "# atomic_compare_exchange_8__" \ + : "=q" (RES), /* 0 */ \ + "+m" (*DST), /* 1 */ \ + "+A" (EXP) /* 2 */ \ + : "b" ((uint32_t)SRC), /* 3 */ \ + "c" ((uint32_t)((uint64_t)SRC >> 32)) /* 4 */ \ + : CLOB, "cc") +#endif + +#define atomic_compare_exchange__(DST, EXP, SRC, RES, CLOB) \ + asm volatile("lock; cmpxchg %3,%1 ; " \ + " sete %0 " \ + "# atomic_compare_exchange__" \ + : "=q" (RES), /* 0 */ \ + "+m" (*DST), /* 1 */ \ + "+a" (EXP) /* 2 */ \ + : "r" (SRC) /* 3 */ \ + : CLOB, "cc") + +/* ORD_FAIL is ignored, as atomic_compare_exchange__ already implements + * at least as strong a barrier as allowed for ORD_FAIL in all cases. */ +#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORDER, ORD_FAIL) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(DST) expp__ = (EXP); \ + typeof(*(DST)) src__ = (SRC); \ + typeof(*(DST)) exp__ = *expp__; \ + uint8_t res__; \ + (void)ORD_FAIL; \ + \ + if ((ORDER) > memory_order_consume) { \ + if (sizeof(*(DST)) <= 4) { \ + atomic_compare_exchange__(dst__, exp__, src__, res__, \ + "memory"); \ + } else { \ + atomic_compare_exchange_8__(dst__, exp__, src__, res__, \ + "memory"); \ + } \ + } else { \ + if (sizeof(*(DST)) <= 4) { \ + atomic_compare_exchange__(dst__, exp__, src__, res__, \ + "cc"); \ + } else { \ + atomic_compare_exchange_8__(dst__, exp__, src__, res__, \ + "cc"); \ + } \ + } \ + if (!res__) { \ + *expp__ = exp__; \ + } \ + (bool)res__; \ + }) +#define atomic_compare_exchange_strong(DST, EXP, SRC) \ + atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ + memory_order_seq_cst, \ + memory_order_seq_cst) +#define atomic_compare_exchange_weak \ + atomic_compare_exchange_strong +#define atomic_compare_exchange_weak_explicit \ + atomic_compare_exchange_strong_explicit + +#define atomic_exchange_explicit(RMW, ARG, ORDER) \ + atomic_exchange__(RMW, ARG, ORDER) +#define atomic_exchange(RMW, ARG) \ + atomic_exchange_explicit(RMW, ARG, memory_order_seq_cst) + +#define atomic_add__(RMW, ARG, CLOB) \ + asm volatile("lock; xadd %0,%1 ; " \ + "# atomic_add__ " \ + : "+r" (ARG), /* 0 */ \ + "+m" (*RMW) /* 1 */ \ + :: CLOB, "cc") + +#define atomic_add_32__(RMW, ARG, ORIG, ORDER) \ + ({ \ + typeof(RMW) rmw__ = (RMW); \ + typeof(*(RMW)) arg__ = (ARG); \ + \ + if ((ORDER) > memory_order_consume) { \ + atomic_add__(rmw__, arg__, "memory"); \ + } else { \ + atomic_add__(rmw__, arg__, "cc"); \ + } \ + *(ORIG) = arg__; \ + }) + +/* We could use simple locked instructions if the original value was not + * needed. */ +#define atomic_op__(RMW, OP, ARG, ORIG, ORDER) \ + ({ \ + typeof(RMW) rmw__ = (RMW); \ + typeof(ARG) arg__ = (ARG); \ + \ + typeof(*(RMW)) val__; \ + \ + atomic_read_explicit(rmw__, &val__, memory_order_relaxed); \ + do { \ + } while (!atomic_compare_exchange_weak_explicit(rmw__, &val__, \ + val__ OP arg__, \ + ORDER, \ + memory_order_relaxed)); \ + *(ORIG) = val__; \ + }) + +#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ + (sizeof(*(RMW)) <= 4 \ + ? atomic_add_32__(RMW, ARG, ORIG, ORDER) \ + : atomic_op__(RMW, +, ARG, ORIG, ORDER)) +#define atomic_add(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ + (sizeof(*(RMW)) <= 4 \ + ? atomic_add_32__(RMW, -(ARG), ORIG, ORDER) \ + : atomic_op__(RMW, -, ARG, ORIG, ORDER)) +#define atomic_sub(RMW, ARG, ORIG) \ + atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_op__(RMW, |, ARG, ORIG, ORDER) +#define atomic_or(RMW, ARG, ORIG) \ + atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_op__(RMW, ^, ARG, ORIG, ORDER) +#define atomic_xor(RMW, ARG, ORIG) \ + atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_op__(RMW, &, ARG, ORIG, ORDER) +#define atomic_and(RMW, ARG, ORIG) \ + atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + + +/* atomic_flag */ + +typedef ATOMIC(int) atomic_flag; +#define ATOMIC_FLAG_INIT { false } + +#define atomic_flag_test_and_set_explicit(FLAG, ORDER) \ + ((bool)atomic_exchange__(FLAG, 1, ORDER)) +#define atomic_flag_test_and_set(FLAG) \ + atomic_flag_test_and_set_explicit(FLAG, memory_order_seq_cst) + +#define atomic_flag_clear_explicit(FLAG, ORDER) \ + atomic_store_explicit(FLAG, 0, ORDER) +#define atomic_flag_clear(FLAG) \ + atomic_flag_clear_explicit(FLAG, memory_order_seq_cst) Index: openvswitch-2.17.2/include/internal/ovs-atomic-locked.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-locked.h @@ -0,0 +1,52 @@ +/* This header implements atomic operation locking helpers. */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#define OVS_ATOMIC_LOCKED_IMPL 1 + +void atomic_lock__(void *); +void atomic_unlock__(void *); + +#define atomic_store_locked(DST, SRC) \ + (atomic_lock__(DST), \ + *(DST) = (SRC), \ + atomic_unlock__(DST), \ + (void) 0) + +#define atomic_read_locked(SRC, DST) \ + (atomic_lock__(SRC), \ + *(DST) = *(SRC), \ + atomic_unlock__(SRC), \ + (void) 0) + +/* XXX: Evaluates EXP multiple times. */ +#define atomic_compare_exchange_locked(DST, EXP, SRC) \ + (atomic_lock__(DST), \ + (*(DST) == *(EXP) \ + ? (*(DST) = (SRC), \ + atomic_unlock__(DST), \ + true) \ + : (*(EXP) = *(DST), \ + atomic_unlock__(DST), \ + false))) + +#define atomic_exchange_locked(DST, SRC) \ + ({ \ + atomic_lock__(DST); \ + typeof(*(DST)) __tmp = *(DST); \ + *(DST) = SRC; \ + atomic_unlock__(DST); \ + __tmp; \ + }) + +#define atomic_op_locked_add += +#define atomic_op_locked_sub -= +#define atomic_op_locked_or |= +#define atomic_op_locked_xor ^= +#define atomic_op_locked_and &= +#define atomic_op_locked(RMW, OP, OPERAND, ORIG) \ + (atomic_lock__(RMW), \ + *(ORIG) = *(RMW), \ + *(RMW) atomic_op_locked_##OP (OPERAND), \ + atomic_unlock__(RMW)) Index: openvswitch-2.17.2/include/internal/ovs-atomic-msvc.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-msvc.h @@ -0,0 +1,463 @@ +/* + * 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. + */ + +/* This header implements atomic operation primitives for MSVC + * on i586 or greater platforms (32 bit). */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +/* From msdn documentation: With Visual Studio 2003, volatile to volatile + * references are ordered; the compiler will not re-order volatile variable + * access. With Visual Studio 2005, the compiler also uses acquire semantics + * for read operations on volatile variables and release semantics for write + * operations on volatile variables (when supported by the CPU). + * + * Though there is no clear documentation that states that anything greater + * than VS 2005 has the same behavior as described above, looking through MSVCs + * C++ atomics library in VS2013 shows that the compiler still takes + * acquire/release semantics on volatile variables. */ +#define ATOMIC(TYPE) TYPE volatile + +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +} memory_order; + +#if _MSC_VER > 1800 && defined(_M_IX86) +/* From WDK 10 _InlineInterlocked* functions are renamed to + * _InlineInterlocked* although the documentation does not specify it */ +#define _InterlockedExchangeAdd64 _InlineInterlockedExchangeAdd64 +#define _InterlockedExchange64 _InlineInterlockedExchange64 +#endif + +#define ATOMIC_BOOL_LOCK_FREE 2 +#define ATOMIC_CHAR_LOCK_FREE 2 +#define ATOMIC_SHORT_LOCK_FREE 2 +#define ATOMIC_INT_LOCK_FREE 2 +#define ATOMIC_LONG_LOCK_FREE 2 +#define ATOMIC_LLONG_LOCK_FREE 2 +#define ATOMIC_POINTER_LOCK_FREE 2 + +#define IS_LOCKLESS_ATOMIC(OBJECT) \ + (sizeof(OBJECT) <= 8 && IS_POW2(sizeof(OBJECT))) + +#define ATOMIC_VAR_INIT(VALUE) (VALUE) +#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) + +static inline void +atomic_compiler_barrier(memory_order order) +{ + /* In case of 'memory_order_consume', it is implicitly assumed that + * the compiler will not move instructions that have data-dependency + * on the variable in question before the barrier. */ + if (order > memory_order_consume) { + _ReadWriteBarrier(); + } +} + +static inline void +atomic_thread_fence(memory_order order) +{ + /* x86 is strongly ordered and acquire/release semantics come + * automatically. */ + atomic_compiler_barrier(order); + if (order == memory_order_seq_cst) { + MemoryBarrier(); + atomic_compiler_barrier(order); + } +} + +static inline void +atomic_signal_fence(memory_order order) +{ + atomic_compiler_barrier(order); +} + +/* 1, 2 and 4 bytes loads and stores are atomic on aligned memory. In addition, + * since the compiler automatically takes acquire and release semantics on + * volatile variables, for any order lesser than 'memory_order_seq_cst', we + * can directly assign or read values. */ + +#define atomic_store32(DST, SRC, ORDER) \ + if (ORDER == memory_order_seq_cst) { \ + InterlockedExchange((long volatile *) (DST), \ + (long) (SRC)); \ + } else { \ + *(DST) = (SRC); \ + } + +/* MSVC converts 64 bit writes into two instructions. So there is + * a possibility that an interrupt can make a 64 bit write non-atomic even + * when 8 byte aligned. So use InterlockedExchange64(). + * + * For atomic stores, 'consume' and 'acquire' semantics are not valid. But we + * are using 'Exchange' to get atomic stores here and we only have + * InterlockedExchange64(), InterlockedExchangeNoFence64() and + * InterlockedExchange64Acquire() available. So we are forced to use + * InterlockedExchange64() which uses full memory barrier for everything + * greater than 'memory_order_relaxed'. */ +#ifdef _M_IX86 +#define atomic_store64(DST, SRC, ORDER) \ + if (ORDER == memory_order_relaxed) { \ + InterlockedExchangeNoFence64((int64_t volatile *) (DST), \ + (int64_t) (SRC)); \ + } else { \ + InterlockedExchange64((int64_t volatile *) (DST), (int64_t) (SRC));\ + } +#elif _M_X64 +/* 64 bit writes are atomic on amd64 if 64 bit aligned. */ +#define atomic_store64(DST, SRC, ORDER) \ + if (ORDER == memory_order_seq_cst) { \ + InterlockedExchange64((int64_t volatile *) (DST), \ + (int64_t) (SRC)); \ + } else { \ + *(DST) = (SRC); \ + } +#endif + +#define atomic_store8(DST, SRC, ORDER) \ + if (ORDER == memory_order_seq_cst) { \ + InterlockedExchange8((char volatile *) (DST), (char) (SRC)); \ + } else { \ + *(DST) = (SRC); \ + } + +#define atomic_store16(DST, SRC, ORDER) \ + if (ORDER == memory_order_seq_cst) { \ + InterlockedExchange16((short volatile *) (DST), (short) (SRC)); \ + } else { \ + *(DST) = (SRC); \ + } + +#define atomic_store(DST, SRC) \ + atomic_store_explicit(DST, SRC, memory_order_seq_cst) + +#define atomic_store_explicit(DST, SRC, ORDER) \ + if (sizeof *(DST) == 1) { \ + atomic_store8(DST, SRC, ORDER) \ + } else if (sizeof *(DST) == 2) { \ + atomic_store16( DST, SRC, ORDER) \ + } else if (sizeof *(DST) == 4) { \ + atomic_store32(DST, SRC, ORDER) \ + } else if (sizeof *(DST) == 8) { \ + atomic_store64(DST, SRC, ORDER) \ + } else { \ + abort(); \ + } + +/* On x86, for 'memory_order_seq_cst', if stores are locked, the corresponding + * reads don't need to be locked (based on the following in Intel Developers + * manual: + * “Locked operations are atomic with respect to all other memory operations + * and all externally visible events. Only instruction fetch and page table + * accesses can pass locked instructions. Locked instructions can be used to + * synchronize data written by one processor and read by another processor. + * For the P6 family processors, locked operations serialize all outstanding + * load and store operations (that is, wait for them to complete). This rule + * is also true for the Pentium 4 and Intel Xeon processors, with one + * exception. Load operations that reference weakly ordered memory types + * (such as the WC memory type) may not be serialized."). */ + + /* For 8, 16 and 32 bit variations. */ +#define atomic_readX(SRC, DST, ORDER) \ + *(DST) = *(SRC); + +/* MSVC converts 64 bit reads into two instructions. So there is + * a possibility that an interrupt can make a 64 bit read non-atomic even + * when 8 byte aligned. So use fully memory barrier InterlockedOr64(). */ +#ifdef _M_IX86 +#define atomic_read64(SRC, DST, ORDER) \ + __pragma (warning(push)) \ + __pragma (warning(disable:4047)) \ + *(DST) = InterlockedOr64((int64_t volatile *) (SRC), 0); \ + __pragma (warning(pop)) +#elif _M_X64 +/* 64 bit reads are atomic on amd64 if 64 bit aligned. */ +#define atomic_read64(SRC, DST, ORDER) \ + *(DST) = *(SRC); +#endif + +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) + +#define atomic_read_explicit(SRC, DST, ORDER) \ + if (sizeof *(DST) == 1 || sizeof *(DST) == 2 || sizeof *(DST) == 4) { \ + atomic_readX(SRC, DST, ORDER) \ + } else if (sizeof *(DST) == 8) { \ + atomic_read64(SRC, DST, ORDER) \ + } else { \ + abort(); \ + } + +/* For add, sub, and logical operations, for 8, 16 and 64 bit data types, + * functions for all the different memory orders does not exist + * (though documentation exists for some of them). The MSVC C++ library which + * implements the c11 atomics simply calls the full memory barrier function + * for everything in x86(see xatomic.h). So do the same here. */ + +/* For 8, 16 and 64 bit variations. */ +#define atomic_op(OP, X, RMW, ARG, ORIG, ORDER) \ + atomic_##OP##_generic(X, RMW, ARG, ORIG, ORDER) + +/* Arithmetic addition calls. */ + +#define atomic_add8(RMW, ARG, ORIG, ORDER) \ + *(ORIG) = _InterlockedExchangeAdd8((char volatile *) (RMW), \ + (char) (ARG)); + +#define atomic_add16(RMW, ARG, ORIG, ORDER) \ + *(ORIG) = _InterlockedExchangeAdd16((short volatile *) (RMW), \ + (short) (ARG)); + +#define atomic_add32(RMW, ARG, ORIG, ORDER) \ + *(ORIG) = InterlockedExchangeAdd((long volatile *) (RMW), \ + (long) (ARG)); +#define atomic_add64(RMW, ARG, ORIG, ORDER) \ + *(ORIG) = _InterlockedExchangeAdd64((int64_t volatile *) (RMW), \ + (int64_t) (ARG)); + +#define atomic_add(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ + if (sizeof *(RMW) == 1) { \ + atomic_add8(RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 2) { \ + atomic_add16(RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 4) { \ + atomic_add32(RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 8) { \ + atomic_add64(RMW, ARG, ORIG, ORDER) \ + } else { \ + abort(); \ + } + +/* Arithmetic subtraction calls. */ + +#define atomic_sub(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, (0 - (ARG)), ORIG, memory_order_seq_cst) + +#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_add_explicit(RMW, (0 - (ARG)), ORIG, ORDER) + +/* Logical 'and' calls. */ + +#define atomic_and32(RMW, ARG, ORIG, ORDER) \ + *(ORIG) = InterlockedAnd((int32_t volatile *) (RMW), (int32_t) (ARG)); + +/* For 8, 16 and 64 bit variations. */ +#define atomic_and_generic(X, RMW, ARG, ORIG, ORDER) \ + *(ORIG) = InterlockedAnd##X((int##X##_t volatile *) (RMW), \ + (int##X##_t) (ARG)); + +#define atomic_and(RMW, ARG, ORIG) \ + atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ + if (sizeof *(RMW) == 1) { \ + atomic_op(and, 8, RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 2) { \ + atomic_op(and, 16, RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 4) { \ + atomic_and32(RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 8) { \ + atomic_op(and, 64, RMW, ARG, ORIG, ORDER) \ + } else { \ + abort(); \ + } + +/* Logical 'Or' calls. */ + +#define atomic_or32(RMW, ARG, ORIG, ORDER) \ + *(ORIG) = InterlockedOr((int32_t volatile *) (RMW), (int32_t) (ARG)); + +/* For 8, 16 and 64 bit variations. */ +#define atomic_or_generic(X, RMW, ARG, ORIG, ORDER) \ + *(ORIG) = InterlockedOr##X((int##X##_t volatile *) (RMW), \ + (int##X##_t) (ARG)); + +#define atomic_or(RMW, ARG, ORIG) \ + atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ + if (sizeof *(RMW) == 1) { \ + atomic_op(or, 8, RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 2) { \ + atomic_op(or, 16, RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 4) { \ + atomic_or32(RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 8) { \ + atomic_op(or, 64, RMW, ARG, ORIG, ORDER) \ + } else { \ + abort(); \ + } + +/* Logical Xor calls. */ + +#define atomic_xor32(RMW, ARG, ORIG, ORDER) \ + *(ORIG) = InterlockedXor((int32_t volatile *) (RMW), (int32_t) (ARG)); + +/* For 8, 16 and 64 bit variations. */ +#define atomic_xor_generic(X, RMW, ARG, ORIG, ORDER) \ + *(ORIG) = InterlockedXor##X((int##X##_t volatile *) (RMW), \ + (int##X##_t) (ARG)); + +#define atomic_xor(RMW, ARG, ORIG) \ + atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ + if (sizeof *(RMW) == 1) { \ + atomic_op(xor, 8, RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 2) { \ + atomic_op(xor, 16, RMW, ARG, ORIG, ORDER) \ + } else if (sizeof *(RMW) == 4) { \ + atomic_xor32(RMW, ARG, ORIG, ORDER); \ + } else if (sizeof *(RMW) == 8) { \ + atomic_op(xor, 64, RMW, ARG, ORIG, ORDER) \ + } else { \ + abort(); \ + } + +#define atomic_compare_exchange_strong(DST, EXP, SRC) \ + atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ + memory_order_seq_cst, \ + memory_order_seq_cst) + +#define atomic_compare_exchange_weak atomic_compare_exchange_strong +#define atomic_compare_exchange_weak_explicit \ + atomic_compare_exchange_strong_explicit + +/* While intrinsics offering different memory ordering + * are available in MSVC C compiler, they are not defined + * in the C++ compiler. Ignore for compatibility. + * + * Use nested ternary operators as the GNU extension ({}) + * is not available. + */ + +#define atomic_exchange_explicit(DST, SRC, ORDER) \ + ((sizeof *(DST) == 1) ? \ + _InterlockedExchange8((char volatile *) DST, SRC) \ + : (sizeof *(DST) == 2) ? \ + _InterlockedExchange16((short volatile *) DST, SRC) \ + : (sizeof *(DST) == 4) ? \ + _InterlockedExchange((long int volatile *) DST, SRC) \ + : (sizeof *(DST) == 8) ? \ + _InterlockedExchange64((__int64 volatile *) DST, SRC) \ + : (abort(), 0)) + +#define atomic_exchange(DST, SRC) \ + atomic_exchange_explicit(DST, SRC, memory_order_seq_cst) + +/* MSVCs c++ compiler implements c11 atomics and looking through its + * implementation (in xatomic.h), orders are ignored for x86 platform. + * Do the same here. */ +static inline bool +atomic_compare_exchange8(int8_t volatile *dst, int8_t *expected, int8_t src) +{ + int8_t previous = _InterlockedCompareExchange8((char volatile *)dst, + src, *expected); + if (previous == *expected) { + return true; + } else { + *expected = previous; + return false; + } +} + +static inline bool +atomic_compare_exchange16(int16_t volatile *dst, int16_t *expected, + int16_t src) +{ + int16_t previous = InterlockedCompareExchange16(dst, src, *expected); + if (previous == *expected) { + return true; + } else { + *expected = previous; + return false; + } +} + +static inline bool +atomic_compare_exchange32(int32_t volatile *dst, int32_t *expected, + int32_t src) +{ + int32_t previous = InterlockedCompareExchange((long volatile *)dst, + src, *expected); + if (previous == *expected) { + return true; + } else { + *expected = previous; + return false; + } +} + +static inline bool +atomic_compare_exchange64(int64_t volatile *dst, int64_t *expected, + int64_t src) +{ + int64_t previous = InterlockedCompareExchange64(dst, src, *expected); + if (previous == *expected) { + return true; + } else { + *expected = previous; + return false; + } +} + +static inline bool +atomic_compare_unreachable() +{ + return true; +} + +#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ + (sizeof *(DST) == 1 \ + ? atomic_compare_exchange8((int8_t volatile *) (DST), (int8_t *) (EXP), \ + (int8_t) (SRC)) \ + : (sizeof *(DST) == 2 \ + ? atomic_compare_exchange16((int16_t volatile *) (DST), \ + (int16_t *) (EXP), (int16_t) (SRC)) \ + : (sizeof *(DST) == 4 \ + ? atomic_compare_exchange32((int32_t volatile *) (DST), \ + (int32_t *) (EXP), (int32_t) (SRC)) \ + : (sizeof *(DST) == 8 \ + ? atomic_compare_exchange64((int64_t volatile *) (DST), \ + (int64_t *) (EXP), (int64_t) (SRC)) \ + : ovs_fatal(0, "atomic operation with size greater than 8 bytes"), \ + atomic_compare_unreachable())))) + + +/* atomic_flag */ + +typedef ATOMIC(int32_t) atomic_flag; +#define ATOMIC_FLAG_INIT 0 + +#define atomic_flag_test_and_set(FLAG) \ + (bool) InterlockedBitTestAndSet(FLAG, 0) + +#define atomic_flag_test_and_set_explicit(FLAG, ORDER) \ + atomic_flag_test_and_set(FLAG) + +#define atomic_flag_clear_explicit(FLAG, ORDER) \ + atomic_flag_clear() +#define atomic_flag_clear(FLAG) \ + InterlockedBitTestAndReset(FLAG, 0) Index: openvswitch-2.17.2/include/internal/ovs-atomic-x86_64.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/ovs-atomic-x86_64.h @@ -0,0 +1,356 @@ +/* + * 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. + */ + +/* This header implements atomic operation primitives on x86_64 with GCC. */ +#ifndef IN_OVS_ATOMIC_H +#error "This header should only be included indirectly via ovs-atomic.h." +#endif + +#define OVS_ATOMIC_X86_64_IMPL 1 + +/* + * x86_64 Memory model (http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.html): + * + * - 1, 2, 4, and 8 byte loads and stores are atomic on aligned memory. + * - Loads are not reordered with other loads. + * - Stores are not reordered with OLDER loads. + * - Loads may be reordered with OLDER stores to a different memory location, + * but not with OLDER stores to the same memory location. + * - Stores are not reordered with other stores, except for special + * instructions (CLFLUSH, streaming stores, fast string operations). + * Most of these are not emitted by compilers, and as long as the + * atomic stores are not combined with any other stores, even the allowed + * reordering of the stores by a single fast string operation (e.g., "stos") + * is not a problem. + * - Neither loads nor stores are reordered with locked instructions. + * - Loads cannot pass earlier LFENCE or MFENCE instructions. + * - Stores cannot pass earlier LFENCE, SFENCE, or MFENCE instructions. + * - LFENCE instruction cannot pass earlier loads. + * - SFENCE instruction cannot pass earlier stores. + * - MFENCE instruction cannot pass earlier loads or stores. + * - Stores by a single processor are observed in the same order by all + * processors. + * - (Unlocked) Stores from different processors are NOT ordered. + * - Memory ordering obeys causality (memory ordering respects transitive + * visibility). + * - Any two stores are seen in a consistent order by processors other than + * the those performing the stores. + * - Locked instructions have total order. + * + * These rules imply that: + * + * - Locked instructions are not needed for aligned loads or stores to make + * them atomic. + * - All stores have release semantics; none of the preceding stores or loads + * can be reordered with following stores. Following loads could still be + * reordered to happen before the store, but that is not a violation of the + * release semantics. + * - All loads from a given memory location have acquire semantics with + * respect to the stores on the same memory location; none of the following + * loads or stores can be reordered with the load. Preceding stores to a + * different memory location MAY be reordered with the load, but that is not + * a violation of the acquire semantics (i.e., the loads and stores of two + * critical sections guarded by a different memory location can overlap). + * - Locked instructions serve as CPU memory barriers by themselves. + * - Locked stores implement the sequential consistency memory order. Using + * locked instructions when seq_cst memory order is requested allows normal + * loads to observe the stores in the same (total) order without using CPU + * memory barrier after the loads. + * + * NOTE: Some older AMD Opteron processors have a bug that violates the + * acquire semantics described above. The bug manifests as an unlocked + * read-modify-write operation following a "semaphore operation" operating + * on data that existed before entering the critical section; i.e., the + * preceding "semaphore operation" fails to function as an acquire barrier. + * The affected CPUs are AMD family 15, models 32 to 63. + * + * Ref. http://support.amd.com/TechDocs/25759.pdf errata #147. + */ + +/* Barriers. */ + +#define compiler_barrier() asm volatile(" " : : : "memory") +#define cpu_barrier() asm volatile("mfence;" : : : "memory") + +/* + * The 'volatile' keyword prevents the compiler from keeping the atomic + * value in a register, and generates a new memory access for each atomic + * operation. This allows the implementations of memory_order_relaxed and + * memory_order_consume to avoid issuing a compiler memory barrier, allowing + * full optimization of all surrounding non-atomic variables. + * + * The placement of the 'volatile' keyword after the 'TYPE' below is highly + * significant when the TYPE is a pointer type. In that case we want the + * pointer to be declared volatile, not the data type that is being pointed + * at! + */ +#define ATOMIC(TYPE) TYPE volatile + +/* Memory ordering. Must be passed in as a constant. */ +typedef enum { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst +} memory_order; + +#define ATOMIC_BOOL_LOCK_FREE 2 +#define ATOMIC_CHAR_LOCK_FREE 2 +#define ATOMIC_SHORT_LOCK_FREE 2 +#define ATOMIC_INT_LOCK_FREE 2 +#define ATOMIC_LONG_LOCK_FREE 2 +#define ATOMIC_LLONG_LOCK_FREE 2 +#define ATOMIC_POINTER_LOCK_FREE 2 + +#define IS_LOCKLESS_ATOMIC(OBJECT) \ + (sizeof(OBJECT) <= 8 && IS_POW2(sizeof(OBJECT))) + +#define ATOMIC_VAR_INIT(VALUE) VALUE +#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) + +/* + * The memory_model_relaxed does not need a compiler barrier, if the + * atomic operation can otherwise be guaranteed to not be moved with + * respect to other atomic operations on the same memory location. Using + * the 'volatile' keyword in the definition of the atomic types + * accomplishes this, as memory accesses to volatile data may not be + * optimized away, or be reordered with other volatile accesses. + * + * On x86 also memory_order_consume is automatic, and data dependency on a + * volatile atomic variable means that the compiler optimizations should not + * cause problems. That is, the compiler should not speculate the value of + * the atomic_read, as it is going to read it from the memory anyway. + * This allows omiting the compiler memory barrier on atomic_reads with + * memory_order_consume. This matches the definition of + * smp_read_barrier_depends() in Linux kernel as a nop for x86, and its usage + * in rcu_dereference(). + * + * We use this same logic below to choose inline assembly statements with or + * without a compiler memory barrier. + */ +static inline void +atomic_compiler_barrier(memory_order order) +{ + if (order > memory_order_consume) { + compiler_barrier(); + } +} + +static inline void +atomic_thread_fence(memory_order order) +{ + if (order == memory_order_seq_cst) { + cpu_barrier(); + } else { + atomic_compiler_barrier(order); + } +} + +static inline void +atomic_signal_fence(memory_order order) +{ + atomic_compiler_barrier(order); +} + +#define atomic_is_lock_free(OBJ) \ + ((void) *(OBJ), \ + IS_LOCKLESS_ATOMIC(*(OBJ)) ? 2 : 0) + +#define atomic_exchange__(DST, SRC, ORDER) \ + ({ \ + typeof(DST) dst___ = (DST); \ + typeof(*(DST)) src___ = (SRC); \ + \ + if ((ORDER) > memory_order_consume) { \ + asm volatile("xchg %1,%0 ; " \ + "# atomic_exchange__" \ + : "+r" (src___), /* 0 */ \ + "+m" (*dst___) /* 1 */ \ + :: "memory"); \ + } else { \ + asm volatile("xchg %1,%0 ; " \ + "# atomic_exchange__" \ + : "+r" (src___), /* 0 */ \ + "+m" (*dst___)); /* 1 */ \ + } \ + src___; \ + }) + +/* Atomic store: Valid memory models are: + * + * memory_order_relaxed, memory_order_release, and + * memory_order_seq_cst. */ +#define atomic_store_explicit(DST, SRC, ORDER) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(*(DST)) src__ = (SRC); \ + \ + if ((ORDER) != memory_order_seq_cst) { \ + atomic_compiler_barrier(ORDER); \ + *dst__ = src__; \ + } else { \ + atomic_exchange__(dst__, src__, ORDER); \ + } \ + (void) 0; \ + }) +#define atomic_store(DST, SRC) \ + atomic_store_explicit(DST, SRC, memory_order_seq_cst) + +/* Atomic read: Valid memory models are: + * + * memory_order_relaxed, memory_order_consume, memory_model_acquire, + * and memory_order_seq_cst. */ +#define atomic_read_explicit(SRC, DST, ORDER) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(SRC) src__ = (SRC); \ + \ + *dst__ = *src__; \ + atomic_compiler_barrier(ORDER); \ + (void) 0; \ + }) +#define atomic_read(SRC, DST) \ + atomic_read_explicit(SRC, DST, memory_order_seq_cst) + +#define atomic_compare_exchange__(DST, EXP, SRC, RES, CLOB) \ + asm volatile("lock; cmpxchg %3,%1 ; " \ + " sete %0 " \ + "# atomic_compare_exchange__" \ + : "=q" (RES), /* 0 */ \ + "+m" (*DST), /* 1 */ \ + "+a" (EXP) /* 2 */ \ + : "r" (SRC) /* 3 */ \ + : CLOB, "cc") + +/* All memory models are valid for read-modify-write operations. + * + * Valid memory models for the read operation of the current value in + * the failure case are the same as for atomic read, but can not be + * stronger than the success memory model. + * ORD_FAIL is ignored, as atomic_compare_exchange__ already implements + * at least as strong a barrier as allowed for ORD_FAIL in all cases. */ +#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORDER, ORD_FAIL) \ + ({ \ + typeof(DST) dst__ = (DST); \ + typeof(DST) expp__ = (EXP); \ + typeof(*(DST)) src__ = (SRC); \ + typeof(*(DST)) exp__ = *expp__; \ + uint8_t res__; \ + (void)ORD_FAIL; \ + \ + if ((ORDER) > memory_order_consume) { \ + atomic_compare_exchange__(dst__, exp__, src__, res__, \ + "memory"); \ + } else { \ + atomic_compare_exchange__(dst__, exp__, src__, res__, \ + "cc"); \ + } \ + if (!res__) { \ + *expp__ = exp__; \ + } \ + (bool)res__; \ + }) +#define atomic_compare_exchange_strong(DST, EXP, SRC) \ + atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ + memory_order_seq_cst, \ + memory_order_seq_cst) +#define atomic_compare_exchange_weak \ + atomic_compare_exchange_strong +#define atomic_compare_exchange_weak_explicit \ + atomic_compare_exchange_strong_explicit + +#define atomic_exchange_explicit(RMW, ARG, ORDER) \ + atomic_exchange__(RMW, ARG, ORDER) +#define atomic_exchange(RMW, ARG) \ + atomic_exchange_explicit(RMW, ARG, memory_order_seq_cst) + +#define atomic_add__(RMW, ARG, CLOB) \ + asm volatile("lock; xadd %0,%1 ; " \ + "# atomic_add__ " \ + : "+r" (ARG), /* 0 */ \ + "+m" (*RMW) /* 1 */ \ + :: CLOB, "cc") + +#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ + ({ \ + typeof(RMW) rmw__ = (RMW); \ + typeof(*(RMW)) arg__ = (ARG); \ + \ + if ((ORDER) > memory_order_consume) { \ + atomic_add__(rmw__, arg__, "memory"); \ + } else { \ + atomic_add__(rmw__, arg__, "cc"); \ + } \ + *(ORIG) = arg__; \ + }) +#define atomic_add(RMW, ARG, ORIG) \ + atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_add_explicit(RMW, -(ARG), ORIG, ORDER) +#define atomic_sub(RMW, ARG, ORIG) \ + atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +/* We could use simple locked instructions if the original value was not + * needed. */ +#define atomic_op__(RMW, OP, ARG, ORIG, ORDER) \ + ({ \ + typeof(RMW) rmw__ = (RMW); \ + typeof(ARG) arg__ = (ARG); \ + \ + typeof(*(RMW)) val__; \ + \ + atomic_read_explicit(rmw__, &val__, memory_order_relaxed); \ + do { \ + } while (!atomic_compare_exchange_weak_explicit(rmw__, &val__, \ + val__ OP arg__, \ + ORDER, \ + memory_order_relaxed)); \ + *(ORIG) = val__; \ + }) + +#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_op__(RMW, |, ARG, ORIG, ORDER) +#define atomic_or(RMW, ARG, ORIG) \ + atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_op__(RMW, ^, ARG, ORIG, ORDER) +#define atomic_xor(RMW, ARG, ORIG) \ + atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + +#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ + atomic_op__(RMW, &, ARG, ORIG, ORDER) +#define atomic_and(RMW, ARG, ORIG) \ + atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) + + +/* atomic_flag */ + +typedef ATOMIC(int) atomic_flag; +#define ATOMIC_FLAG_INIT { false } + +#define atomic_flag_test_and_set_explicit(FLAG, ORDER) \ + ((bool)atomic_exchange__(FLAG, 1, ORDER)) +#define atomic_flag_test_and_set(FLAG) \ + atomic_flag_test_and_set_explicit(FLAG, memory_order_seq_cst) + +#define atomic_flag_clear_explicit(FLAG, ORDER) \ + atomic_store_explicit(FLAG, 0, ORDER) +#define atomic_flag_clear(FLAG) \ + atomic_flag_clear_explicit(FLAG, memory_order_seq_cst) Index: openvswitch-2.17.2/include/internal/process.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/process.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2008, 2009, 2011, 2013 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef PROCESS_H +#define PROCESS_H 1 + +#include +#include + +struct process; + +struct process_info { + unsigned long int vsz; /* Virtual size, in kB. */ + unsigned long int rss; /* Resident set size, in kB. */ + long long int booted; /* ms since monitor started. */ + int crashes; /* # of crashes (usually 0). */ + long long int uptime; /* ms since last (re)started by monitor. */ + long long int cputime; /* ms of CPU used during 'uptime'. */ + int core_id; + char name[18]; +}; + +/* Starting and monitoring subprocesses. + * + * process_init() and process_start() may safely be called only from a + * single-threaded parent process. The parent process may safely create + * additional threads afterward, as long as the remaining functions in this + * group are called only from a single thread at any given time. */ +void process_init(void); +int process_start(char **argv, struct process **); +void process_destroy(struct process *); +int process_kill(const struct process *, int signr); +pid_t process_pid(const struct process *); +const char *process_name(const struct process *); +bool process_exited(struct process *); +int process_status(const struct process *); +void process_run(void); +void process_wait(struct process *); + +int count_crashes(pid_t); +bool get_process_info(pid_t, struct process_info *); + +/* These functions are thread-safe. */ +char *process_status_msg(int); +char *process_escape_args(char **argv); +char *process_search_path(const char *); + +#endif /* process.h */ Index: openvswitch-2.17.2/include/internal/random.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/random.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2012 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef RANDOM_H +#define RANDOM_H 1 + +#include +#include + +void random_init(void); +void random_set_seed(uint32_t); + +void random_bytes(void *, size_t); +uint32_t random_uint32(void); +uint64_t random_uint64(void); + +static inline int +random_range(int max) +{ + return random_uint32() % max; +} + +static inline uint8_t +random_uint8(void) +{ + return random_uint32(); +} + +static inline uint16_t +random_uint16(void) +{ + return random_uint32(); +} + +#endif /* random.h */ Index: openvswitch-2.17.2/include/internal/simap.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/simap.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2009, 2010, 2011, 2012, 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. + */ + +#ifndef SIMAP_H +#define SIMAP_H 1 + +#include "openvswitch/hmap.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* A map from strings to unsigned integers. */ +struct simap { + struct hmap map; /* Contains "struct simap_node"s. */ +}; + +struct simap_node { + struct hmap_node node; /* In struct simap's 'map' hmap. */ + char *name; + unsigned int data; +}; + +#define SIMAP_INITIALIZER(SIMAP) { HMAP_INITIALIZER(&(SIMAP)->map) } + +#define SIMAP_FOR_EACH(SIMAP_NODE, SIMAP) \ + HMAP_FOR_EACH_INIT (SIMAP_NODE, node, &(SIMAP)->map, \ + BUILD_ASSERT_TYPE(SIMAP_NODE, struct simap_node *), \ + BUILD_ASSERT_TYPE(SIMAP, struct simap *)) + +#define SIMAP_FOR_EACH_SAFE_SHORT(SIMAP_NODE, SIMAP) \ + HMAP_FOR_EACH_SAFE_SHORT_INIT (SIMAP_NODE, node, &(SIMAP)->map, \ + BUILD_ASSERT_TYPE(SIMAP_NODE, struct simap_node *), \ + BUILD_ASSERT_TYPE(SIMAP, struct simap *)) + +#define SIMAP_FOR_EACH_SAFE_LONG(SIMAP_NODE, NEXT, SIMAP) \ + HMAP_FOR_EACH_SAFE_LONG_INIT (SIMAP_NODE, NEXT, node, &(SIMAP)->map, \ + BUILD_ASSERT_TYPE(SIMAP_NODE, struct simap_node *), \ + BUILD_ASSERT_TYPE(NEXT, struct simap_node *), \ + BUILD_ASSERT_TYPE(SIMAP, struct simap *)) + +#define SIMAP_FOR_EACH_SAFE(...) \ + OVERLOAD_SAFE_MACRO(SIMAP_FOR_EACH_SAFE_LONG, \ + SIMAP_FOR_EACH_SAFE_SHORT, \ + 3, __VA_ARGS__) + +void simap_init(struct simap *); +void simap_destroy(struct simap *); +void simap_swap(struct simap *, struct simap *); +void simap_moved(struct simap *); +void simap_clear(struct simap *); + +bool simap_is_empty(const struct simap *); +size_t simap_count(const struct simap *); + +bool simap_put(struct simap *, const char *, unsigned int); +unsigned int simap_increase(struct simap *, const char *, unsigned int); + +unsigned int simap_get(const struct simap *, const char *); +struct simap_node *simap_find(const struct simap *, const char *); +struct simap_node *simap_find_len(const struct simap *, + const char *, size_t len); +bool simap_contains(const struct simap *, const char *); + +void simap_delete(struct simap *, struct simap_node *); +bool simap_find_and_delete(struct simap *, const char *); + +const struct simap_node **simap_sort(const struct simap *); +bool simap_equal(const struct simap *, const struct simap *); +uint32_t simap_hash(const struct simap *); + +#ifdef __cplusplus +} +#endif + +#endif /* simap.h */ Index: openvswitch-2.17.2/include/internal/skiplist.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/skiplist.h @@ -0,0 +1,49 @@ +/* Copyright (C) 2016 Hewlett Packard Enterprise Development LP + * All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. You may obtain + * a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +#ifndef LIB_SKIPLIST_H_ +#define LIB_SKIPLIST_H_ + +#include +#include +#include + +typedef int (skiplist_comparator)(const void *a, const void *b, + const void *conf); + +struct skiplist_node; + +struct skiplist; + +#define SKIPLIST_FOR_EACH (SKIPLIST_NODE, SKIPLIST) \ + for (SKIPLIST_NODE = skiplist_first(SKIPLIST); \ + SKIPLIST_NODE; \ + SKIPLIST_NODE = skiplist_next(SKIPLIST_NODE)) + +struct skiplist *skiplist_create(skiplist_comparator *object_comparator, + void *configuration); +void skiplist_insert(struct skiplist *sl, const void *object); +void *skiplist_delete(struct skiplist *sl, const void *object); +struct skiplist_node *skiplist_find(struct skiplist *sl, const void *value); +void *skiplist_get_data(struct skiplist_node *node); +uint32_t skiplist_get_size(struct skiplist *sl); +struct skiplist_node *skiplist_forward_to(struct skiplist *sl, + const void *value); +struct skiplist_node *skiplist_first(struct skiplist *sl); +struct skiplist_node *skiplist_next(struct skiplist_node *node); +void skiplist_destroy(struct skiplist *sl, void (*func)(void *)); + +#endif /* LIB_SKIPLIST_H_ */ Index: openvswitch-2.17.2/include/internal/socket-util.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/socket-util.h @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 SOCKET_UTIL_H +#define SOCKET_UTIL_H 1 + +#include +#include +#include +#include +#include +#include +#include +#include "openvswitch/types.h" +#include +#include + +struct ds; + +int set_nonblocking(int fd); +void xset_nonblocking(int fd); +void setsockopt_tcp_nodelay(int fd); +int set_dscp(int fd, int family, uint8_t dscp); + +bool addr_is_ipv6(const char *host_name); +int lookup_ip(const char *host_name, struct in_addr *address); +int lookup_ipv6(const char *host_name, struct in6_addr *address); + +int lookup_hostname(const char *host_name, struct in_addr *); + +int get_socket_rcvbuf(int sock); +int check_connection_completion(int fd); +void drain_fd(int fd, size_t n_packets); +ovs_be32 guess_netmask(ovs_be32 ip); + +void inet_parse_host_port_tokens(char *s, char **hostp, char **portp); +void inet_parse_port_host_tokens(char *s, char **portp, char **hostp); +bool inet_parse_active(const char *target, int default_port, + struct sockaddr_storage *ssp, + bool resolve_host, bool *dns_failure); +int inet_open_active(int style, const char *target, int default_port, + struct sockaddr_storage *ssp, int *fdp, uint8_t dscp); + +bool inet_parse_passive(const char *target, int default_port, + struct sockaddr_storage *ssp); +int inet_open_passive(int style, const char *target, int default_port, + struct sockaddr_storage *ssp, uint8_t dscp, + bool kernel_print_port); + +bool inet_parse_address(const char *target, struct sockaddr_storage *); + +int read_fully(int fd, void *, size_t, size_t *bytes_read); +int write_fully(int fd, const void *, size_t, size_t *bytes_written); + +int fsync_parent_dir(const char *file_name); +int get_mtime(const char *file_name, struct timespec *mtime); + +char *describe_fd(int fd); + +/* Default value of dscp bits for connection between controller and manager. + * Value of IPTOS_PREC_INTERNETCONTROL = 0xc0 which is defined + * in is used. */ +#define DSCP_DEFAULT (IPTOS_PREC_INTERNETCONTROL >> 2) + +/* Functions for working with sockaddr that might contain an IPv4 or + * IPv6 address. */ +bool sa_is_ip(const struct sockaddr *); +uint16_t sa_get_port(const struct sockaddr *); +struct in6_addr sa_get_address(const struct sockaddr *); +void sa_format_address(const struct sockaddr *, struct ds *); +void sa_format_address_nobracks(const struct sockaddr *, struct ds *); +size_t sa_length(const struct sockaddr *); + +/* Functions for working with sockaddr_storage that might contain an IPv4 or + * IPv6 address. */ +bool ss_is_ip(const struct sockaddr_storage *); +uint16_t ss_get_port(const struct sockaddr_storage *); +struct in6_addr ss_get_address(const struct sockaddr_storage *); +void ss_format_address(const struct sockaddr_storage *, struct ds *); +void ss_format_address_nobracks(const struct sockaddr_storage *, struct ds *); +size_t ss_length(const struct sockaddr_storage *); + +const char *sock_strerror(int error); + +#ifndef _WIN32 +void xpipe(int fds[2]); +void xpipe_nonblocking(int fds[2]); + +int drain_rcvbuf(int fd); + +int make_unix_socket(int style, bool nonblock, + const char *bind_path, const char *connect_path); +int get_unix_name_len(const struct sockaddr_un *sun, socklen_t sun_len); + +/* Universal sendmmsg and recvmmsg support on Linux. + * + * New enough Linux supports sendmmsg and recvmmsg, but older versions do not. + * We add the following infrastructure to allow all code on Linux to use + * sendmmsg and recvmmsg, regardless of platform support: + * + * - For platforms that lack these functions entirely, we emulate them. + * + * - With newer glibc but an old kernel, sendmmsg() and recvmmsg() fail with + * ENOSYS. To compensate, even if these functions appear to be available, we + * wrap them with handlers that use our emulation in this case. + */ +#ifdef __linux__ +#ifndef HAVE_STRUCT_MMSGHDR_MSG_LEN +struct mmsghdr { + struct msghdr msg_hdr; + unsigned int msg_len; +}; +#endif + +#ifndef HAVE_SENDMMSG +int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int); +int recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *); +#else +#define sendmmsg wrap_sendmmsg +int wrap_sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int); +#define recvmmsg wrap_recvmmsg +int wrap_recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *); +#endif +#endif /* __linux__ */ + +/* Helpers for calling ioctl() on an AF_INET socket. */ +struct ifreq; +int af_inet_ioctl(unsigned long int command, const void *arg); +int af_inet_ifreq_ioctl(const char *name, struct ifreq *, + unsigned long int cmd, const char *cmd_name); + +#define closesocket close +#endif + +#ifdef _WIN32 +static inline int make_unix_socket(int style, bool nonblock, + const char *bind_path, + const char *connect_path) +{ + return -EINVAL; +} + +/* Windows defines the 'optval' argument as char * instead of void *. */ +#define setsockopt(sock, level, optname, optval, optlen) \ + rpl_setsockopt(sock, level, optname, optval, optlen) +static inline int rpl_setsockopt(int sock, int level, int optname, + const void *optval, socklen_t optlen) +{ + return (setsockopt)(sock, level, optname, (const char *)optval, optlen); +} + +#define getsockopt(sock, level, optname, optval, optlen) \ + rpl_getsockopt(sock, level, optname, optval, optlen) +static inline int rpl_getsockopt(int sock, int level, int optname, + void *optval, socklen_t *optlen) +{ + return (getsockopt)(sock, level, optname, (char *)optval, optlen); +} +#endif + +/* In Windows platform, errno is not set for socket calls. + * The last error has to be gotten from WSAGetLastError(). */ +static inline int sock_errno(void) +{ +#ifdef _WIN32 + return WSAGetLastError(); +#else + return errno; +#endif +} + +#endif /* socket-util.h */ Index: openvswitch-2.17.2/include/internal/sort.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/sort.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2009 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SORT_H +#define SORT_H 1 + +#include + +void sort(size_t count, + int (*compare)(size_t a, size_t b, void *aux), + void (*swap)(size_t a, size_t b, void *aux), + void *aux); + +#endif /* sort.h */ Index: openvswitch-2.17.2/include/internal/stopwatch.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/stopwatch.h @@ -0,0 +1,59 @@ +/* Copyright (c) 2017 Red Hat, 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 STOPWATCH_H +#define STOPWATCH_H 1 + +#include + +enum stopwatch_units { + SW_MS, + SW_US, + SW_NS, +}; + +struct stopwatch_stats { + unsigned long long count; /* Total number of samples. */ + enum stopwatch_units unit; /* Unit of following values. */ + unsigned long long max; /* Maximum value. */ + unsigned long long min; /* Minimum value. */ + double pctl_95; /* 95th percentile. */ + double ewma_50; /* Exponentially weighted moving average + (alpha 0.50). */ + double ewma_1; /* Exponentially weighted moving average + (alpha 0.01). */ +}; + +/* Create a new stopwatch. + * The "units" are not used for any calculations but are printed when + * statistics are requested. + */ +void stopwatch_create(const char *name, enum stopwatch_units units); + +/* Start a stopwatch. */ +void stopwatch_start(const char *name, unsigned long long ts); + +/* Stop a stopwatch. The elapsed time will be used for updating statistics + * for this stopwatch. + */ +void stopwatch_stop(const char *name, unsigned long long ts); + +/* Retrieve statistics calculated from collected samples */ +bool stopwatch_get_stats(const char *name, struct stopwatch_stats *stats); + +/* Block until all enqueued samples have been processed. */ +void stopwatch_sync(void); + +#endif /* stopwatch.h */ Index: openvswitch-2.17.2/include/internal/stream-ssl.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/stream-ssl.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef STREAM_SSL_H +#define STREAM_SSL_H 1 + +#include + +bool stream_ssl_is_configured(void); +void stream_ssl_set_private_key_file(const char *file_name); +void stream_ssl_set_certificate_file(const char *file_name); +void stream_ssl_set_ca_cert_file(const char *file_name, bool bootstrap); +void stream_ssl_set_peer_ca_cert_file(const char *file_name); +void stream_ssl_set_key_and_cert(const char *private_key_file, + const char *certificate_file); +void stream_ssl_set_protocols(const char *arg); +void stream_ssl_set_ciphers(const char *arg); + +#define SSL_OPTION_ENUMS \ + OPT_SSL_PROTOCOLS, \ + OPT_SSL_CIPHERS + +#define STREAM_SSL_LONG_OPTIONS \ + {"private-key", required_argument, NULL, 'p'}, \ + {"certificate", required_argument, NULL, 'c'}, \ + {"ca-cert", required_argument, NULL, 'C'}, \ + {"ssl-protocols", required_argument, NULL, OPT_SSL_PROTOCOLS}, \ + {"ssl-ciphers", required_argument, NULL, OPT_SSL_CIPHERS} + +#define STREAM_SSL_OPTION_HANDLERS \ + case 'p': \ + stream_ssl_set_private_key_file(optarg); \ + break; \ + \ + case 'c': \ + stream_ssl_set_certificate_file(optarg); \ + break; \ + \ + case 'C': \ + stream_ssl_set_ca_cert_file(optarg, false); \ + break; \ + \ + case OPT_SSL_PROTOCOLS: \ + stream_ssl_set_protocols(optarg); \ + break; \ + \ + case OPT_SSL_CIPHERS: \ + stream_ssl_set_ciphers(optarg); \ + break; + +#define STREAM_SSL_CASES \ + case 'p': case 'c': case 'C': case OPT_SSL_PROTOCOLS: case OPT_SSL_CIPHERS: + +#endif /* stream-ssl.h */ Index: openvswitch-2.17.2/include/internal/svec.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/svec.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2008, 2009, 2011 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SVEC_H +#define SVEC_H 1 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct svec { + char **names; + size_t n; + size_t allocated; +}; + +#define SVEC_EMPTY_INITIALIZER { NULL, 0, 0 } + +void svec_init(struct svec *); +void svec_clone(struct svec *, const struct svec *); +void svec_destroy(struct svec *); +void svec_clear(struct svec *); +bool svec_is_empty(const struct svec *); +void svec_add(struct svec *, const char *); +void svec_add_nocopy(struct svec *, char *); +void svec_del(struct svec *, const char *); +void svec_append(struct svec *, const struct svec *); +void svec_terminate(struct svec *); +void svec_sort(struct svec *); +void svec_sort_unique(struct svec *); +void svec_unique(struct svec *); +void svec_compact(struct svec *); +void svec_shuffle(struct svec *); +void svec_diff(const struct svec *a, const struct svec *b, + struct svec *a_only, struct svec *both, struct svec *b_only); +bool svec_contains(const struct svec *, const char *); +bool svec_contains_unsorted(const struct svec *, const char *); +size_t svec_find(const struct svec *, const char *); +bool svec_is_sorted(const struct svec *); +bool svec_is_unique(const struct svec *); +const char *svec_get_duplicate(const struct svec *); +void svec_swap(struct svec *a, struct svec *b); +void svec_print(const struct svec *svec, const char *title); +void svec_parse_words(struct svec *svec, const char *words); +bool svec_equal(const struct svec *, const struct svec *); +char *svec_join(const struct svec *, + const char *delimiter, const char *terminator); +const char *svec_back(const struct svec *); +void svec_pop_back(struct svec *); + +/* Iterates over the names in SVEC, assigning each name in turn to NAME and its + * index to INDEX. */ +#define SVEC_FOR_EACH(INDEX, NAME, SVEC) \ + for ((INDEX) = 0; \ + ((INDEX) < (SVEC)->n \ + ? (NAME) = (SVEC)->names[INDEX], 1 \ + : 0); \ + (INDEX)++) + +#ifdef __cplusplus +} +#endif + +#endif /* svec.h */ Index: openvswitch-2.17.2/include/internal/table.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/table.h @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef TABLE_H +#define TABLE_H 1 + +#include +#include +#include "openvswitch/compiler.h" +#include "openvswitch/json.h" + +struct ds; +struct table_style; + +/* Manipulating tables and their rows and columns. */ + +struct table { + struct cell *cells; + struct column *columns; + size_t n_columns, allocated_columns; + size_t n_rows, allocated_rows; + size_t current_column; + char *caption; + bool timestamp; +}; + +void table_init(struct table *); +void table_destroy(struct table *); +void table_set_caption(struct table *, char *caption); +void table_set_timestamp(struct table *, bool timestamp); + +void table_add_column(struct table *, const char *heading, ...) + OVS_PRINTF_FORMAT(2, 3); +void table_add_row(struct table *); + +/* Table cells. */ + +struct cell { + /* Literal text. */ + char *text; + + /* JSON. */ + struct json *json; + const struct ovsdb_type *type; +}; + +struct cell *table_add_cell(struct table *); + +/* Table formatting. */ + +enum table_format { + TF_TABLE, /* 2-d table. */ + TF_LIST, /* One cell per line, one row per paragraph. */ + TF_HTML, /* HTML table. */ + TF_CSV, /* Comma-separated lines. */ + TF_JSON /* JSON. */ +}; + +enum cell_format { + CF_STRING, /* String format. */ + CF_BARE, /* String format without most punctuation. */ + CF_JSON /* JSON. */ +}; + +struct table_style { + enum table_format format; /* TF_*. */ + enum cell_format cell_format; /* CF_*. */ + bool headings; /* Include headings? */ + int json_flags; /* CF_JSON: Flags for json_to_string(). */ + int max_column_width; /* CF_STRING: Limit for column width. */ +}; + +#define TABLE_STYLE_DEFAULT { TF_LIST, CF_STRING, true, JSSF_SORT, 0 } +static const struct table_style table_style_default = TABLE_STYLE_DEFAULT; + +#define TABLE_OPTION_ENUMS \ + OPT_NO_HEADINGS, \ + OPT_PRETTY, \ + OPT_BARE, \ + OPT_MAX_COLUMN_WIDTH + +#define TABLE_LONG_OPTIONS \ + {"format", required_argument, NULL, 'f'}, \ + {"data", required_argument, NULL, 'd'}, \ + {"no-headings", no_argument, NULL, OPT_NO_HEADINGS}, \ + {"pretty", no_argument, NULL, OPT_PRETTY}, \ + {"bare", no_argument, NULL, OPT_BARE}, \ + {"max-column-width", required_argument, NULL, OPT_MAX_COLUMN_WIDTH} + +#define TABLE_OPTION_HANDLERS(STYLE) \ + case 'f': \ + table_parse_format(STYLE, optarg); \ + break; \ + \ + case 'd': \ + table_parse_cell_format(STYLE, optarg); \ + break; \ + \ + case OPT_NO_HEADINGS: \ + (STYLE)->headings = false; \ + break; \ + \ + case OPT_PRETTY: \ + (STYLE)->json_flags |= JSSF_PRETTY; \ + break; \ + \ + case OPT_BARE: \ + (STYLE)->format = TF_LIST; \ + (STYLE)->cell_format = CF_BARE; \ + (STYLE)->headings = false; \ + break; \ + \ + case OPT_MAX_COLUMN_WIDTH: \ + (STYLE)->max_column_width = atoi(optarg); \ + break; + +void table_parse_format(struct table_style *, const char *format); +void table_parse_cell_format(struct table_style *, const char *format); + +void table_print(const struct table *, const struct table_style *); +void table_format(const struct table *, const struct table_style *, + struct ds *); +void table_format_reset(void); +void table_usage(void); + +#endif /* table.h */ Index: openvswitch-2.17.2/include/internal/unixctl.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/unixctl.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2008, 2009, 2011 Nicira, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef UNIXCTL_H +#define UNIXCTL_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* Server for Unix domain socket control connection. */ +struct unixctl_server; +int unixctl_server_create(const char *path, struct unixctl_server **); +void unixctl_server_run(struct unixctl_server *); +void unixctl_server_wait(struct unixctl_server *); +void unixctl_server_destroy(struct unixctl_server *); + +const char *unixctl_server_get_path(const struct unixctl_server *); + +/* Client for Unix domain socket control connection. */ +struct jsonrpc; +int unixctl_client_create(const char *path, struct jsonrpc **client); +int unixctl_client_transact(struct jsonrpc *client, + const char *command, + int argc, char *argv[], + char **result, char **error); + +/* Command registration. */ +struct unixctl_conn; +typedef void unixctl_cb_func(struct unixctl_conn *, + int argc, const char *argv[], void *aux); +void unixctl_command_register(const char *name, const char *usage, + int min_args, int max_args, + unixctl_cb_func *cb, void *aux); +void unixctl_command_reply_error(struct unixctl_conn *, const char *error); +void unixctl_command_reply(struct unixctl_conn *, const char *body); + +#ifdef __cplusplus +} +#endif + +#endif /* unixctl.h */ Index: openvswitch-2.17.2/include/internal/uuid.h =================================================================== --- /dev/null +++ openvswitch-2.17.2/include/internal/uuid.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2008, 2009, 2010, 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. + */ + +#ifndef UUID_H +#define UUID_H 1 + +#include "openvswitch/uuid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* An initializer or expression for an all-zero UUID. */ +#define UUID_ZERO ((struct uuid) { .parts = { 0, 0, 0, 0 } }) + +/* Formats a UUID as a string, in the conventional format. + * + * Example: + * struct uuid uuid = ...; + * printf("This UUID is "UUID_FMT"\n", UUID_ARGS(&uuid)); + * + */ +#define UUID_LEN 36 +#define UUID_FMT "%08x-%04x-%04x-%04x-%04x%08x" +#define UUID_ARGS(UUID) \ + ((unsigned int) ((UUID)->parts[0])), \ + ((unsigned int) ((UUID)->parts[1] >> 16)), \ + ((unsigned int) ((UUID)->parts[1] & 0xffff)), \ + ((unsigned int) ((UUID)->parts[2] >> 16)), \ + ((unsigned int) ((UUID)->parts[2] & 0xffff)), \ + ((unsigned int) ((UUID)->parts[3])) + +/* Returns a hash value for 'uuid'. This hash value is the same regardless of + * whether we are running on a 32-bit or 64-bit or big-endian or little-endian + * architecture. */ +static inline size_t +uuid_hash(const struct uuid *uuid) +{ + return uuid->parts[0]; +} + +/* Returns true if 'a == b', false otherwise. */ +static inline bool +uuid_equals(const struct uuid *a, const struct uuid *b) +{ + return (a->parts[0] == b->parts[0] + && a->parts[1] == b->parts[1] + && a->parts[2] == b->parts[2] + && a->parts[3] == b->parts[3]); +} + +/* Returns the first 'n' hex digits of 'uuid', for 0 < 'n' <= 8. + * + * This is useful for displaying a few leading digits of the uuid, e.g. to + * display 4 digits: + * printf("%04x", uuid_prefix(uuid, 4)); + */ +static inline unsigned int +uuid_prefix(const struct uuid *uuid, int digits) +{ + return (uuid->parts[0] >> (32 - 4 * digits)); +} + +void uuid_init(void); +void uuid_generate(struct uuid *); +struct uuid uuid_random(void); +void uuid_zero(struct uuid *); +bool uuid_is_zero(const struct uuid *); +int uuid_compare_3way(const struct uuid *, const struct uuid *); +bool uuid_from_string(struct uuid *, const char *); +bool uuid_from_string_prefix(struct uuid *, const char *); +int uuid_is_partial_string(const char *); +int uuid_is_partial_match(const struct uuid *, const char *match); +void uuid_set_bits_v4(struct uuid *); + +#ifdef __cplusplus +} +#endif + +#endif /* uuid.h */ Index: openvswitch-2.17.2/lib/bundle.h =================================================================== --- openvswitch-2.17.2.orig/lib/bundle.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (c) 2011, 2012, 2013, 2014, 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. - */ - -#ifndef BUNDLE_H -#define BUNDLE_H 1 - -#include -#include -#include -#include -#include -#include - -#include "openvswitch/compiler.h" -#include "openflow/nicira-ext.h" -#include "openvswitch/ofp-errors.h" -#include "openvswitch/types.h" - -struct ds; -struct flow; -struct flow_wildcards; -struct match; -struct ofpact_bundle; -struct ofpbuf; -struct ofputil_port_map; - -/* NXAST_BUNDLE helper functions. - * - * See lib/ofp-actions.c for NXAST_BUNDLE specification. */ - -#define BUNDLE_MAX_MEMBERS 2048 - -ofp_port_t bundle_execute(const struct ofpact_bundle *, const struct flow *, - struct flow_wildcards *wc, - bool (*member_enabled)(ofp_port_t ofp_port, void *aux), - void *aux); -enum ofperr bundle_check(const struct ofpact_bundle *, ofp_port_t max_ports, - const struct match *); -char *bundle_parse(const char *, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts) OVS_WARN_UNUSED_RESULT; -char *bundle_parse_load(const char *, const struct ofputil_port_map *port_map, - struct ofpbuf *ofpacts) - OVS_WARN_UNUSED_RESULT; -void bundle_format(const struct ofpact_bundle *, - const struct ofputil_port_map *, struct ds *); - -#endif /* bundle.h */ Index: openvswitch-2.17.2/lib/byte-order.h =================================================================== --- openvswitch-2.17.2.orig/lib/byte-order.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2008, 2010, 2011, 2013, 2016 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 BYTE_ORDER_H -#define BYTE_ORDER_H 1 - -#include -#include -#include -#include -#include "openvswitch/types.h" - -#ifndef __CHECKER__ -#if !(defined(_WIN32) || defined(htonll)) -static inline ovs_be64 -htonll(uint64_t n) -{ - return htonl(1) == 1 ? n : ((uint64_t) htonl(n) << 32) | htonl(n >> 32); -} - -static inline uint64_t -ntohll(ovs_be64 n) -{ - return htonl(1) == 1 ? n : ((uint64_t) ntohl(n) << 32) | ntohl(n >> 32); -} -#endif /* !(defined(_WIN32) || defined(htonll)) */ -#else -/* Making sparse happy with these functions also makes them unreadable, so - * don't bother to show it their implementations. */ -ovs_be64 htonll(uint64_t); -uint64_t ntohll(ovs_be64); -#endif - -static inline ovs_be128 -hton128(const ovs_u128 src) -{ - ovs_be128 dst; - - dst.be64.hi = htonll(src.u64.hi); - dst.be64.lo = htonll(src.u64.lo); - return dst; -} - -static inline ovs_u128 -ntoh128(const ovs_be128 src) -{ - ovs_u128 dst; - - dst.u64.hi = ntohll(src.be64.hi); - dst.u64.lo = ntohll(src.be64.lo); - return dst; -} - -static inline uint32_t -uint32_byteswap(uint32_t crc) { - return (((crc & 0x000000ff) << 24) | - ((crc & 0x0000ff00) << 8) | - ((crc & 0x00ff0000) >> 8) | - ((crc & 0xff000000) >> 24)); -} - -/* These macros may substitute for htons(), htonl(), and htonll() in contexts - * where function calls are not allowed, such as case labels. They should not - * be used elsewhere because all of them evaluate their argument many times. */ -#if defined(WORDS_BIGENDIAN) || __CHECKER__ -#define CONSTANT_HTONS(VALUE) ((OVS_FORCE ovs_be16) ((VALUE) & 0xffff)) -#define CONSTANT_HTONL(VALUE) ((OVS_FORCE ovs_be32) ((VALUE) & 0xffffffff)) -#define CONSTANT_HTONLL(VALUE) \ - ((OVS_FORCE ovs_be64) ((VALUE) & UINT64_C(0xffffffffffffffff))) -#else -#define CONSTANT_HTONS(VALUE) \ - (((((ovs_be16) (VALUE)) & 0xff00) >> 8) | \ - ((((ovs_be16) (VALUE)) & 0x00ff) << 8)) -#define CONSTANT_HTONL(VALUE) \ - (((((ovs_be32) (VALUE)) & 0x000000ff) << 24) | \ - ((((ovs_be32) (VALUE)) & 0x0000ff00) << 8) | \ - ((((ovs_be32) (VALUE)) & 0x00ff0000) >> 8) | \ - ((((ovs_be32) (VALUE)) & 0xff000000) >> 24)) -#define CONSTANT_HTONLL(VALUE) \ - (((((ovs_be64) (VALUE)) & UINT64_C(0x00000000000000ff)) << 56) | \ - ((((ovs_be64) (VALUE)) & UINT64_C(0x000000000000ff00)) << 40) | \ - ((((ovs_be64) (VALUE)) & UINT64_C(0x0000000000ff0000)) << 24) | \ - ((((ovs_be64) (VALUE)) & UINT64_C(0x00000000ff000000)) << 8) | \ - ((((ovs_be64) (VALUE)) & UINT64_C(0x000000ff00000000)) >> 8) | \ - ((((ovs_be64) (VALUE)) & UINT64_C(0x0000ff0000000000)) >> 24) | \ - ((((ovs_be64) (VALUE)) & UINT64_C(0x00ff000000000000)) >> 40) | \ - ((((ovs_be64) (VALUE)) & UINT64_C(0xff00000000000000)) >> 56)) -#endif - -/* Returns the ovs_be32 that you would get from: - * - * union { uint8_t b[4]; ovs_be32 be32; } x = { .b = { b0, b1, b2, b3 } }; - * return x.be32; - * - * but without the undefined behavior. */ -static inline ovs_be32 -bytes_to_be32(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) -{ -#if WORDS_BIGENDIAN - uint32_t x = ((uint32_t) b0 << 24) | (b1 << 16) | (b2 << 8) | b3; -#else - uint32_t x = ((uint32_t) b3 << 24) | (b2 << 16) | (b1 << 8) | b0; -#endif - return (OVS_FORCE ovs_be32) x; -} - -/* These functions zero-extend big-endian values to longer ones, - * or truncate long big-endian value to shorter ones. */ -#ifndef __CHECKER__ -#if WORDS_BIGENDIAN -static inline ovs_be32 be16_to_be32(ovs_be16 x) { return x; } -static inline ovs_be64 be16_to_be64(ovs_be16 x) { return x; } -static inline ovs_be64 be32_to_be64(ovs_be32 x) { return x; } -static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x; } -static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x; } -static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x; } -#else /* !WORDS_BIGENDIAN */ -static inline ovs_be32 be16_to_be32(ovs_be16 x) { return (ovs_be32) x << 16; } -static inline ovs_be64 be16_to_be64(ovs_be16 x) { return (ovs_be64) x << 48; } -static inline ovs_be64 be32_to_be64(ovs_be32 x) { return (ovs_be64) x << 32; } -static inline ovs_be32 be64_to_be32(ovs_be64 x) { return x >> 32; } -static inline ovs_be16 be64_to_be16(ovs_be64 x) { return x >> 48; } -static inline ovs_be16 be32_to_be16(ovs_be32 x) { return x >> 16; } -#endif /* !WORDS_BIGENDIAN */ -#else /* __CHECKER__ */ -/* Making sparse happy with these functions also makes them unreadable, so - * don't bother to show it their implementations. */ -ovs_be32 be16_to_be32(ovs_be16); -ovs_be64 be16_to_be64(ovs_be16); -ovs_be64 be32_to_be64(ovs_be32); -ovs_be32 be64_to_be32(ovs_be64); -ovs_be16 be64_to_be16(ovs_be64); -ovs_be16 be32_to_be16(ovs_be32); -#endif - -#endif /* byte-order.h */ Index: openvswitch-2.17.2/lib/colors.h =================================================================== --- openvswitch-2.17.2.orig/lib/colors.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016 6WIND S.A. - * - * 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 COLORS_H -#define COLORS_H 1 - -#include - -struct colors { - /* Color codes for various situation. Each of these is a fully formed - * Select Graphic Rendition (SGR, "\33[...m") start string for the - * appropriate color. - */ - char *actions; - char *drop; - char *learn; - char *param; - char *paren; - char *special; - char *value; - - /* SGR end string. */ - char *end; -}; -extern struct colors colors; - -void colors_init(bool enable_color); - -#endif /* colors.h */ Index: openvswitch-2.17.2/lib/command-line.h =================================================================== --- openvswitch-2.17.2.orig/lib/command-line.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010 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 COMMAND_LINE_H -#define COMMAND_LINE_H 1 - -/* Utilities for command-line parsing. */ - -#include "openvswitch/compiler.h" - -struct option; - -/* Command handler context */ -struct ovs_cmdl_context { - /* number of command line arguments */ - int argc; - /* array of command line arguments */ - char **argv; - /* private context data defined by the API user */ - void *pvt; -}; - -typedef void (*ovs_cmdl_handler)(struct ovs_cmdl_context *); - -struct ovs_cmdl_command { - const char *name; - const char *usage; - int min_args; - int max_args; - ovs_cmdl_handler handler; - enum { OVS_RO, OVS_RW } mode; /* Does this command modify things? */ -}; - -char *ovs_cmdl_long_options_to_short_options(const struct option *options); - -struct ovs_cmdl_parsed_option { - const struct option *o; - char *arg; -}; -char *ovs_cmdl_parse_all(int argc, char *argv[], const struct option *, - struct ovs_cmdl_parsed_option **, size_t *) - OVS_WARN_UNUSED_RESULT; - -char **ovs_cmdl_env_parse_all(int *argcp, char *argv_[], - const char *env_options); - -void ovs_cmdl_print_options(const struct option *options); -void ovs_cmdl_print_commands(const struct ovs_cmdl_command *commands); - -void ovs_cmdl_run_command(struct ovs_cmdl_context *, - const struct ovs_cmdl_command[]); -void ovs_cmdl_run_command_read_only(struct ovs_cmdl_context *, - const struct ovs_cmdl_command[]); - -void ovs_cmdl_proctitle_init(int argc, char **argv); -#if defined(__FreeBSD__) || defined(__NetBSD__) -#define ovs_cmdl_proctitle_set setproctitle -#else -void ovs_cmdl_proctitle_set(const char *, ...) - OVS_PRINTF_FORMAT(1, 2); -#endif -void ovs_cmdl_proctitle_restore(void); - -#endif /* command-line.h */ Index: openvswitch-2.17.2/lib/crc32c.h =================================================================== --- openvswitch-2.17.2.orig/lib/crc32c.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2012 The University of Waikato. - * Author: Joe Stringer - * - * 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 CRC32C_H -#define CRC32C_H 1 - -#include "openvswitch/types.h" - -ovs_be32 crc32c(const uint8_t *data, size_t); - -#endif /* crc32c.h */ Index: openvswitch-2.17.2/lib/csum.h =================================================================== --- openvswitch-2.17.2.orig/lib/csum.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2008, 2011, 2015 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef CSUM_H -#define CSUM_H 1 - -#include -#include -#include "openvswitch/types.h" - -struct in6_addr; - -ovs_be16 csum(const void *, size_t); -uint32_t csum_continue(uint32_t partial, const void *, size_t); -ovs_be16 csum_finish(uint32_t partial); -ovs_be16 recalc_csum16(ovs_be16 old_csum, ovs_be16 old_u16, ovs_be16 new_u16); -ovs_be16 recalc_csum32(ovs_be16 old_csum, ovs_be32 old_u32, ovs_be32 new_u32); -ovs_be16 recalc_csum48(ovs_be16 old_csum, const struct eth_addr old_mac, - const struct eth_addr new_mac); -ovs_be16 recalc_csum128(ovs_be16 old_csum, ovs_16aligned_be32 old_u32[4], - const struct in6_addr *); - -#ifndef __CHECKER__ -/* Adds the 16 bits in 'new' to the partial IP checksum 'partial' and returns - * the updated checksum. (To start a new checksum, pass 0 for 'partial'. To - * obtain the finished checksum, pass the return value to csum_finish().) */ -static inline uint32_t -csum_add16(uint32_t partial, ovs_be16 new) -{ - return partial + new; -} - -/* Adds the 32 bits in 'new' to the partial IP checksum 'partial' and returns - * the updated checksum. (To start a new checksum, pass 0 for 'partial'. To - * obtain the finished checksum, pass the return value to csum_finish().) */ -static inline uint32_t -csum_add32(uint32_t partial, ovs_be32 new) -{ - return partial + (new >> 16) + (new & 0xffff); -} -#else -uint32_t csum_add16(uint32_t partial, ovs_be16); -uint32_t csum_add32(uint32_t partial, ovs_be32); -#endif - -#endif /* csum.h */ Index: openvswitch-2.17.2/lib/daemon.h =================================================================== --- openvswitch-2.17.2.orig/lib/daemon.h +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DAEMON_H -#define DAEMON_H 1 - -#include -#include -#include - -/* This file provides an interface for utilities to run in the background - * as daemons on POSIX platforms like Linux or as services on Windows platform. - * Some of the functionalities defined in this file are only applicable to - * POSIX platforms and some are applicable only on Windows. As such, the - * function definitions unique to each platform are separated out with - * ifdef macros. More descriptive comments on individual functions are provided - * in daemon-unix.c (for POSIX platforms) and daemon-windows.c (for Windows). - - * The DAEMON_OPTION_ENUMS, DAEMON_LONG_OPTIONS and DAEMON_OPTION_HANDLERS - * macros are useful for parsing command-line options in individual utilities. - * For e.g., the command-line option "--monitor" is recognized on Linux - * and results in calling the daemon_set_monitor() function. The same option is - * not recognized on Windows platform. - */ - -#ifndef _WIN32 -#define DAEMON_OPTION_ENUMS \ - OPT_DETACH, \ - OPT_NO_SELF_CONFINEMENT, \ - OPT_NO_CHDIR, \ - OPT_OVERWRITE_PIDFILE, \ - OPT_PIDFILE, \ - OPT_MONITOR, \ - OPT_USER_GROUP - -#define DAEMON_LONG_OPTIONS \ - {"detach", no_argument, NULL, OPT_DETACH}, \ - {"no-self-confinement", no_argument, NULL, OPT_NO_SELF_CONFINEMENT}, \ - {"no-chdir", no_argument, NULL, OPT_NO_CHDIR}, \ - {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \ - {"overwrite-pidfile", no_argument, NULL, OPT_OVERWRITE_PIDFILE}, \ - {"monitor", no_argument, NULL, OPT_MONITOR}, \ - {"user", required_argument, NULL, OPT_USER_GROUP} - -#define DAEMON_OPTION_HANDLERS \ - case OPT_DETACH: \ - set_detach(); \ - break; \ - \ - case OPT_NO_SELF_CONFINEMENT: \ - daemon_disable_self_confinement(); \ - break; \ - \ - case OPT_NO_CHDIR: \ - set_no_chdir(); \ - break; \ - \ - case OPT_PIDFILE: \ - set_pidfile(optarg); \ - break; \ - \ - case OPT_OVERWRITE_PIDFILE: \ - ignore_existing_pidfile(); \ - break; \ - \ - case OPT_MONITOR: \ - daemon_set_monitor(); \ - break; \ - \ - case OPT_USER_GROUP: \ - daemon_set_new_user(optarg); \ - break; - -#define DAEMON_OPTION_CASES \ - case OPT_DETACH: \ - case OPT_NO_SELF_CONFINEMENT: \ - case OPT_NO_CHDIR: \ - case OPT_PIDFILE: \ - case OPT_OVERWRITE_PIDFILE: \ - case OPT_MONITOR: \ - case OPT_USER_GROUP: - -void set_detach(void); -void daemon_set_monitor(void); -void set_no_chdir(void); -void ignore_existing_pidfile(void); -pid_t read_pidfile(const char *name); -#else -#define DAEMON_OPTION_ENUMS \ - OPT_DETACH, \ - OPT_NO_SELF_CONFINEMENT, \ - OPT_NO_CHDIR, \ - OPT_PIDFILE, \ - OPT_PIPE_HANDLE, \ - OPT_SERVICE, \ - OPT_SERVICE_MONITOR, \ - OPT_USER_GROUP - -#define DAEMON_LONG_OPTIONS \ - {"detach", no_argument, NULL, OPT_DETACH}, \ - {"no-self-confinement", no_argument, NULL, OPT_NO_SELF_CONFINEMENT}, \ - {"no-chdir", no_argument, NULL, OPT_NO_CHDIR}, \ - {"pidfile", optional_argument, NULL, OPT_PIDFILE}, \ - {"pipe-handle", required_argument, NULL, OPT_PIPE_HANDLE}, \ - {"service", no_argument, NULL, OPT_SERVICE}, \ - {"service-monitor", no_argument, NULL, OPT_SERVICE_MONITOR}, \ - {"user", required_argument, NULL, OPT_USER_GROUP} - -#define DAEMON_OPTION_HANDLERS \ - case OPT_DETACH: \ - set_detach(); \ - break; \ - \ - case OPT_NO_SELF_CONFINEMENT: \ - daemon_disable_self_confinement(); \ - break; \ - \ - case OPT_NO_CHDIR: \ - break; \ - \ - case OPT_PIDFILE: \ - set_pidfile(optarg); \ - break; \ - \ - case OPT_PIPE_HANDLE: \ - set_pipe_handle(optarg); \ - break; \ - \ - case OPT_SERVICE: \ - set_detach(); \ - break; \ - \ - case OPT_SERVICE_MONITOR: \ - break; \ - \ - case OPT_USER_GROUP: \ - daemon_set_new_user(optarg); - -#define DAEMON_OPTION_CASES \ - case OPT_DETACH: \ - case OPT_NO_SELF_CONFINEMENT: \ - case OPT_NO_CHDIR: \ - case OPT_PIDFILE: \ - case OPT_PIPE_HANDLE: \ - case OPT_SERVICE: \ - case OPT_SERVICE_MONITOR: \ - case OPT_USER_GROUP: - -void control_handler(DWORD request); -void set_pipe_handle(const char *pipe_handle); -void set_detach(void); -#endif /* _WIN32 */ - -bool get_detach(void); -void daemon_save_fd(int fd); -void daemonize(void); -void daemonize_start(bool access_datapath); -void daemonize_complete(void); -void daemon_set_new_user(const char * user_spec); -void daemon_become_new_user(bool access_datapath); -void daemon_usage(void); -void daemon_disable_self_confinement(void); -bool daemon_should_self_confine(void); -void service_start(int *argcp, char **argvp[]); -void service_stop(void); -bool should_service_stop(void); -void set_pidfile(const char *name); -void close_standard_fds(void); - -#endif /* daemon.h */ Index: openvswitch-2.17.2/lib/db-ctl-base.h =================================================================== --- openvswitch-2.17.2.orig/lib/db-ctl-base.h +++ /dev/null @@ -1,282 +0,0 @@ -/* - * Copyright (c) 2015, 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. - */ - -#ifndef DB_CTL_BASE_H -#define DB_CTL_BASE_H 1 - -#include "openvswitch/compiler.h" -#include "openvswitch/dynamic-string.h" -#include "openvswitch/shash.h" - -struct ctl_context; -struct option; -struct ovsdb_idl; -struct ovsdb_idl_row; -struct ovsdb_idl_txn; -struct ovsdb_symbol_table; -struct table; - -/* This library module contains the common parts for ovsdb manipulation - * (structs, commands and functions). To utilize this module, user must - * define the following: - * - * - the command syntaxes for each command. (See 'struct ctl_command_syntax' - * for more info) and regiters them using ctl_register_commands(). - * - * - the *ctl command context by inheriting the 'struct ctl_context' for - * additional commands implemented by user. (See 'struct ctl_context' for - * more info) -*/ - -/* ctl_fatal() also logs the error, so it is preferred in this file. */ -#define ovs_fatal please_use_ctl_fatal_instead_of_ovs_fatal - -struct ctl_table_class; -struct ovsdb_idl_class; -struct ovsdb_idl_table_class; -struct cmd_show_table; - -/* ctl_init() figures out the number of tables on its own and flags an error if - * 'ctl_classes' was defined with the wrong number of elements. */ -#define ctl_init(idl_class, table_classes, ctl_classes, cmd_show_table, \ - ctl_exit_func) \ - (BUILD_ASSERT(ARRAY_SIZE(table_classes) == ARRAY_SIZE(ctl_classes)), \ - ctl_init__(idl_class, ctl_classes, cmd_show_table, ctl_exit_func)) -void ctl_init__(const struct ovsdb_idl_class *, const struct ctl_table_class *, - const struct cmd_show_table *cmd_show_tables, - void (*ctl_exit_func)(int status)); -char *ctl_default_db(void); -void ctl_error(struct ctl_context *, const char *, ...) -OVS_PRINTF_FORMAT(2, 3); -OVS_NO_RETURN void ctl_fatal(const char *, ...) OVS_PRINTF_FORMAT(1, 2); - -/* *ctl command syntax structure, to be defined by each command implementation. - * - * Execution Path - * ============== - * - * Three stylized functions accompany each of these data structures: - * - * "pre-run" "run" "post-run" - * --------------- ------------ ----------------- - * *ctl ->prerequisites ->run ->postprocess - * - * Any *ctl command implementation should go through the following execution - * path: - * - * 1. parses user command-line input and finds the corresponding syntax - * structures. - * - * 2. calls prerequisites() for getting the columns or tables used by each - * command. - * - * 3. calls run() to execute each command and to generate output. - * - * 4. calls postprocess() after output has been committed. (Only needed - * by 'create' command sofar) - * - * Execution Context - * ================= - * - * Each of the stylized functions requires the 'struct ctl_context' as input - * to provide context e.g. command-line arguments, table to be modified. User - * may define more specific context (by inheriting 'struct ctl_context') and - * write stylized functions that use it. In that case, CONTAINER_OF() can - * be used to cast the generic context to the specific one. - * - * */ -struct ctl_command_syntax { - const char *name; /* e.g. "add-br" */ - int min_args; /* Min number of arguments following name. */ - int max_args; /* Max number of arguments following name. */ - - /* Names that roughly describe the arguments that the command - * uses. These should be similar to the names displayed in the - * man page or in the help output. */ - const char *arguments; - - /* If nonnull, calls ovsdb_idl_add_column() or ovsdb_idl_add_table() for - * each column or table in ctx->idl that it uses. */ - void (*prerequisites)(struct ctl_context *ctx); - - /* Does the actual work of the command and puts the command's output, if - * any, in ctx->output or ctx->table. - * - * Alternatively, if some prerequisite of the command is not met and the - * caller should wait for something to change and then retry, it may set - * ctx->try_again to true. (Only the "wait-until" command currently does - * this.) */ - void (*run)(struct ctl_context *ctx); - - /* If nonnull, called after the transaction has been successfully - * committed. ctx->output is the output from the "run" function, which - * this function may modify and otherwise postprocess as needed. (Only the - * "create" command currently does any postprocessing.) */ - void (*postprocess)(struct ctl_context *ctx); - - /* A comma-separated list of supported options, e.g. "--a,--b", or the - * empty string if the command does not support any options. - * - * Arguments are determined by appending special characters to option - * names: - * - * - Append "=" (e.g. "--id=") for a required argument. - * - * - Append "?" (e.g. "--ovs?") for an optional argument. - * - * - Otherwise an option does not accept an argument. */ - const char *options; - - enum { RO, RW } mode; /* Does this command modify the database? */ -}; - -/* A command extracted from command-line input plus the structs for - * output generation. */ -struct ctl_command { - /* Data that remains constant after initialization. */ - const struct ctl_command_syntax *syntax; - int argc; - char **argv; - struct shash options; - - /* Data modified by commands. */ - struct ds output; - struct table *table; -}; - -bool ctl_might_write_to_db(const struct ctl_command *, size_t n); -const char *ctl_get_db_cmd_usage(void); - -const char *ctl_list_db_tables_usage(void); -void ctl_print_commands(void); -void ctl_print_options(const struct option *); -void ctl_add_cmd_options(struct option **, size_t *n_options_p, - size_t *allocated_options_p, int opt_val); -void ctl_register_commands(const struct ctl_command_syntax *); -char * OVS_WARN_UNUSED_RESULT ctl_parse_commands( - int argc, char *argv[], struct shash *local_options, - struct ctl_command **commandsp, size_t *n_commandsp); - -/* Sometimes, it is desirable to print the table with weak reference to - * rows in a 'cmd_show_table' table. In that case, the 'weak_ref_table' - * should be used and user must define all variables. */ -struct weak_ref_table { - const struct ovsdb_idl_table_class *table; - const struct ovsdb_idl_column *name_column; - /* This colum must be a weak reference to the owning - * 'struct cmd_show_table''s table row. */ - const struct ovsdb_idl_column *wref_column; -}; - -/* This struct is for organizing the 'show' command output where: - * - * - 'table' is the table to show. - * - * - if 'name_column' is not null, it is used as the name for each row - * in 'table'. - * - * - 'columns[]' allows user to specify the print of additional columns - * in 'table'. - * - * - if 'wref_table' is populated, print 'wref_table.name_column' for - * each row in table 'wref_table.table' that has a reference to 'table' - * in 'wref_table.wref_column'. Every field must be populated. - * - * */ -struct cmd_show_table { - const struct ovsdb_idl_table_class *table; - const struct ovsdb_idl_column *name_column; - const struct ovsdb_idl_column *columns[4]; /* Seems like a good number. */ - const struct weak_ref_table wref_table; -}; - - -/* The base context struct for conducting the common database - * operations (commands listed in 'db_ctl_commands'). User should - * define the per-schema context by inheriting this struct as base. - * - * Database Caches - * =============== - * - * User may implement caches for contents of the database to facilitate - * specific commands. In that case, the common commands defined in - * 'db_ctl_commands' that may invalidate the cache must call the - * invalidate_cache(). - * - **/ -struct ctl_context { - /* Read-only. */ - int argc; - char **argv; - struct shash options; - - /* Modifiable state. */ - char *error; - struct ds output; - struct table *table; - struct ovsdb_idl *idl; - struct ovsdb_idl_txn *txn; - struct ovsdb_symbol_table *symtab; - - /* For implementation with a cache of the contents of the database, - * this function will be called when the database is changed and the - * change makes the cache no longer valid. */ - void (*invalidate_cache_cb)(struct ctl_context *); - - /* A command may set this member to true if some prerequisite is not met - * and the caller should wait for something to change and then retry. */ - bool try_again; -}; - -void ctl_context_init_command(struct ctl_context *, struct ctl_command *); -void ctl_context_init(struct ctl_context *, struct ctl_command *, - struct ovsdb_idl *, struct ovsdb_idl_txn *, - struct ovsdb_symbol_table *, - void (*invalidate_cache)(struct ctl_context *)); -void ctl_context_done_command(struct ctl_context *, struct ctl_command *); -void ctl_context_done(struct ctl_context *, struct ctl_command *); - -/* A way to identify a particular row in the database based on a user-provided - * string. If all fields are NULL, the struct is ignored. Otherwise, - * 'name_column' designates a column whose table is searched for rows that - * match with the user string. If 'key' is NULL, then 'name_column' should be - * a string or integer-valued column; otherwise it should be a map from a - * string to one of those types and the value corresponding to 'key' is what is - * matched. If a matching row is found, then: - * - * - If 'uuid_column' is NULL, the matching row is the final row. - * - * - Otherwise 'uuid_column' must designate a UUID-typed column whose value - * refers to exactly one row, which is the final row. - */ -struct ctl_row_id { - const struct ovsdb_idl_column *name_column; - const char *key; - const struct ovsdb_idl_column *uuid_column; -}; - -struct ctl_table_class { - struct ctl_row_id row_ids[4]; -}; - -char *ctl_get_row(struct ctl_context *, const struct ovsdb_idl_table_class *, - const char *record_id, bool must_exist, - const struct ovsdb_idl_row **); - -char *ctl_set_column(const char *table_name, const struct ovsdb_idl_row *, - const char *arg, struct ovsdb_symbol_table *); - -#endif /* db-ctl-base.h */ Index: openvswitch-2.17.2/lib/dhparams.h =================================================================== --- openvswitch-2.17.2.orig/lib/dhparams.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2008, 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. - */ - -#ifndef DHPARAMS_H -#define DHPARAMS_H 1 - -#include -#include - -DH *get_dh2048(void); -DH *get_dh4096(void); - -#endif /* dhparams.h */ Index: openvswitch-2.17.2/lib/dirs.h =================================================================== --- openvswitch-2.17.2.orig/lib/dirs.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef DIRS_H -#define DIRS_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -const char *ovs_sysconfdir(void); /* /usr/local/etc */ -const char *ovs_pkgdatadir(void); /* /usr/local/share/openvswitch */ -const char *ovs_rundir(void); /* /usr/local/var/run/openvswitch */ -const char *ovs_logdir(void); /* /usr/local/var/log/openvswitch */ -const char *ovs_dbdir(void); /* /usr/local/etc/openvswitch */ -const char *ovs_bindir(void); /* /usr/local/bin */ - -#ifdef __cplusplus -} -#endif - -#endif /* dirs.h */ Index: openvswitch-2.17.2/lib/fatal-signal.h =================================================================== --- openvswitch-2.17.2.orig/lib/fatal-signal.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2013 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef FATAL_SIGNAL_H -#define FATAL_SIGNAL_H 1 - -#ifndef _WIN32 -#include -#endif -#include - -/* Basic interface. */ -void fatal_signal_init(void); -void fatal_signal_add_hook(void (*hook_cb)(void *aux), - void (*cancel_cb)(void *aux), void *aux, - bool run_at_exit); -void fatal_signal_fork(void); -void fatal_signal_run(void); -void fatal_signal_wait(void); -void fatal_ignore_sigpipe(void); -void fatal_signal_atexit_handler(void); - -/* Convenience functions for unlinking files upon termination. - * - * These functions also unlink the files upon normal process termination via - * exit(). */ -void fatal_signal_add_file_to_unlink(const char *); -void fatal_signal_remove_file_to_unlink(const char *); -int fatal_signal_unlink_file_now(const char *); - -/* Interface for other code that catches one of our signals and needs to pass - * it through. */ -void fatal_signal_handler(int sig_nr); - -#ifndef _WIN32 -void fatal_signal_block(sigset_t *prev_mask); -#endif - -#endif /* fatal-signal.h */ Index: openvswitch-2.17.2/lib/hash-aarch64.h =================================================================== --- openvswitch-2.17.2.orig/lib/hash-aarch64.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2019 Arm Limited - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This header implements HASH operation primitives on aarch64. */ -#ifndef HASH_AARCH64_H -#define HASH_AARCH64_H 1 - -#ifndef HASH_H -#error "This header should only be included indirectly via hash.h." -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#include - -static inline uint32_t hash_add(uint32_t hash, uint32_t data) -{ - return __crc32cw(hash, data); -} - -/* Add the halves of 'data' in the memory order. */ -static inline uint32_t hash_add64(uint32_t hash, uint64_t data) -{ - return __crc32cd(hash, data); -} - -static inline uint32_t hash_finish(uint32_t hash, uint64_t final) -{ - /* The finishing multiplier 0x805204f3 has been experimentally - * derived to pass the testsuite hash tests. */ - hash = __crc32cd(hash, final) * 0x805204f3; - return hash ^ hash >> 16; /* Increase entropy in LSBs. */ -} - -/* Returns the hash of the 'n' 32-bit words at 'p_', starting from 'basis'. - * We access 'p_' as a uint64_t pointer. - * - * This is inlined for the compiler to have access to the 'n_words', which - * in many cases is a constant. */ -static inline uint32_t -hash_words_inline(const uint32_t p_[], size_t n_words, uint32_t basis) -{ - const uint64_t *p = (const void *)p_; - uint32_t hash1 = basis; - uint32_t hash2 = 0; - uint32_t hash3 = n_words; - const uint32_t *endp = (const uint32_t *)p + n_words; - const uint64_t *limit = p + n_words / 2 - 3; - - while (p <= limit) { - hash1 = __crc32cd(hash1, p[0]); - hash2 = __crc32cd(hash2, p[1]); - hash3 = __crc32cd(hash3, p[2]); - p += 3; - } - switch (endp - (const uint32_t *)p) { - case 1: - hash1 = __crc32cw(hash1, *(const uint32_t *)&p[0]); - break; - case 2: - hash1 = __crc32cd(hash1, p[0]); - break; - case 3: - hash1 = __crc32cd(hash1, p[0]); - hash2 = __crc32cw(hash2, *(const uint32_t *)&p[1]); - break; - case 4: - hash1 = __crc32cd(hash1, p[0]); - hash2 = __crc32cd(hash2, p[1]); - break; - case 5: - hash1 = __crc32cd(hash1, p[0]); - hash2 = __crc32cd(hash2, p[1]); - hash3 = __crc32cw(hash3, *(const uint32_t *)&p[2]); - break; - } - return hash_finish(hash1, (uint64_t)hash2 << 32 | hash3); -} - -/* A simpler version for 64-bit data. - * 'n_words' is the count of 64-bit words, basis is 64 bits. */ -static inline uint32_t -hash_words64_inline(const uint64_t p[], size_t n_words, uint32_t basis) -{ - uint32_t hash1 = basis; - uint32_t hash2 = 0; - uint32_t hash3 = n_words; - const uint64_t *endp = p + n_words; - const uint64_t *limit = endp - 3; - - while (p <= limit) { - hash1 = __crc32cd(hash1, p[0]); - hash2 = __crc32cd(hash2, p[1]); - hash3 = __crc32cd(hash3, p[2]); - p += 3; - } - switch (endp - p) { - case 1: - hash1 = __crc32cd(hash1, p[0]); - break; - case 2: - hash1 = __crc32cd(hash1, p[0]); - hash2 = __crc32cd(hash2, p[1]); - break; - } - return hash_finish(hash1, (uint64_t)hash2 << 32 | hash3); -} - -static inline uint32_t hash_uint64_basis(const uint64_t x, - const uint32_t basis) -{ - /* '23' chosen to mix bits enough for the test-hash to pass. */ - return hash_finish(hash_add64(basis, x), 23); -} - -static inline uint32_t hash_uint64(const uint64_t x) -{ - return hash_uint64_basis(x, 0); -} - -static inline uint32_t hash_2words(uint32_t x, uint32_t y) -{ - return hash_uint64((uint64_t)y << 32 | x); -} - -static inline uint32_t hash_pointer(const void *p, uint32_t basis) -{ - return hash_uint64_basis((uint64_t) (uintptr_t) p, basis); -} - -#ifdef __cplusplus -} -#endif - -#endif /* hash-aarch64.h */ Index: openvswitch-2.17.2/lib/hmapx.h =================================================================== --- openvswitch-2.17.2.orig/lib/hmapx.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2011, 2016 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 HMAPX_H -#define HMAPX_H - -#include "openvswitch/hmap.h" - -struct hmapx_node { - struct hmap_node hmap_node; - void *data; -}; - -/* A set of "void *" pointers. */ -struct hmapx { - struct hmap map; -}; - -#define HMAPX_INITIALIZER(HMAPX) { HMAP_INITIALIZER(&(HMAPX)->map) } - -/* Basics. */ -void hmapx_init(struct hmapx *); -void hmapx_destroy(struct hmapx *); -void hmapx_clone(struct hmapx *, const struct hmapx *); -void hmapx_swap(struct hmapx *, struct hmapx *); -void hmapx_moved(struct hmapx *); - -/* Count. */ -bool hmapx_is_empty(const struct hmapx *); -size_t hmapx_count(const struct hmapx *); - -/* Insertion. */ -struct hmapx_node *hmapx_add(struct hmapx *, void *); -void hmapx_add_assert(struct hmapx *, void *); - -/* Deletion. */ -void hmapx_clear(struct hmapx *); -void hmapx_delete(struct hmapx *, struct hmapx_node *); -bool hmapx_find_and_delete(struct hmapx *, const void *); -void hmapx_find_and_delete_assert(struct hmapx *, const void *); - -/* Search. */ -struct hmapx_node *hmapx_find(const struct hmapx *, const void *); -bool hmapx_contains(const struct hmapx *, const void *); -bool hmapx_equals(const struct hmapx *, const struct hmapx *); - -/* Iteration. */ - -/* Iterates through every hmapx_node in HMAPX. */ -#define HMAPX_FOR_EACH(NODE, HMAPX) \ - HMAP_FOR_EACH_INIT(NODE, hmap_node, &(HMAPX)->map, \ - BUILD_ASSERT_TYPE(NODE, struct hmapx_node *), \ - BUILD_ASSERT_TYPE(HMAPX, struct hmapx *)) - -/* Safe when NODE may be freed (not needed when NODE may be removed from the - * hash map but its members remain accessible and intact). */ -#define HMAPX_FOR_EACH_SAFE_SHORT(NODE, HMAPX) \ - HMAP_FOR_EACH_SAFE_SHORT_INIT (NODE, hmap_node, &(HMAPX)->map, \ - BUILD_ASSERT_TYPE(NODE, struct hmapx_node *), \ - BUILD_ASSERT_TYPE(HMAPX, struct hmapx *)) - -#define HMAPX_FOR_EACH_SAFE_LONG(NODE, NEXT, HMAPX) \ - HMAP_FOR_EACH_SAFE_LONG_INIT (NODE, NEXT, hmap_node, &(HMAPX)->map, \ - BUILD_ASSERT_TYPE(NODE, struct hmapx_node *), \ - BUILD_ASSERT_TYPE(NEXT, struct hmapx_node *), \ - BUILD_ASSERT_TYPE(HMAPX, struct hmapx *)) - -#define HMAPX_FOR_EACH_SAFE(...) \ - OVERLOAD_SAFE_MACRO(HMAPX_FOR_EACH_SAFE_LONG, \ - HMAPX_FOR_EACH_SAFE_SHORT, \ - 3, __VA_ARGS__) - -#endif /* hmapx.h */ Index: openvswitch-2.17.2/lib/id-pool.h =================================================================== --- openvswitch-2.17.2.orig/lib/id-pool.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2014 Nicira, Inc. - * Copyright (c) 2014 Netronome. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ID_POOL_H -#define ID_POOL_H - -#include -#include -#include - -struct id_pool; - -struct id_pool *id_pool_create(uint32_t base, uint32_t n_ids); -void id_pool_destroy(struct id_pool *); -bool id_pool_alloc_id(struct id_pool *, uint32_t *id); -void id_pool_free_id(struct id_pool *, uint32_t id); -void id_pool_add(struct id_pool *, uint32_t id); - -/* - * ID pool. - * ======== - * - * Pool of unique 32bit ids. - * Allocation always returns the lowest available id. - * - * Thread-safety - * ============= - * - * APIs are not thread safe. - */ -#endif /* id-pool.h */ Index: openvswitch-2.17.2/lib/jsonrpc.h =================================================================== --- openvswitch-2.17.2.orig/lib/jsonrpc.h +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) 2009, 2010, 2012, 2013, 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. - */ - -#ifndef JSONRPC_H -#define JSONRPC_H 1 - -/* This is an implementation of the JSON-RPC 1.0 specification defined at - * http://json-rpc.org/wiki/specification. */ - -#include -#include -#include "openvswitch/types.h" - -struct json; -struct jsonrpc_msg; -struct pstream; -struct reconnect_stats; -struct stream; -struct svec; - -/* API for a JSON-RPC stream. */ - -/* Default port numbers. - * - * OVSDB_OLD_PORT defines the original port number used by OVS. - * OVSDB_PORT defines the official port number assigned by IANA. */ -#define OVSDB_OLD_PORT 6632 -#define OVSDB_PORT 6640 - -int jsonrpc_stream_open(const char *name, struct stream **, uint8_t dscp); -int jsonrpc_pstream_open(const char *name, struct pstream **, uint8_t dscp); - -struct jsonrpc *jsonrpc_open(struct stream *); -void jsonrpc_close(struct jsonrpc *); - -void jsonrpc_run(struct jsonrpc *); -void jsonrpc_wait(struct jsonrpc *); - -int jsonrpc_get_status(const struct jsonrpc *); -size_t jsonrpc_get_backlog(const struct jsonrpc *); -void jsonrpc_set_backlog_threshold(struct jsonrpc *, size_t max_n_msgs, - size_t max_backlog_bytes); - -unsigned int jsonrpc_get_received_bytes(const struct jsonrpc *); -const char *jsonrpc_get_name(const struct jsonrpc *); - -int jsonrpc_send(struct jsonrpc *, struct jsonrpc_msg *); -int jsonrpc_recv(struct jsonrpc *, struct jsonrpc_msg **); -void jsonrpc_recv_wait(struct jsonrpc *); - -int jsonrpc_send_block(struct jsonrpc *, struct jsonrpc_msg *); -int jsonrpc_recv_block(struct jsonrpc *, struct jsonrpc_msg **); -int jsonrpc_transact_block(struct jsonrpc *, struct jsonrpc_msg *, - struct jsonrpc_msg **); - -/* Messages. */ -enum jsonrpc_msg_type { - JSONRPC_REQUEST, /* Request. */ - JSONRPC_NOTIFY, /* Notification. */ - JSONRPC_REPLY, /* Successful reply. */ - JSONRPC_ERROR /* Error reply. */ -}; - -struct jsonrpc_msg { - enum jsonrpc_msg_type type; - char *method; /* Request or notification only. */ - struct json *params; /* Request or notification only. */ - struct json *result; /* Successful reply only. */ - struct json *error; /* Error reply only. */ - struct json *id; /* Request or reply only. */ -}; - -struct jsonrpc_msg *jsonrpc_create_request(const char *method, - struct json *params, - struct json **idp); -struct jsonrpc_msg *jsonrpc_create_notify(const char *method, - struct json *params); -struct jsonrpc_msg *jsonrpc_create_reply(struct json *result, - const struct json *id); -struct jsonrpc_msg *jsonrpc_create_error(struct json *error, - const struct json *id); - -struct jsonrpc_msg *jsonrpc_msg_clone(const struct jsonrpc_msg *); - -const char *jsonrpc_msg_type_to_string(enum jsonrpc_msg_type); -char *jsonrpc_msg_is_valid(const struct jsonrpc_msg *); -void jsonrpc_msg_destroy(struct jsonrpc_msg *); - -char *jsonrpc_msg_from_json(struct json *, struct jsonrpc_msg **); -struct json *jsonrpc_msg_to_json(struct jsonrpc_msg *); - -char *jsonrpc_msg_to_string(const struct jsonrpc_msg *); - -/* A JSON-RPC session with reconnection. */ - -struct jsonrpc_session *jsonrpc_session_open(const char *name, bool retry); -struct jsonrpc_session *jsonrpc_session_open_multiple(const struct svec *, - bool retry); -struct jsonrpc_session *jsonrpc_session_open_unreliably(struct jsonrpc *, - uint8_t); -void jsonrpc_session_close(struct jsonrpc_session *); - -struct jsonrpc *jsonrpc_session_steal(struct jsonrpc_session *); -void jsonrpc_session_replace(struct jsonrpc_session *, struct jsonrpc *); - -void jsonrpc_session_run(struct jsonrpc_session *); -void jsonrpc_session_wait(struct jsonrpc_session *); - -size_t jsonrpc_session_get_backlog(const struct jsonrpc_session *); -const char *jsonrpc_session_get_name(const struct jsonrpc_session *); -size_t jsonrpc_session_get_n_remotes(const struct jsonrpc_session *); - -int jsonrpc_session_send(struct jsonrpc_session *, struct jsonrpc_msg *); -struct jsonrpc_msg *jsonrpc_session_recv(struct jsonrpc_session *); -void jsonrpc_session_recv_wait(struct jsonrpc_session *); - -bool jsonrpc_session_is_alive(const struct jsonrpc_session *); -bool jsonrpc_session_is_connected(const struct jsonrpc_session *); -unsigned int jsonrpc_session_get_seqno(const struct jsonrpc_session *); -int jsonrpc_session_get_status(const struct jsonrpc_session *); -int jsonrpc_session_get_last_error(const struct jsonrpc_session *); -void jsonrpc_session_get_reconnect_stats(const struct jsonrpc_session *, - struct reconnect_stats *); - -void jsonrpc_session_enable_reconnect(struct jsonrpc_session *); -void jsonrpc_session_force_reconnect(struct jsonrpc_session *); -void jsonrpc_session_reset_backoff(struct jsonrpc_session *); - -void jsonrpc_session_set_max_backoff(struct jsonrpc_session *, - int max_backoff); -void jsonrpc_session_set_probe_interval(struct jsonrpc_session *, - int probe_interval); -void jsonrpc_session_set_dscp(struct jsonrpc_session *, - uint8_t dscp); -void jsonrpc_session_set_backlog_threshold(struct jsonrpc_session *, - size_t max_n_msgs, - size_t max_backlog_bytes); -const char *jsonrpc_session_get_id(const struct jsonrpc_session *); - -#endif /* jsonrpc.h */ Index: openvswitch-2.17.2/lib/memory.h =================================================================== --- openvswitch-2.17.2.orig/lib/memory.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2012 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef MEMORY_H -#define MEMORY_H 1 - -/* Memory usage monitor. - * - * This is intended to be called as part of a daemon's main loop. After some - * time to allow the daemon to allocate an initial memory usage, it logs some - * memory usage information (most of which must actually be provided by the - * client). At intervals, if the daemon's memory usage has grown - * significantly, it again logs information. - * - * The monitor also has a unixctl interface. - * - * Intended usage in the program's main loop is like this: - * - * for (;;) { - * memory_run(); - * if (memory_should_report()) { - * struct simap usage; - * - * simap_init(&usage); - * ...fill in 'usage' with meaningful statistics... - * memory_report(&usage); - * simap_destroy(&usage); - * } - * - * ... - * - * memory_wait(); - * poll_block(); - * } - */ - -#include - -struct simap; - -void memory_run(void); -void memory_wait(void); - -bool memory_should_report(void); -void memory_report(const struct simap *usage); - -#endif /* memory.h */ Index: openvswitch-2.17.2/lib/netdev-afxdp.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-afxdp.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2018, 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. - */ - -#ifndef NETDEV_AFXDP_H -#define NETDEV_AFXDP_H 1 - -#ifdef HAVE_AF_XDP - -#include -#include - -/* These functions are Linux AF_XDP specific, so they should be used directly - * only by Linux-specific code. */ - -enum afxdp_mode { - OVS_AF_XDP_MODE_UNSPEC, - OVS_AF_XDP_MODE_BEST_EFFORT, - OVS_AF_XDP_MODE_NATIVE_ZC, - OVS_AF_XDP_MODE_NATIVE, - OVS_AF_XDP_MODE_GENERIC, - OVS_AF_XDP_MODE_MAX, -}; - -struct dp_packet; -struct dp_packet_batch; -struct netdev; -struct netdev_afxdp_tx_lock; -struct netdev_custom_stats; -struct netdev_rxq; -struct netdev_stats; -struct smap; -struct xdp_umem; -struct xsk_socket_info; - -int netdev_afxdp_rxq_construct(struct netdev_rxq *rxq_); -void netdev_afxdp_rxq_destruct(struct netdev_rxq *rxq_); -int netdev_afxdp_init(void); -int netdev_afxdp_construct(struct netdev *netdev_); -void netdev_afxdp_destruct(struct netdev *netdev_); -int netdev_afxdp_verify_mtu_size(const struct netdev *netdev, int mtu); - -int netdev_afxdp_rxq_recv(struct netdev_rxq *rxq_, - struct dp_packet_batch *batch, - int *qfill); -int netdev_afxdp_batch_send(struct netdev *netdev_, int qid, - struct dp_packet_batch *batch, - bool concurrent_txq); -int netdev_afxdp_set_config(struct netdev *netdev, const struct smap *args, - char **errp); -int netdev_afxdp_get_config(const struct netdev *netdev, struct smap *args); -int netdev_afxdp_get_stats(const struct netdev *netdev_, - struct netdev_stats *stats); -int netdev_afxdp_get_custom_stats(const struct netdev *netdev, - struct netdev_custom_stats *custom_stats); - - -void free_afxdp_buf(struct dp_packet *p); -int netdev_afxdp_reconfigure(struct netdev *netdev); -void signal_remove_xdp(struct netdev *netdev); - -#else /* !HAVE_AF_XDP */ - -#include "openvswitch/compiler.h" - -struct dp_packet; - -static inline void -free_afxdp_buf(struct dp_packet *p OVS_UNUSED) -{ - /* Nothing. */ -} - -#endif /* HAVE_AF_XDP */ -#endif /* netdev-afxdp.h */ Index: openvswitch-2.17.2/lib/netdev-dpdk.h =================================================================== --- openvswitch-2.17.2.orig/lib/netdev-dpdk.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 2014, 2015, 2016 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 NETDEV_DPDK_H -#define NETDEV_DPDK_H - -#include - -#include "openvswitch/compiler.h" - -struct dp_packet; -struct netdev; - -#ifdef DPDK_NETDEV - -#include - -void netdev_dpdk_register(void); -void free_dpdk_buf(struct dp_packet *); - -bool netdev_dpdk_flow_api_supported(struct netdev *); - -int -netdev_dpdk_rte_flow_destroy(struct netdev *netdev, - struct rte_flow *rte_flow, - struct rte_flow_error *error); -struct rte_flow * -netdev_dpdk_rte_flow_create(struct netdev *netdev, - const struct rte_flow_attr *attr, - const struct rte_flow_item *items, - const struct rte_flow_action *actions, - struct rte_flow_error *error); -int -netdev_dpdk_rte_flow_query_count(struct netdev *netdev, - struct rte_flow *rte_flow, - struct rte_flow_query_count *query, - struct rte_flow_error *error); -int -netdev_dpdk_get_port_id(struct netdev *netdev); - -#ifdef ALLOW_EXPERIMENTAL_API - -int netdev_dpdk_rte_flow_tunnel_decap_set(struct netdev *, - struct rte_flow_tunnel *, - struct rte_flow_action **, - uint32_t *num_of_actions, - struct rte_flow_error *); -int netdev_dpdk_rte_flow_tunnel_match(struct netdev *, - struct rte_flow_tunnel *, - struct rte_flow_item **, - uint32_t *num_of_items, - struct rte_flow_error *); -int netdev_dpdk_rte_flow_get_restore_info(struct netdev *, - struct dp_packet *, - struct rte_flow_restore_info *, - struct rte_flow_error *); -int netdev_dpdk_rte_flow_tunnel_action_decap_release(struct netdev *, - struct rte_flow_action *, - uint32_t num_of_actions, - struct rte_flow_error *); -int netdev_dpdk_rte_flow_tunnel_item_release(struct netdev *, - struct rte_flow_item *, - uint32_t num_of_items, - struct rte_flow_error *); - -#else - -static inline void -set_error(struct rte_flow_error *error, enum rte_flow_error_type type) -{ - if (!error) { - return; - } - error->type = type; - error->cause = NULL; - error->message = NULL; -} - -static inline int -netdev_dpdk_rte_flow_tunnel_decap_set( - struct netdev *netdev OVS_UNUSED, - struct rte_flow_tunnel *tunnel OVS_UNUSED, - struct rte_flow_action **actions OVS_UNUSED, - uint32_t *num_of_actions OVS_UNUSED, - struct rte_flow_error *error) -{ - set_error(error, RTE_FLOW_ERROR_TYPE_ACTION); - return -1; -} - -static inline int -netdev_dpdk_rte_flow_tunnel_match(struct netdev *netdev OVS_UNUSED, - struct rte_flow_tunnel *tunnel OVS_UNUSED, - struct rte_flow_item **items OVS_UNUSED, - uint32_t *num_of_items OVS_UNUSED, - struct rte_flow_error *error) -{ - set_error(error, RTE_FLOW_ERROR_TYPE_ITEM); - return -1; -} - -static inline int -netdev_dpdk_rte_flow_get_restore_info( - struct netdev *netdev OVS_UNUSED, - struct dp_packet *p OVS_UNUSED, - struct rte_flow_restore_info *info OVS_UNUSED, - struct rte_flow_error *error) -{ - set_error(error, RTE_FLOW_ERROR_TYPE_ATTR); - return -1; -} - -static inline int -netdev_dpdk_rte_flow_tunnel_action_decap_release( - struct netdev *netdev OVS_UNUSED, - struct rte_flow_action *actions OVS_UNUSED, - uint32_t num_of_actions OVS_UNUSED, - struct rte_flow_error *error) -{ - set_error(error, RTE_FLOW_ERROR_TYPE_NONE); - return 0; -} - -static inline int -netdev_dpdk_rte_flow_tunnel_item_release( - struct netdev *netdev OVS_UNUSED, - struct rte_flow_item *items OVS_UNUSED, - uint32_t num_of_items OVS_UNUSED, - struct rte_flow_error *error) -{ - set_error(error, RTE_FLOW_ERROR_TYPE_NONE); - return 0; -} - -#endif /* ALLOW_EXPERIMENTAL_API */ - -#else - -static inline void -netdev_dpdk_register(void) -{ - /* Nothing */ -} -static inline void -free_dpdk_buf(struct dp_packet *buf OVS_UNUSED) -{ - /* Nothing */ -} - -#endif - -#endif /* netdev-dpdk.h */ Index: openvswitch-2.17.2/lib/ovs-atomic-c++.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-c++.h +++ /dev/null @@ -1,67 +0,0 @@ -/* This header implements atomic operation primitives on compilers that - * have built-in support for ++C11 */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#include - -#define ATOMIC(TYPE) std::atomic - -using std::atomic_init; - -using std::memory_order_relaxed; -using std::memory_order_consume; -using std::memory_order_acquire; -using std::memory_order_release; -using std::memory_order_acq_rel; -using std::memory_order_seq_cst; - -using std::atomic_thread_fence; -using std::atomic_signal_fence; -using std::atomic_is_lock_free; - -using std::atomic_store; -using std::atomic_store_explicit; - -using std::atomic_compare_exchange_strong; -using std::atomic_compare_exchange_strong_explicit; -using std::atomic_compare_exchange_weak; -using std::atomic_compare_exchange_weak_explicit; - -using std::atomic_exchange; -using std::atomic_exchange_explicit; - -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) -#define atomic_read_explicit(SRC, DST, ORDER) \ - (*(DST) = std::atomic_load_explicit(SRC, ORDER), \ - (void) 0) - -#define atomic_add(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_sub(RMW, ARG, ORIG) \ - atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_or(RMW, ARG, ORIG) \ - atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_xor(RMW, ARG, ORIG) \ - atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_and(RMW, ARG, ORIG) \ - atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = (*(RMW)).fetch_add(ARG, ORDER), (void) 0) -#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = (*(RMW)).fetch_sub(ARG, ORDER), (void) 0) -#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = (*(RMW)).fetch_or(ARG, ORDER), (void) 0) -#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = (*(RMW)).fetch_xor(ARG, ORDER), (void) 0) -#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = (*(RMW)).fetch_and(ARG, ORDER), (void) 0) - -using std::atomic_flag; -using std::atomic_flag_test_and_set_explicit; -using std::atomic_flag_test_and_set; -using std::atomic_flag_clear_explicit; -using std::atomic_flag_clear; Index: openvswitch-2.17.2/lib/ovs-atomic-c11.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-c11.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This header implements atomic operation primitives on compilers that - * have built-in support for C11 */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#include - -#define OMIT_STANDARD_ATOMIC_TYPES 1 -#define ATOMIC(TYPE) _Atomic(TYPE) - -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) -#define atomic_read_explicit(SRC, DST, ORDER) \ - (*(DST) = atomic_load_explicit(SRC, ORDER), \ - (void) 0) - -#define atomic_add(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_sub(RMW, ARG, ORIG) \ - atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_or(RMW, ARG, ORIG) \ - atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_xor(RMW, ARG, ORIG) \ - atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) -#define atomic_and(RMW, ARG, ORIG) \ - atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = atomic_fetch_add_explicit(RMW, ARG, ORDER), (void) 0) -#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = atomic_fetch_sub_explicit(RMW, ARG, ORDER), (void) 0) -#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = atomic_fetch_or_explicit(RMW, ARG, ORDER), (void) 0) -#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = atomic_fetch_xor_explicit(RMW, ARG, ORDER), (void) 0) -#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ - (*(ORIG) = atomic_fetch_and_explicit(RMW, ARG, ORDER), (void) 0) Index: openvswitch-2.17.2/lib/ovs-atomic-flag-gcc4.7+.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-flag-gcc4.7+.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2013, 2014 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* This header implements atomic_flag on Clang and on GCC 4.7 and later. */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -/* atomic_flag */ - -typedef struct { - unsigned char b; -} atomic_flag; -#define ATOMIC_FLAG_INIT { .b = false } - -static inline bool -atomic_flag_test_and_set_explicit(volatile atomic_flag *object, - memory_order order) -{ - return __atomic_test_and_set(&object->b, order); -} - -static inline bool -atomic_flag_test_and_set(volatile atomic_flag *object) -{ - return atomic_flag_test_and_set_explicit(object, memory_order_seq_cst); -} - -static inline void -atomic_flag_clear_explicit(volatile atomic_flag *object, memory_order order) -{ - __atomic_clear(object, order); -} - -static inline void -atomic_flag_clear(volatile atomic_flag *object) -{ - atomic_flag_clear_explicit(object, memory_order_seq_cst); -} Index: openvswitch-2.17.2/lib/ovs-atomic-i586.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-i586.h +++ /dev/null @@ -1,489 +0,0 @@ -/* - * 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. - */ - -/* This header implements atomic operation primitives on 32-bit 586+ with GCC. - */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#define OVS_ATOMIC_I586_IMPL 1 - -/* - * These assumptions have been adopted from the x86_64 Memory model: - * - * - 1, 2, and 4 byte loads and stores are atomic on aligned memory. - * - Loads are not reordered with other loads. - * - Stores are not reordered with OLDER loads. - * - Loads may be reordered with OLDER stores to a different memory location, - * but not with OLDER stores to the same memory location. - * - Stores are not reordered with other stores, except maybe for special - * instructions not emitted by compilers, or by the stores performed by - * a single fast string operation (e.g., "stos"). As long as the atomic - * stores are not combined with any other stores, even the allowed reordering - * of the stores by a single fast string operation is not a problem. - * - Neither loads nor stores are reordered with locked instructions. - * - Stores by a single processor are observed in the same order by all - * processors. - * - (Unlocked) Stores from different processors are NOT ordered. - * - Memory ordering obeys causality (memory ordering respects transitive - * visibility). - * - Any two stores are seen in a consistent order by processors other than - * the those performing the stores. - * - Locked instructions have total order. - * - * These rules imply that: - * - * - Locked instructions are not needed for aligned loads or stores to make - * them atomic for sizes upto 4 bytes. 8 byte objects need locked - * instructions. - * - All stores have release semantics; none of the preceding stores or loads - * can be reordered with following stores. Following loads could still be - * reordered to happen before the store, but that is not a violation of the - * release semantics. - * - All loads from a given memory location have acquire semantics with - * respect to the stores on the same memory location; none of the following - * loads or stores can be reordered with the load. Preceding stores to a - * different memory location MAY be reordered with the load, but that is not - * a violation of the acquire semantics (i.e., the loads and stores of two - * critical sections guarded by a different memory location can overlap). - * - Locked instructions serve as CPU memory barriers by themselves. - * - Locked stores implement the sequential consistency memory order. Using - * locked instructions when seq_cst memory order is requested allows normal - * loads to observe the stores in the same (total) order without using CPU - * memory barrier after the loads. - * - * NOTE: Some older AMD Opteron processors have a bug that violates the - * acquire semantics described above. The bug manifests as an unlocked - * read-modify-write operation following a "semaphore operation" operating - * on data that existed before entering the critical section; i.e., the - * preceding "semaphore operation" fails to function as an acquire barrier. - * The affected CPUs are AMD family 15, models 32 to 63. - * - * Ref. http://support.amd.com/TechDocs/25759.pdf errata #147. - */ - -/* Barriers. */ - -#define compiler_barrier() asm volatile(" " : : : "memory") -#define cpu_barrier() asm volatile("lock; addl $0,(%%esp)" ::: "memory", "cc") - -/* - * The 'volatile' keyword prevents the compiler from keeping the atomic - * value in a register, and generates a new memory access for each atomic - * operation. This allows the implementations of memory_order_relaxed and - * memory_order_consume to avoid issuing a compiler memory barrier, allowing - * full optimization of all surrounding non-atomic variables. - * - * The placement of the 'volatile' keyword after the 'TYPE' below is highly - * significant when the TYPE is a pointer type. In that case we want the - * pointer to be declared volatile, not the data type that is being pointed - * at! - * - * Attribute aligned is used to tell the compiler to align 64-bit data - * on a 8-byte boundary. This allows more efficient atomic access, as the - * the CPU guarantees such memory accesses to be atomic. */ -#define ATOMIC(TYPE) TYPE volatile __attribute__((aligned(sizeof(TYPE)))) - -/* Memory ordering. Must be passed in as a constant. */ -typedef enum { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -} memory_order; - -#define ATOMIC_BOOL_LOCK_FREE 2 -#define ATOMIC_CHAR_LOCK_FREE 2 -#define ATOMIC_SHORT_LOCK_FREE 2 -#define ATOMIC_INT_LOCK_FREE 2 -#define ATOMIC_LONG_LOCK_FREE 2 -#define ATOMIC_LLONG_LOCK_FREE 2 -#define ATOMIC_POINTER_LOCK_FREE 2 - -#define IS_LOCKLESS_ATOMIC(OBJECT) \ - (sizeof(OBJECT) <= 8 && IS_POW2(sizeof(OBJECT))) - -#define ATOMIC_VAR_INIT(VALUE) VALUE -#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) - -/* - * The memory_model_relaxed does not need a compiler barrier, if the - * atomic operation can otherwise be guaranteed to not be moved with - * respect to other atomic operations on the same memory location. Using - * the 'volatile' keyword in the definition of the atomic types - * accomplishes this, as memory accesses to volatile data may not be - * optimized away, or be reordered with other volatile accesses. - * - * On x86 also memory_order_consume is automatic, and data dependency on a - * volatile atomic variable means that the compiler optimizations should not - * cause problems. That is, the compiler should not speculate the value of - * the atomic_read, as it is going to read it from the memory anyway. - * This allows omiting the compiler memory barrier on atomic_reads with - * memory_order_consume. This matches the definition of - * smp_read_barrier_depends() in Linux kernel as a nop for x86, and its usage - * in rcu_dereference(). - * - * We use this same logic below to choose inline assembly statements with or - * without a compiler memory barrier. - */ -static inline void -atomic_compiler_barrier(memory_order order) -{ - if (order > memory_order_consume) { - compiler_barrier(); - } -} - -static inline void -atomic_thread_fence(memory_order order) -{ - if (order == memory_order_seq_cst) { - cpu_barrier(); - } else { - atomic_compiler_barrier(order); - } -} - -static inline void -atomic_signal_fence(memory_order order) -{ - atomic_compiler_barrier(order); -} - -#define atomic_is_lock_free(OBJ) \ - ((void) *(OBJ), \ - IS_LOCKLESS_ATOMIC(*(OBJ)) ? 2 : 0) - -/* The 8-byte atomic exchange uses cmpxchg8b with the SRC (ax:dx) as - * the expected value (bx:cx), which will get replaced by the current - * value in the likely case it did not match, after which we keep - * trying until the swap succeeds. */ - -#if defined(__PIC__) -/* ebx may not be clobbered when compiled with -fPIC, must save and - * restore it. Furthermore, 'DST' may be addressed via ebx, so the - * address must be passed via a register so that it remains valid also - * after changing ebx. */ -#define atomic_exchange_8__(DST, SRC, CLOB) \ - uint32_t temp____; \ - \ - asm volatile(" movl %%ebx,%2 ; " \ - " movl %%eax,%%ebx ; " \ - " movl %%edx,%%ecx ; " \ - "1: " \ - "lock; cmpxchg8b (%0); " \ - " jne 1b ; " \ - " movl %2,%%ebx ; " \ - " # atomic_exchange_8__ " \ - : "+r" (DST), /* 0 */ \ - "+A" (SRC), /* 1 */ \ - "=mr" (temp____) /* 2 */ \ - :: "ecx", CLOB, "cc") - -#else -#define atomic_exchange_8__(DST, SRC, CLOB) \ - asm volatile(" movl %%eax,%%ebx ; " \ - " movl %%edx,%%ecx ; " \ - "1: " \ - "lock; cmpxchg8b %0 ; " \ - " jne 1b ; " \ - " # atomic_exchange_8__ " \ - : "+m" (*DST), /* 0 */ \ - "+A" (SRC) /* 1 */ \ - :: "ebx", "ecx", CLOB, "cc") -#endif - -#define atomic_exchange__(DST, SRC, ORDER) \ - ({ \ - typeof(DST) dst___ = (DST); \ - typeof(*(DST)) src___ = (SRC); \ - \ - if ((ORDER) > memory_order_consume) { \ - if (sizeof(*(DST)) == 8) { \ - atomic_exchange_8__(dst___, src___, "memory"); \ - } else { \ - asm volatile("xchg %1,%0 ; " \ - "# atomic_exchange__" \ - : "+r" (src___), /* 0 */ \ - "+m" (*dst___) /* 1 */ \ - :: "memory"); \ - } \ - } else { \ - if (sizeof(*(DST)) == 8) { \ - atomic_exchange_8__(dst___, src___, "cc"); \ - } else { \ - asm volatile("xchg %1,%0 ; " \ - "# atomic_exchange__" \ - : "+r" (src___), /* 0 */ \ - "+m" (*dst___)); /* 1 */ \ - } \ - } \ - src___; \ - }) - -#if defined(__SSE__) -/* SSE registers are 128-bit wide, and moving the lowest 64-bits of an SSE - * register to proerly aligned memory is atomic. See ATOMIC(TYPE) above. */ -#define atomic_store_8__(DST, SRC) \ - asm volatile("movq %1,%0 ; # atomic_store_8__" \ - : "=m" (*DST) /* 0 */ \ - : "x" (SRC)) /* 1, SSE */ -#else -/* Locked 64-bit exchange is available on all i586 CPUs. */ -#define atomic_store_8__(DST, SRC) \ - atomic_exchange_8__(DST, SRC, "cc") -#endif - -#define atomic_store_explicit(DST, SRC, ORDER) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(*(DST)) src__ = (SRC); \ - \ - if ((ORDER) != memory_order_seq_cst) { \ - atomic_compiler_barrier(ORDER); \ - if (sizeof(*(DST)) == 8) { \ - atomic_store_8__(dst__, src__); \ - } else { \ - *dst__ = src__; \ - } \ - } else { \ - atomic_exchange__(dst__, src__, ORDER); \ - } \ - (void) 0; \ - }) -#define atomic_store(DST, SRC) \ - atomic_store_explicit(DST, SRC, memory_order_seq_cst) - -#if defined(__SSE__) -/* SSE registers are 128-bit wide, and moving 64-bits from properly aligned - * memory to an SSE register is atomic. See ATOMIC(TYPE) above. */ -#define atomic_read_8__(SRC, DST) \ - ({ \ - typeof(*(DST)) res__; \ - \ - asm ("movq %1,%0 ; # atomic_read_8__" \ - : "=x" (res__) /* 0, SSE. */ \ - : "m" (*SRC)); /* 1 */ \ - *(DST) = res__; \ - }) -#else -/* Must use locked cmpxchg8b (available on all i586 CPUs) if compiled w/o sse - * support. Compare '*DST' to a random value in bx:cx and returns the actual - * value in ax:dx. The registers bx and cx are only read, so they are not - * clobbered. */ -#define atomic_read_8__(SRC, DST) \ - ({ \ - typeof(*(DST)) res__; \ - \ - asm (" movl %%ebx,%%eax ; " \ - " movl %%ecx,%%edx ; " \ - "lock; cmpxchg8b %1 ; " \ - "# atomic_read_8__ " \ - : "=&A" (res__), /* 0 */ \ - "+m" (*SRC) /* 1 */ \ - : : "cc"); \ - *(DST) = res__; \ - }) -#endif - -#define atomic_read_explicit(SRC, DST, ORDER) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(SRC) src__ = (SRC); \ - \ - if (sizeof(*(DST)) <= 4) { \ - *dst__ = *src__; \ - } else { \ - atomic_read_8__(SRC, DST); \ - } \ - atomic_compiler_barrier(ORDER); \ - (void) 0; \ - }) -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) - -#if defined(__PIC__) -/* ebx may not be used as an input when compiled with -fPIC, must save - * and restore it. Furthermore, 'DST' may be addressed via ebx, so - * the address must be passed via a register so that it remains valid - * also after changing ebx. */ -#define atomic_compare_exchange_8__(DST, EXP, SRC, RES, CLOB) \ - asm volatile(" xchgl %%ebx,%3 ; " \ - "lock; cmpxchg8b (%1) ; " \ - " xchgl %3,%%ebx ; " \ - " sete %0 " \ - "# atomic_compare_exchange_8__" \ - : "=q" (RES), /* 0 */ \ - "+r" (DST), /* 1 */ \ - "+A" (EXP) /* 2 */ \ - : "r" ((uint32_t)SRC), /* 3 */ \ - "c" ((uint32_t)((uint64_t)SRC >> 32)) /* 4 */ \ - : CLOB, "cc") -#else -#define atomic_compare_exchange_8__(DST, EXP, SRC, RES, CLOB) \ - asm volatile("lock; cmpxchg8b %1 ; " \ - " sete %0 " \ - "# atomic_compare_exchange_8__" \ - : "=q" (RES), /* 0 */ \ - "+m" (*DST), /* 1 */ \ - "+A" (EXP) /* 2 */ \ - : "b" ((uint32_t)SRC), /* 3 */ \ - "c" ((uint32_t)((uint64_t)SRC >> 32)) /* 4 */ \ - : CLOB, "cc") -#endif - -#define atomic_compare_exchange__(DST, EXP, SRC, RES, CLOB) \ - asm volatile("lock; cmpxchg %3,%1 ; " \ - " sete %0 " \ - "# atomic_compare_exchange__" \ - : "=q" (RES), /* 0 */ \ - "+m" (*DST), /* 1 */ \ - "+a" (EXP) /* 2 */ \ - : "r" (SRC) /* 3 */ \ - : CLOB, "cc") - -/* ORD_FAIL is ignored, as atomic_compare_exchange__ already implements - * at least as strong a barrier as allowed for ORD_FAIL in all cases. */ -#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORDER, ORD_FAIL) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(DST) expp__ = (EXP); \ - typeof(*(DST)) src__ = (SRC); \ - typeof(*(DST)) exp__ = *expp__; \ - uint8_t res__; \ - (void)ORD_FAIL; \ - \ - if ((ORDER) > memory_order_consume) { \ - if (sizeof(*(DST)) <= 4) { \ - atomic_compare_exchange__(dst__, exp__, src__, res__, \ - "memory"); \ - } else { \ - atomic_compare_exchange_8__(dst__, exp__, src__, res__, \ - "memory"); \ - } \ - } else { \ - if (sizeof(*(DST)) <= 4) { \ - atomic_compare_exchange__(dst__, exp__, src__, res__, \ - "cc"); \ - } else { \ - atomic_compare_exchange_8__(dst__, exp__, src__, res__, \ - "cc"); \ - } \ - } \ - if (!res__) { \ - *expp__ = exp__; \ - } \ - (bool)res__; \ - }) -#define atomic_compare_exchange_strong(DST, EXP, SRC) \ - atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -#define atomic_compare_exchange_weak \ - atomic_compare_exchange_strong -#define atomic_compare_exchange_weak_explicit \ - atomic_compare_exchange_strong_explicit - -#define atomic_exchange_explicit(RMW, ARG, ORDER) \ - atomic_exchange__(RMW, ARG, ORDER) -#define atomic_exchange(RMW, ARG) \ - atomic_exchange_explicit(RMW, ARG, memory_order_seq_cst) - -#define atomic_add__(RMW, ARG, CLOB) \ - asm volatile("lock; xadd %0,%1 ; " \ - "# atomic_add__ " \ - : "+r" (ARG), /* 0 */ \ - "+m" (*RMW) /* 1 */ \ - :: CLOB, "cc") - -#define atomic_add_32__(RMW, ARG, ORIG, ORDER) \ - ({ \ - typeof(RMW) rmw__ = (RMW); \ - typeof(*(RMW)) arg__ = (ARG); \ - \ - if ((ORDER) > memory_order_consume) { \ - atomic_add__(rmw__, arg__, "memory"); \ - } else { \ - atomic_add__(rmw__, arg__, "cc"); \ - } \ - *(ORIG) = arg__; \ - }) - -/* We could use simple locked instructions if the original value was not - * needed. */ -#define atomic_op__(RMW, OP, ARG, ORIG, ORDER) \ - ({ \ - typeof(RMW) rmw__ = (RMW); \ - typeof(ARG) arg__ = (ARG); \ - \ - typeof(*(RMW)) val__; \ - \ - atomic_read_explicit(rmw__, &val__, memory_order_relaxed); \ - do { \ - } while (!atomic_compare_exchange_weak_explicit(rmw__, &val__, \ - val__ OP arg__, \ - ORDER, \ - memory_order_relaxed)); \ - *(ORIG) = val__; \ - }) - -#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ - (sizeof(*(RMW)) <= 4 \ - ? atomic_add_32__(RMW, ARG, ORIG, ORDER) \ - : atomic_op__(RMW, +, ARG, ORIG, ORDER)) -#define atomic_add(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ - (sizeof(*(RMW)) <= 4 \ - ? atomic_add_32__(RMW, -(ARG), ORIG, ORDER) \ - : atomic_op__(RMW, -, ARG, ORIG, ORDER)) -#define atomic_sub(RMW, ARG, ORIG) \ - atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_op__(RMW, |, ARG, ORIG, ORDER) -#define atomic_or(RMW, ARG, ORIG) \ - atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_op__(RMW, ^, ARG, ORIG, ORDER) -#define atomic_xor(RMW, ARG, ORIG) \ - atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_op__(RMW, &, ARG, ORIG, ORDER) -#define atomic_and(RMW, ARG, ORIG) \ - atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - - -/* atomic_flag */ - -typedef ATOMIC(int) atomic_flag; -#define ATOMIC_FLAG_INIT { false } - -#define atomic_flag_test_and_set_explicit(FLAG, ORDER) \ - ((bool)atomic_exchange__(FLAG, 1, ORDER)) -#define atomic_flag_test_and_set(FLAG) \ - atomic_flag_test_and_set_explicit(FLAG, memory_order_seq_cst) - -#define atomic_flag_clear_explicit(FLAG, ORDER) \ - atomic_store_explicit(FLAG, 0, ORDER) -#define atomic_flag_clear(FLAG) \ - atomic_flag_clear_explicit(FLAG, memory_order_seq_cst) Index: openvswitch-2.17.2/lib/ovs-atomic-locked.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-locked.h +++ /dev/null @@ -1,52 +0,0 @@ -/* This header implements atomic operation locking helpers. */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#define OVS_ATOMIC_LOCKED_IMPL 1 - -void atomic_lock__(void *); -void atomic_unlock__(void *); - -#define atomic_store_locked(DST, SRC) \ - (atomic_lock__(DST), \ - *(DST) = (SRC), \ - atomic_unlock__(DST), \ - (void) 0) - -#define atomic_read_locked(SRC, DST) \ - (atomic_lock__(SRC), \ - *(DST) = *(SRC), \ - atomic_unlock__(SRC), \ - (void) 0) - -/* XXX: Evaluates EXP multiple times. */ -#define atomic_compare_exchange_locked(DST, EXP, SRC) \ - (atomic_lock__(DST), \ - (*(DST) == *(EXP) \ - ? (*(DST) = (SRC), \ - atomic_unlock__(DST), \ - true) \ - : (*(EXP) = *(DST), \ - atomic_unlock__(DST), \ - false))) - -#define atomic_exchange_locked(DST, SRC) \ - ({ \ - atomic_lock__(DST); \ - typeof(*(DST)) __tmp = *(DST); \ - *(DST) = SRC; \ - atomic_unlock__(DST); \ - __tmp; \ - }) - -#define atomic_op_locked_add += -#define atomic_op_locked_sub -= -#define atomic_op_locked_or |= -#define atomic_op_locked_xor ^= -#define atomic_op_locked_and &= -#define atomic_op_locked(RMW, OP, OPERAND, ORIG) \ - (atomic_lock__(RMW), \ - *(ORIG) = *(RMW), \ - *(RMW) atomic_op_locked_##OP (OPERAND), \ - atomic_unlock__(RMW)) Index: openvswitch-2.17.2/lib/ovs-atomic-msvc.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-msvc.h +++ /dev/null @@ -1,463 +0,0 @@ -/* - * 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. - */ - -/* This header implements atomic operation primitives for MSVC - * on i586 or greater platforms (32 bit). */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -/* From msdn documentation: With Visual Studio 2003, volatile to volatile - * references are ordered; the compiler will not re-order volatile variable - * access. With Visual Studio 2005, the compiler also uses acquire semantics - * for read operations on volatile variables and release semantics for write - * operations on volatile variables (when supported by the CPU). - * - * Though there is no clear documentation that states that anything greater - * than VS 2005 has the same behavior as described above, looking through MSVCs - * C++ atomics library in VS2013 shows that the compiler still takes - * acquire/release semantics on volatile variables. */ -#define ATOMIC(TYPE) TYPE volatile - -typedef enum { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -} memory_order; - -#if _MSC_VER > 1800 && defined(_M_IX86) -/* From WDK 10 _InlineInterlocked* functions are renamed to - * _InlineInterlocked* although the documentation does not specify it */ -#define _InterlockedExchangeAdd64 _InlineInterlockedExchangeAdd64 -#define _InterlockedExchange64 _InlineInterlockedExchange64 -#endif - -#define ATOMIC_BOOL_LOCK_FREE 2 -#define ATOMIC_CHAR_LOCK_FREE 2 -#define ATOMIC_SHORT_LOCK_FREE 2 -#define ATOMIC_INT_LOCK_FREE 2 -#define ATOMIC_LONG_LOCK_FREE 2 -#define ATOMIC_LLONG_LOCK_FREE 2 -#define ATOMIC_POINTER_LOCK_FREE 2 - -#define IS_LOCKLESS_ATOMIC(OBJECT) \ - (sizeof(OBJECT) <= 8 && IS_POW2(sizeof(OBJECT))) - -#define ATOMIC_VAR_INIT(VALUE) (VALUE) -#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) - -static inline void -atomic_compiler_barrier(memory_order order) -{ - /* In case of 'memory_order_consume', it is implicitly assumed that - * the compiler will not move instructions that have data-dependency - * on the variable in question before the barrier. */ - if (order > memory_order_consume) { - _ReadWriteBarrier(); - } -} - -static inline void -atomic_thread_fence(memory_order order) -{ - /* x86 is strongly ordered and acquire/release semantics come - * automatically. */ - atomic_compiler_barrier(order); - if (order == memory_order_seq_cst) { - MemoryBarrier(); - atomic_compiler_barrier(order); - } -} - -static inline void -atomic_signal_fence(memory_order order) -{ - atomic_compiler_barrier(order); -} - -/* 1, 2 and 4 bytes loads and stores are atomic on aligned memory. In addition, - * since the compiler automatically takes acquire and release semantics on - * volatile variables, for any order lesser than 'memory_order_seq_cst', we - * can directly assign or read values. */ - -#define atomic_store32(DST, SRC, ORDER) \ - if (ORDER == memory_order_seq_cst) { \ - InterlockedExchange((long volatile *) (DST), \ - (long) (SRC)); \ - } else { \ - *(DST) = (SRC); \ - } - -/* MSVC converts 64 bit writes into two instructions. So there is - * a possibility that an interrupt can make a 64 bit write non-atomic even - * when 8 byte aligned. So use InterlockedExchange64(). - * - * For atomic stores, 'consume' and 'acquire' semantics are not valid. But we - * are using 'Exchange' to get atomic stores here and we only have - * InterlockedExchange64(), InterlockedExchangeNoFence64() and - * InterlockedExchange64Acquire() available. So we are forced to use - * InterlockedExchange64() which uses full memory barrier for everything - * greater than 'memory_order_relaxed'. */ -#ifdef _M_IX86 -#define atomic_store64(DST, SRC, ORDER) \ - if (ORDER == memory_order_relaxed) { \ - InterlockedExchangeNoFence64((int64_t volatile *) (DST), \ - (int64_t) (SRC)); \ - } else { \ - InterlockedExchange64((int64_t volatile *) (DST), (int64_t) (SRC));\ - } -#elif _M_X64 -/* 64 bit writes are atomic on amd64 if 64 bit aligned. */ -#define atomic_store64(DST, SRC, ORDER) \ - if (ORDER == memory_order_seq_cst) { \ - InterlockedExchange64((int64_t volatile *) (DST), \ - (int64_t) (SRC)); \ - } else { \ - *(DST) = (SRC); \ - } -#endif - -#define atomic_store8(DST, SRC, ORDER) \ - if (ORDER == memory_order_seq_cst) { \ - InterlockedExchange8((char volatile *) (DST), (char) (SRC)); \ - } else { \ - *(DST) = (SRC); \ - } - -#define atomic_store16(DST, SRC, ORDER) \ - if (ORDER == memory_order_seq_cst) { \ - InterlockedExchange16((short volatile *) (DST), (short) (SRC)); \ - } else { \ - *(DST) = (SRC); \ - } - -#define atomic_store(DST, SRC) \ - atomic_store_explicit(DST, SRC, memory_order_seq_cst) - -#define atomic_store_explicit(DST, SRC, ORDER) \ - if (sizeof *(DST) == 1) { \ - atomic_store8(DST, SRC, ORDER) \ - } else if (sizeof *(DST) == 2) { \ - atomic_store16( DST, SRC, ORDER) \ - } else if (sizeof *(DST) == 4) { \ - atomic_store32(DST, SRC, ORDER) \ - } else if (sizeof *(DST) == 8) { \ - atomic_store64(DST, SRC, ORDER) \ - } else { \ - abort(); \ - } - -/* On x86, for 'memory_order_seq_cst', if stores are locked, the corresponding - * reads don't need to be locked (based on the following in Intel Developers - * manual: - * “Locked operations are atomic with respect to all other memory operations - * and all externally visible events. Only instruction fetch and page table - * accesses can pass locked instructions. Locked instructions can be used to - * synchronize data written by one processor and read by another processor. - * For the P6 family processors, locked operations serialize all outstanding - * load and store operations (that is, wait for them to complete). This rule - * is also true for the Pentium 4 and Intel Xeon processors, with one - * exception. Load operations that reference weakly ordered memory types - * (such as the WC memory type) may not be serialized."). */ - - /* For 8, 16 and 32 bit variations. */ -#define atomic_readX(SRC, DST, ORDER) \ - *(DST) = *(SRC); - -/* MSVC converts 64 bit reads into two instructions. So there is - * a possibility that an interrupt can make a 64 bit read non-atomic even - * when 8 byte aligned. So use fully memory barrier InterlockedOr64(). */ -#ifdef _M_IX86 -#define atomic_read64(SRC, DST, ORDER) \ - __pragma (warning(push)) \ - __pragma (warning(disable:4047)) \ - *(DST) = InterlockedOr64((int64_t volatile *) (SRC), 0); \ - __pragma (warning(pop)) -#elif _M_X64 -/* 64 bit reads are atomic on amd64 if 64 bit aligned. */ -#define atomic_read64(SRC, DST, ORDER) \ - *(DST) = *(SRC); -#endif - -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) - -#define atomic_read_explicit(SRC, DST, ORDER) \ - if (sizeof *(DST) == 1 || sizeof *(DST) == 2 || sizeof *(DST) == 4) { \ - atomic_readX(SRC, DST, ORDER) \ - } else if (sizeof *(DST) == 8) { \ - atomic_read64(SRC, DST, ORDER) \ - } else { \ - abort(); \ - } - -/* For add, sub, and logical operations, for 8, 16 and 64 bit data types, - * functions for all the different memory orders does not exist - * (though documentation exists for some of them). The MSVC C++ library which - * implements the c11 atomics simply calls the full memory barrier function - * for everything in x86(see xatomic.h). So do the same here. */ - -/* For 8, 16 and 64 bit variations. */ -#define atomic_op(OP, X, RMW, ARG, ORIG, ORDER) \ - atomic_##OP##_generic(X, RMW, ARG, ORIG, ORDER) - -/* Arithmetic addition calls. */ - -#define atomic_add8(RMW, ARG, ORIG, ORDER) \ - *(ORIG) = _InterlockedExchangeAdd8((char volatile *) (RMW), \ - (char) (ARG)); - -#define atomic_add16(RMW, ARG, ORIG, ORDER) \ - *(ORIG) = _InterlockedExchangeAdd16((short volatile *) (RMW), \ - (short) (ARG)); - -#define atomic_add32(RMW, ARG, ORIG, ORDER) \ - *(ORIG) = InterlockedExchangeAdd((long volatile *) (RMW), \ - (long) (ARG)); -#define atomic_add64(RMW, ARG, ORIG, ORDER) \ - *(ORIG) = _InterlockedExchangeAdd64((int64_t volatile *) (RMW), \ - (int64_t) (ARG)); - -#define atomic_add(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ - if (sizeof *(RMW) == 1) { \ - atomic_add8(RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 2) { \ - atomic_add16(RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 4) { \ - atomic_add32(RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 8) { \ - atomic_add64(RMW, ARG, ORIG, ORDER) \ - } else { \ - abort(); \ - } - -/* Arithmetic subtraction calls. */ - -#define atomic_sub(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, (0 - (ARG)), ORIG, memory_order_seq_cst) - -#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_add_explicit(RMW, (0 - (ARG)), ORIG, ORDER) - -/* Logical 'and' calls. */ - -#define atomic_and32(RMW, ARG, ORIG, ORDER) \ - *(ORIG) = InterlockedAnd((int32_t volatile *) (RMW), (int32_t) (ARG)); - -/* For 8, 16 and 64 bit variations. */ -#define atomic_and_generic(X, RMW, ARG, ORIG, ORDER) \ - *(ORIG) = InterlockedAnd##X((int##X##_t volatile *) (RMW), \ - (int##X##_t) (ARG)); - -#define atomic_and(RMW, ARG, ORIG) \ - atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ - if (sizeof *(RMW) == 1) { \ - atomic_op(and, 8, RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 2) { \ - atomic_op(and, 16, RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 4) { \ - atomic_and32(RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 8) { \ - atomic_op(and, 64, RMW, ARG, ORIG, ORDER) \ - } else { \ - abort(); \ - } - -/* Logical 'Or' calls. */ - -#define atomic_or32(RMW, ARG, ORIG, ORDER) \ - *(ORIG) = InterlockedOr((int32_t volatile *) (RMW), (int32_t) (ARG)); - -/* For 8, 16 and 64 bit variations. */ -#define atomic_or_generic(X, RMW, ARG, ORIG, ORDER) \ - *(ORIG) = InterlockedOr##X((int##X##_t volatile *) (RMW), \ - (int##X##_t) (ARG)); - -#define atomic_or(RMW, ARG, ORIG) \ - atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ - if (sizeof *(RMW) == 1) { \ - atomic_op(or, 8, RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 2) { \ - atomic_op(or, 16, RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 4) { \ - atomic_or32(RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 8) { \ - atomic_op(or, 64, RMW, ARG, ORIG, ORDER) \ - } else { \ - abort(); \ - } - -/* Logical Xor calls. */ - -#define atomic_xor32(RMW, ARG, ORIG, ORDER) \ - *(ORIG) = InterlockedXor((int32_t volatile *) (RMW), (int32_t) (ARG)); - -/* For 8, 16 and 64 bit variations. */ -#define atomic_xor_generic(X, RMW, ARG, ORIG, ORDER) \ - *(ORIG) = InterlockedXor##X((int##X##_t volatile *) (RMW), \ - (int##X##_t) (ARG)); - -#define atomic_xor(RMW, ARG, ORIG) \ - atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ - if (sizeof *(RMW) == 1) { \ - atomic_op(xor, 8, RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 2) { \ - atomic_op(xor, 16, RMW, ARG, ORIG, ORDER) \ - } else if (sizeof *(RMW) == 4) { \ - atomic_xor32(RMW, ARG, ORIG, ORDER); \ - } else if (sizeof *(RMW) == 8) { \ - atomic_op(xor, 64, RMW, ARG, ORIG, ORDER) \ - } else { \ - abort(); \ - } - -#define atomic_compare_exchange_strong(DST, EXP, SRC) \ - atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ - memory_order_seq_cst, \ - memory_order_seq_cst) - -#define atomic_compare_exchange_weak atomic_compare_exchange_strong -#define atomic_compare_exchange_weak_explicit \ - atomic_compare_exchange_strong_explicit - -/* While intrinsics offering different memory ordering - * are available in MSVC C compiler, they are not defined - * in the C++ compiler. Ignore for compatibility. - * - * Use nested ternary operators as the GNU extension ({}) - * is not available. - */ - -#define atomic_exchange_explicit(DST, SRC, ORDER) \ - ((sizeof *(DST) == 1) ? \ - _InterlockedExchange8((char volatile *) DST, SRC) \ - : (sizeof *(DST) == 2) ? \ - _InterlockedExchange16((short volatile *) DST, SRC) \ - : (sizeof *(DST) == 4) ? \ - _InterlockedExchange((long int volatile *) DST, SRC) \ - : (sizeof *(DST) == 8) ? \ - _InterlockedExchange64((__int64 volatile *) DST, SRC) \ - : (abort(), 0)) - -#define atomic_exchange(DST, SRC) \ - atomic_exchange_explicit(DST, SRC, memory_order_seq_cst) - -/* MSVCs c++ compiler implements c11 atomics and looking through its - * implementation (in xatomic.h), orders are ignored for x86 platform. - * Do the same here. */ -static inline bool -atomic_compare_exchange8(int8_t volatile *dst, int8_t *expected, int8_t src) -{ - int8_t previous = _InterlockedCompareExchange8((char volatile *)dst, - src, *expected); - if (previous == *expected) { - return true; - } else { - *expected = previous; - return false; - } -} - -static inline bool -atomic_compare_exchange16(int16_t volatile *dst, int16_t *expected, - int16_t src) -{ - int16_t previous = InterlockedCompareExchange16(dst, src, *expected); - if (previous == *expected) { - return true; - } else { - *expected = previous; - return false; - } -} - -static inline bool -atomic_compare_exchange32(int32_t volatile *dst, int32_t *expected, - int32_t src) -{ - int32_t previous = InterlockedCompareExchange((long volatile *)dst, - src, *expected); - if (previous == *expected) { - return true; - } else { - *expected = previous; - return false; - } -} - -static inline bool -atomic_compare_exchange64(int64_t volatile *dst, int64_t *expected, - int64_t src) -{ - int64_t previous = InterlockedCompareExchange64(dst, src, *expected); - if (previous == *expected) { - return true; - } else { - *expected = previous; - return false; - } -} - -static inline bool -atomic_compare_unreachable() -{ - return true; -} - -#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORD1, ORD2) \ - (sizeof *(DST) == 1 \ - ? atomic_compare_exchange8((int8_t volatile *) (DST), (int8_t *) (EXP), \ - (int8_t) (SRC)) \ - : (sizeof *(DST) == 2 \ - ? atomic_compare_exchange16((int16_t volatile *) (DST), \ - (int16_t *) (EXP), (int16_t) (SRC)) \ - : (sizeof *(DST) == 4 \ - ? atomic_compare_exchange32((int32_t volatile *) (DST), \ - (int32_t *) (EXP), (int32_t) (SRC)) \ - : (sizeof *(DST) == 8 \ - ? atomic_compare_exchange64((int64_t volatile *) (DST), \ - (int64_t *) (EXP), (int64_t) (SRC)) \ - : ovs_fatal(0, "atomic operation with size greater than 8 bytes"), \ - atomic_compare_unreachable())))) - - -/* atomic_flag */ - -typedef ATOMIC(int32_t) atomic_flag; -#define ATOMIC_FLAG_INIT 0 - -#define atomic_flag_test_and_set(FLAG) \ - (bool) InterlockedBitTestAndSet(FLAG, 0) - -#define atomic_flag_test_and_set_explicit(FLAG, ORDER) \ - atomic_flag_test_and_set(FLAG) - -#define atomic_flag_clear_explicit(FLAG, ORDER) \ - atomic_flag_clear() -#define atomic_flag_clear(FLAG) \ - InterlockedBitTestAndReset(FLAG, 0) Index: openvswitch-2.17.2/lib/ovs-atomic-x86_64.h =================================================================== --- openvswitch-2.17.2.orig/lib/ovs-atomic-x86_64.h +++ /dev/null @@ -1,356 +0,0 @@ -/* - * 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. - */ - -/* This header implements atomic operation primitives on x86_64 with GCC. */ -#ifndef IN_OVS_ATOMIC_H -#error "This header should only be included indirectly via ovs-atomic.h." -#endif - -#define OVS_ATOMIC_X86_64_IMPL 1 - -/* - * x86_64 Memory model (http://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-3a-part-1-manual.html): - * - * - 1, 2, 4, and 8 byte loads and stores are atomic on aligned memory. - * - Loads are not reordered with other loads. - * - Stores are not reordered with OLDER loads. - * - Loads may be reordered with OLDER stores to a different memory location, - * but not with OLDER stores to the same memory location. - * - Stores are not reordered with other stores, except for special - * instructions (CLFLUSH, streaming stores, fast string operations). - * Most of these are not emitted by compilers, and as long as the - * atomic stores are not combined with any other stores, even the allowed - * reordering of the stores by a single fast string operation (e.g., "stos") - * is not a problem. - * - Neither loads nor stores are reordered with locked instructions. - * - Loads cannot pass earlier LFENCE or MFENCE instructions. - * - Stores cannot pass earlier LFENCE, SFENCE, or MFENCE instructions. - * - LFENCE instruction cannot pass earlier loads. - * - SFENCE instruction cannot pass earlier stores. - * - MFENCE instruction cannot pass earlier loads or stores. - * - Stores by a single processor are observed in the same order by all - * processors. - * - (Unlocked) Stores from different processors are NOT ordered. - * - Memory ordering obeys causality (memory ordering respects transitive - * visibility). - * - Any two stores are seen in a consistent order by processors other than - * the those performing the stores. - * - Locked instructions have total order. - * - * These rules imply that: - * - * - Locked instructions are not needed for aligned loads or stores to make - * them atomic. - * - All stores have release semantics; none of the preceding stores or loads - * can be reordered with following stores. Following loads could still be - * reordered to happen before the store, but that is not a violation of the - * release semantics. - * - All loads from a given memory location have acquire semantics with - * respect to the stores on the same memory location; none of the following - * loads or stores can be reordered with the load. Preceding stores to a - * different memory location MAY be reordered with the load, but that is not - * a violation of the acquire semantics (i.e., the loads and stores of two - * critical sections guarded by a different memory location can overlap). - * - Locked instructions serve as CPU memory barriers by themselves. - * - Locked stores implement the sequential consistency memory order. Using - * locked instructions when seq_cst memory order is requested allows normal - * loads to observe the stores in the same (total) order without using CPU - * memory barrier after the loads. - * - * NOTE: Some older AMD Opteron processors have a bug that violates the - * acquire semantics described above. The bug manifests as an unlocked - * read-modify-write operation following a "semaphore operation" operating - * on data that existed before entering the critical section; i.e., the - * preceding "semaphore operation" fails to function as an acquire barrier. - * The affected CPUs are AMD family 15, models 32 to 63. - * - * Ref. http://support.amd.com/TechDocs/25759.pdf errata #147. - */ - -/* Barriers. */ - -#define compiler_barrier() asm volatile(" " : : : "memory") -#define cpu_barrier() asm volatile("mfence;" : : : "memory") - -/* - * The 'volatile' keyword prevents the compiler from keeping the atomic - * value in a register, and generates a new memory access for each atomic - * operation. This allows the implementations of memory_order_relaxed and - * memory_order_consume to avoid issuing a compiler memory barrier, allowing - * full optimization of all surrounding non-atomic variables. - * - * The placement of the 'volatile' keyword after the 'TYPE' below is highly - * significant when the TYPE is a pointer type. In that case we want the - * pointer to be declared volatile, not the data type that is being pointed - * at! - */ -#define ATOMIC(TYPE) TYPE volatile - -/* Memory ordering. Must be passed in as a constant. */ -typedef enum { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst -} memory_order; - -#define ATOMIC_BOOL_LOCK_FREE 2 -#define ATOMIC_CHAR_LOCK_FREE 2 -#define ATOMIC_SHORT_LOCK_FREE 2 -#define ATOMIC_INT_LOCK_FREE 2 -#define ATOMIC_LONG_LOCK_FREE 2 -#define ATOMIC_LLONG_LOCK_FREE 2 -#define ATOMIC_POINTER_LOCK_FREE 2 - -#define IS_LOCKLESS_ATOMIC(OBJECT) \ - (sizeof(OBJECT) <= 8 && IS_POW2(sizeof(OBJECT))) - -#define ATOMIC_VAR_INIT(VALUE) VALUE -#define atomic_init(OBJECT, VALUE) (*(OBJECT) = (VALUE), (void) 0) - -/* - * The memory_model_relaxed does not need a compiler barrier, if the - * atomic operation can otherwise be guaranteed to not be moved with - * respect to other atomic operations on the same memory location. Using - * the 'volatile' keyword in the definition of the atomic types - * accomplishes this, as memory accesses to volatile data may not be - * optimized away, or be reordered with other volatile accesses. - * - * On x86 also memory_order_consume is automatic, and data dependency on a - * volatile atomic variable means that the compiler optimizations should not - * cause problems. That is, the compiler should not speculate the value of - * the atomic_read, as it is going to read it from the memory anyway. - * This allows omiting the compiler memory barrier on atomic_reads with - * memory_order_consume. This matches the definition of - * smp_read_barrier_depends() in Linux kernel as a nop for x86, and its usage - * in rcu_dereference(). - * - * We use this same logic below to choose inline assembly statements with or - * without a compiler memory barrier. - */ -static inline void -atomic_compiler_barrier(memory_order order) -{ - if (order > memory_order_consume) { - compiler_barrier(); - } -} - -static inline void -atomic_thread_fence(memory_order order) -{ - if (order == memory_order_seq_cst) { - cpu_barrier(); - } else { - atomic_compiler_barrier(order); - } -} - -static inline void -atomic_signal_fence(memory_order order) -{ - atomic_compiler_barrier(order); -} - -#define atomic_is_lock_free(OBJ) \ - ((void) *(OBJ), \ - IS_LOCKLESS_ATOMIC(*(OBJ)) ? 2 : 0) - -#define atomic_exchange__(DST, SRC, ORDER) \ - ({ \ - typeof(DST) dst___ = (DST); \ - typeof(*(DST)) src___ = (SRC); \ - \ - if ((ORDER) > memory_order_consume) { \ - asm volatile("xchg %1,%0 ; " \ - "# atomic_exchange__" \ - : "+r" (src___), /* 0 */ \ - "+m" (*dst___) /* 1 */ \ - :: "memory"); \ - } else { \ - asm volatile("xchg %1,%0 ; " \ - "# atomic_exchange__" \ - : "+r" (src___), /* 0 */ \ - "+m" (*dst___)); /* 1 */ \ - } \ - src___; \ - }) - -/* Atomic store: Valid memory models are: - * - * memory_order_relaxed, memory_order_release, and - * memory_order_seq_cst. */ -#define atomic_store_explicit(DST, SRC, ORDER) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(*(DST)) src__ = (SRC); \ - \ - if ((ORDER) != memory_order_seq_cst) { \ - atomic_compiler_barrier(ORDER); \ - *dst__ = src__; \ - } else { \ - atomic_exchange__(dst__, src__, ORDER); \ - } \ - (void) 0; \ - }) -#define atomic_store(DST, SRC) \ - atomic_store_explicit(DST, SRC, memory_order_seq_cst) - -/* Atomic read: Valid memory models are: - * - * memory_order_relaxed, memory_order_consume, memory_model_acquire, - * and memory_order_seq_cst. */ -#define atomic_read_explicit(SRC, DST, ORDER) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(SRC) src__ = (SRC); \ - \ - *dst__ = *src__; \ - atomic_compiler_barrier(ORDER); \ - (void) 0; \ - }) -#define atomic_read(SRC, DST) \ - atomic_read_explicit(SRC, DST, memory_order_seq_cst) - -#define atomic_compare_exchange__(DST, EXP, SRC, RES, CLOB) \ - asm volatile("lock; cmpxchg %3,%1 ; " \ - " sete %0 " \ - "# atomic_compare_exchange__" \ - : "=q" (RES), /* 0 */ \ - "+m" (*DST), /* 1 */ \ - "+a" (EXP) /* 2 */ \ - : "r" (SRC) /* 3 */ \ - : CLOB, "cc") - -/* All memory models are valid for read-modify-write operations. - * - * Valid memory models for the read operation of the current value in - * the failure case are the same as for atomic read, but can not be - * stronger than the success memory model. - * ORD_FAIL is ignored, as atomic_compare_exchange__ already implements - * at least as strong a barrier as allowed for ORD_FAIL in all cases. */ -#define atomic_compare_exchange_strong_explicit(DST, EXP, SRC, ORDER, ORD_FAIL) \ - ({ \ - typeof(DST) dst__ = (DST); \ - typeof(DST) expp__ = (EXP); \ - typeof(*(DST)) src__ = (SRC); \ - typeof(*(DST)) exp__ = *expp__; \ - uint8_t res__; \ - (void)ORD_FAIL; \ - \ - if ((ORDER) > memory_order_consume) { \ - atomic_compare_exchange__(dst__, exp__, src__, res__, \ - "memory"); \ - } else { \ - atomic_compare_exchange__(dst__, exp__, src__, res__, \ - "cc"); \ - } \ - if (!res__) { \ - *expp__ = exp__; \ - } \ - (bool)res__; \ - }) -#define atomic_compare_exchange_strong(DST, EXP, SRC) \ - atomic_compare_exchange_strong_explicit(DST, EXP, SRC, \ - memory_order_seq_cst, \ - memory_order_seq_cst) -#define atomic_compare_exchange_weak \ - atomic_compare_exchange_strong -#define atomic_compare_exchange_weak_explicit \ - atomic_compare_exchange_strong_explicit - -#define atomic_exchange_explicit(RMW, ARG, ORDER) \ - atomic_exchange__(RMW, ARG, ORDER) -#define atomic_exchange(RMW, ARG) \ - atomic_exchange_explicit(RMW, ARG, memory_order_seq_cst) - -#define atomic_add__(RMW, ARG, CLOB) \ - asm volatile("lock; xadd %0,%1 ; " \ - "# atomic_add__ " \ - : "+r" (ARG), /* 0 */ \ - "+m" (*RMW) /* 1 */ \ - :: CLOB, "cc") - -#define atomic_add_explicit(RMW, ARG, ORIG, ORDER) \ - ({ \ - typeof(RMW) rmw__ = (RMW); \ - typeof(*(RMW)) arg__ = (ARG); \ - \ - if ((ORDER) > memory_order_consume) { \ - atomic_add__(rmw__, arg__, "memory"); \ - } else { \ - atomic_add__(rmw__, arg__, "cc"); \ - } \ - *(ORIG) = arg__; \ - }) -#define atomic_add(RMW, ARG, ORIG) \ - atomic_add_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_sub_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_add_explicit(RMW, -(ARG), ORIG, ORDER) -#define atomic_sub(RMW, ARG, ORIG) \ - atomic_sub_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -/* We could use simple locked instructions if the original value was not - * needed. */ -#define atomic_op__(RMW, OP, ARG, ORIG, ORDER) \ - ({ \ - typeof(RMW) rmw__ = (RMW); \ - typeof(ARG) arg__ = (ARG); \ - \ - typeof(*(RMW)) val__; \ - \ - atomic_read_explicit(rmw__, &val__, memory_order_relaxed); \ - do { \ - } while (!atomic_compare_exchange_weak_explicit(rmw__, &val__, \ - val__ OP arg__, \ - ORDER, \ - memory_order_relaxed)); \ - *(ORIG) = val__; \ - }) - -#define atomic_or_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_op__(RMW, |, ARG, ORIG, ORDER) -#define atomic_or(RMW, ARG, ORIG) \ - atomic_or_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_xor_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_op__(RMW, ^, ARG, ORIG, ORDER) -#define atomic_xor(RMW, ARG, ORIG) \ - atomic_xor_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - -#define atomic_and_explicit(RMW, ARG, ORIG, ORDER) \ - atomic_op__(RMW, &, ARG, ORIG, ORDER) -#define atomic_and(RMW, ARG, ORIG) \ - atomic_and_explicit(RMW, ARG, ORIG, memory_order_seq_cst) - - -/* atomic_flag */ - -typedef ATOMIC(int) atomic_flag; -#define ATOMIC_FLAG_INIT { false } - -#define atomic_flag_test_and_set_explicit(FLAG, ORDER) \ - ((bool)atomic_exchange__(FLAG, 1, ORDER)) -#define atomic_flag_test_and_set(FLAG) \ - atomic_flag_test_and_set_explicit(FLAG, memory_order_seq_cst) - -#define atomic_flag_clear_explicit(FLAG, ORDER) \ - atomic_store_explicit(FLAG, 0, ORDER) -#define atomic_flag_clear(FLAG) \ - atomic_flag_clear_explicit(FLAG, memory_order_seq_cst) Index: openvswitch-2.17.2/lib/process.h =================================================================== --- openvswitch-2.17.2.orig/lib/process.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2011, 2013 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PROCESS_H -#define PROCESS_H 1 - -#include -#include - -struct process; - -struct process_info { - unsigned long int vsz; /* Virtual size, in kB. */ - unsigned long int rss; /* Resident set size, in kB. */ - long long int booted; /* ms since monitor started. */ - int crashes; /* # of crashes (usually 0). */ - long long int uptime; /* ms since last (re)started by monitor. */ - long long int cputime; /* ms of CPU used during 'uptime'. */ - int core_id; - char name[18]; -}; - -/* Starting and monitoring subprocesses. - * - * process_init() and process_start() may safely be called only from a - * single-threaded parent process. The parent process may safely create - * additional threads afterward, as long as the remaining functions in this - * group are called only from a single thread at any given time. */ -void process_init(void); -int process_start(char **argv, struct process **); -void process_destroy(struct process *); -int process_kill(const struct process *, int signr); -pid_t process_pid(const struct process *); -const char *process_name(const struct process *); -bool process_exited(struct process *); -int process_status(const struct process *); -void process_run(void); -void process_wait(struct process *); - -int count_crashes(pid_t); -bool get_process_info(pid_t, struct process_info *); - -/* These functions are thread-safe. */ -char *process_status_msg(int); -char *process_escape_args(char **argv); -char *process_search_path(const char *); - -#endif /* process.h */ Index: openvswitch-2.17.2/lib/random.h =================================================================== --- openvswitch-2.17.2.orig/lib/random.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2012 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef RANDOM_H -#define RANDOM_H 1 - -#include -#include - -void random_init(void); -void random_set_seed(uint32_t); - -void random_bytes(void *, size_t); -uint32_t random_uint32(void); -uint64_t random_uint64(void); - -static inline int -random_range(int max) -{ - return random_uint32() % max; -} - -static inline uint8_t -random_uint8(void) -{ - return random_uint32(); -} - -static inline uint16_t -random_uint16(void) -{ - return random_uint32(); -} - -#endif /* random.h */ Index: openvswitch-2.17.2/lib/simap.h =================================================================== --- openvswitch-2.17.2.orig/lib/simap.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2009, 2010, 2011, 2012, 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. - */ - -#ifndef SIMAP_H -#define SIMAP_H 1 - -#include "openvswitch/hmap.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* A map from strings to unsigned integers. */ -struct simap { - struct hmap map; /* Contains "struct simap_node"s. */ -}; - -struct simap_node { - struct hmap_node node; /* In struct simap's 'map' hmap. */ - char *name; - unsigned int data; -}; - -#define SIMAP_INITIALIZER(SIMAP) { HMAP_INITIALIZER(&(SIMAP)->map) } - -#define SIMAP_FOR_EACH(SIMAP_NODE, SIMAP) \ - HMAP_FOR_EACH_INIT (SIMAP_NODE, node, &(SIMAP)->map, \ - BUILD_ASSERT_TYPE(SIMAP_NODE, struct simap_node *), \ - BUILD_ASSERT_TYPE(SIMAP, struct simap *)) - -#define SIMAP_FOR_EACH_SAFE_SHORT(SIMAP_NODE, SIMAP) \ - HMAP_FOR_EACH_SAFE_SHORT_INIT (SIMAP_NODE, node, &(SIMAP)->map, \ - BUILD_ASSERT_TYPE(SIMAP_NODE, struct simap_node *), \ - BUILD_ASSERT_TYPE(SIMAP, struct simap *)) - -#define SIMAP_FOR_EACH_SAFE_LONG(SIMAP_NODE, NEXT, SIMAP) \ - HMAP_FOR_EACH_SAFE_LONG_INIT (SIMAP_NODE, NEXT, node, &(SIMAP)->map, \ - BUILD_ASSERT_TYPE(SIMAP_NODE, struct simap_node *), \ - BUILD_ASSERT_TYPE(NEXT, struct simap_node *), \ - BUILD_ASSERT_TYPE(SIMAP, struct simap *)) - -#define SIMAP_FOR_EACH_SAFE(...) \ - OVERLOAD_SAFE_MACRO(SIMAP_FOR_EACH_SAFE_LONG, \ - SIMAP_FOR_EACH_SAFE_SHORT, \ - 3, __VA_ARGS__) - -void simap_init(struct simap *); -void simap_destroy(struct simap *); -void simap_swap(struct simap *, struct simap *); -void simap_moved(struct simap *); -void simap_clear(struct simap *); - -bool simap_is_empty(const struct simap *); -size_t simap_count(const struct simap *); - -bool simap_put(struct simap *, const char *, unsigned int); -unsigned int simap_increase(struct simap *, const char *, unsigned int); - -unsigned int simap_get(const struct simap *, const char *); -struct simap_node *simap_find(const struct simap *, const char *); -struct simap_node *simap_find_len(const struct simap *, - const char *, size_t len); -bool simap_contains(const struct simap *, const char *); - -void simap_delete(struct simap *, struct simap_node *); -bool simap_find_and_delete(struct simap *, const char *); - -const struct simap_node **simap_sort(const struct simap *); -bool simap_equal(const struct simap *, const struct simap *); -uint32_t simap_hash(const struct simap *); - -#ifdef __cplusplus -} -#endif - -#endif /* simap.h */ Index: openvswitch-2.17.2/lib/skiplist.h =================================================================== --- openvswitch-2.17.2.orig/lib/skiplist.h +++ /dev/null @@ -1,49 +0,0 @@ -/* Copyright (C) 2016 Hewlett Packard Enterprise Development LP - * All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -#ifndef LIB_SKIPLIST_H_ -#define LIB_SKIPLIST_H_ - -#include -#include -#include - -typedef int (skiplist_comparator)(const void *a, const void *b, - const void *conf); - -struct skiplist_node; - -struct skiplist; - -#define SKIPLIST_FOR_EACH (SKIPLIST_NODE, SKIPLIST) \ - for (SKIPLIST_NODE = skiplist_first(SKIPLIST); \ - SKIPLIST_NODE; \ - SKIPLIST_NODE = skiplist_next(SKIPLIST_NODE)) - -struct skiplist *skiplist_create(skiplist_comparator *object_comparator, - void *configuration); -void skiplist_insert(struct skiplist *sl, const void *object); -void *skiplist_delete(struct skiplist *sl, const void *object); -struct skiplist_node *skiplist_find(struct skiplist *sl, const void *value); -void *skiplist_get_data(struct skiplist_node *node); -uint32_t skiplist_get_size(struct skiplist *sl); -struct skiplist_node *skiplist_forward_to(struct skiplist *sl, - const void *value); -struct skiplist_node *skiplist_first(struct skiplist *sl); -struct skiplist_node *skiplist_next(struct skiplist_node *node); -void skiplist_destroy(struct skiplist *sl, void (*func)(void *)); - -#endif /* LIB_SKIPLIST_H_ */ Index: openvswitch-2.17.2/lib/socket-util.h =================================================================== --- openvswitch-2.17.2.orig/lib/socket-util.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 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 SOCKET_UTIL_H -#define SOCKET_UTIL_H 1 - -#include -#include -#include -#include -#include -#include -#include -#include "openvswitch/types.h" -#include -#include - -struct ds; - -int set_nonblocking(int fd); -void xset_nonblocking(int fd); -void setsockopt_tcp_nodelay(int fd); -int set_dscp(int fd, int family, uint8_t dscp); - -bool addr_is_ipv6(const char *host_name); -int lookup_ip(const char *host_name, struct in_addr *address); -int lookup_ipv6(const char *host_name, struct in6_addr *address); - -int lookup_hostname(const char *host_name, struct in_addr *); - -int get_socket_rcvbuf(int sock); -int check_connection_completion(int fd); -void drain_fd(int fd, size_t n_packets); -ovs_be32 guess_netmask(ovs_be32 ip); - -void inet_parse_host_port_tokens(char *s, char **hostp, char **portp); -void inet_parse_port_host_tokens(char *s, char **portp, char **hostp); -bool inet_parse_active(const char *target, int default_port, - struct sockaddr_storage *ssp, - bool resolve_host, bool *dns_failure); -int inet_open_active(int style, const char *target, int default_port, - struct sockaddr_storage *ssp, int *fdp, uint8_t dscp); - -bool inet_parse_passive(const char *target, int default_port, - struct sockaddr_storage *ssp); -int inet_open_passive(int style, const char *target, int default_port, - struct sockaddr_storage *ssp, uint8_t dscp, - bool kernel_print_port); - -bool inet_parse_address(const char *target, struct sockaddr_storage *); - -int read_fully(int fd, void *, size_t, size_t *bytes_read); -int write_fully(int fd, const void *, size_t, size_t *bytes_written); - -int fsync_parent_dir(const char *file_name); -int get_mtime(const char *file_name, struct timespec *mtime); - -char *describe_fd(int fd); - -/* Default value of dscp bits for connection between controller and manager. - * Value of IPTOS_PREC_INTERNETCONTROL = 0xc0 which is defined - * in is used. */ -#define DSCP_DEFAULT (IPTOS_PREC_INTERNETCONTROL >> 2) - -/* Functions for working with sockaddr that might contain an IPv4 or - * IPv6 address. */ -bool sa_is_ip(const struct sockaddr *); -uint16_t sa_get_port(const struct sockaddr *); -struct in6_addr sa_get_address(const struct sockaddr *); -void sa_format_address(const struct sockaddr *, struct ds *); -void sa_format_address_nobracks(const struct sockaddr *, struct ds *); -size_t sa_length(const struct sockaddr *); - -/* Functions for working with sockaddr_storage that might contain an IPv4 or - * IPv6 address. */ -bool ss_is_ip(const struct sockaddr_storage *); -uint16_t ss_get_port(const struct sockaddr_storage *); -struct in6_addr ss_get_address(const struct sockaddr_storage *); -void ss_format_address(const struct sockaddr_storage *, struct ds *); -void ss_format_address_nobracks(const struct sockaddr_storage *, struct ds *); -size_t ss_length(const struct sockaddr_storage *); - -const char *sock_strerror(int error); - -#ifndef _WIN32 -void xpipe(int fds[2]); -void xpipe_nonblocking(int fds[2]); - -int drain_rcvbuf(int fd); - -int make_unix_socket(int style, bool nonblock, - const char *bind_path, const char *connect_path); -int get_unix_name_len(const struct sockaddr_un *sun, socklen_t sun_len); - -/* Universal sendmmsg and recvmmsg support on Linux. - * - * New enough Linux supports sendmmsg and recvmmsg, but older versions do not. - * We add the following infrastructure to allow all code on Linux to use - * sendmmsg and recvmmsg, regardless of platform support: - * - * - For platforms that lack these functions entirely, we emulate them. - * - * - With newer glibc but an old kernel, sendmmsg() and recvmmsg() fail with - * ENOSYS. To compensate, even if these functions appear to be available, we - * wrap them with handlers that use our emulation in this case. - */ -#ifdef __linux__ -#ifndef HAVE_STRUCT_MMSGHDR_MSG_LEN -struct mmsghdr { - struct msghdr msg_hdr; - unsigned int msg_len; -}; -#endif - -#ifndef HAVE_SENDMMSG -int sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int); -int recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *); -#else -#define sendmmsg wrap_sendmmsg -int wrap_sendmmsg(int, struct mmsghdr *, unsigned int, unsigned int); -#define recvmmsg wrap_recvmmsg -int wrap_recvmmsg(int, struct mmsghdr *, unsigned int, int, struct timespec *); -#endif -#endif /* __linux__ */ - -/* Helpers for calling ioctl() on an AF_INET socket. */ -struct ifreq; -int af_inet_ioctl(unsigned long int command, const void *arg); -int af_inet_ifreq_ioctl(const char *name, struct ifreq *, - unsigned long int cmd, const char *cmd_name); - -#define closesocket close -#endif - -#ifdef _WIN32 -static inline int make_unix_socket(int style, bool nonblock, - const char *bind_path, - const char *connect_path) -{ - return -EINVAL; -} - -/* Windows defines the 'optval' argument as char * instead of void *. */ -#define setsockopt(sock, level, optname, optval, optlen) \ - rpl_setsockopt(sock, level, optname, optval, optlen) -static inline int rpl_setsockopt(int sock, int level, int optname, - const void *optval, socklen_t optlen) -{ - return (setsockopt)(sock, level, optname, (const char *)optval, optlen); -} - -#define getsockopt(sock, level, optname, optval, optlen) \ - rpl_getsockopt(sock, level, optname, optval, optlen) -static inline int rpl_getsockopt(int sock, int level, int optname, - void *optval, socklen_t *optlen) -{ - return (getsockopt)(sock, level, optname, (char *)optval, optlen); -} -#endif - -/* In Windows platform, errno is not set for socket calls. - * The last error has to be gotten from WSAGetLastError(). */ -static inline int sock_errno(void) -{ -#ifdef _WIN32 - return WSAGetLastError(); -#else - return errno; -#endif -} - -#endif /* socket-util.h */ Index: openvswitch-2.17.2/lib/sort.h =================================================================== --- openvswitch-2.17.2.orig/lib/sort.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Copyright (c) 2009 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SORT_H -#define SORT_H 1 - -#include - -void sort(size_t count, - int (*compare)(size_t a, size_t b, void *aux), - void (*swap)(size_t a, size_t b, void *aux), - void *aux); - -#endif /* sort.h */ Index: openvswitch-2.17.2/lib/stopwatch.h =================================================================== --- openvswitch-2.17.2.orig/lib/stopwatch.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (c) 2017 Red Hat, 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 STOPWATCH_H -#define STOPWATCH_H 1 - -#include - -enum stopwatch_units { - SW_MS, - SW_US, - SW_NS, -}; - -struct stopwatch_stats { - unsigned long long count; /* Total number of samples. */ - enum stopwatch_units unit; /* Unit of following values. */ - unsigned long long max; /* Maximum value. */ - unsigned long long min; /* Minimum value. */ - double pctl_95; /* 95th percentile. */ - double ewma_50; /* Exponentially weighted moving average - (alpha 0.50). */ - double ewma_1; /* Exponentially weighted moving average - (alpha 0.01). */ -}; - -/* Create a new stopwatch. - * The "units" are not used for any calculations but are printed when - * statistics are requested. - */ -void stopwatch_create(const char *name, enum stopwatch_units units); - -/* Start a stopwatch. */ -void stopwatch_start(const char *name, unsigned long long ts); - -/* Stop a stopwatch. The elapsed time will be used for updating statistics - * for this stopwatch. - */ -void stopwatch_stop(const char *name, unsigned long long ts); - -/* Retrieve statistics calculated from collected samples */ -bool stopwatch_get_stats(const char *name, struct stopwatch_stats *stats); - -/* Block until all enqueued samples have been processed. */ -void stopwatch_sync(void); - -#endif /* stopwatch.h */ Index: openvswitch-2.17.2/lib/stream-ssl.h =================================================================== --- openvswitch-2.17.2.orig/lib/stream-ssl.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef STREAM_SSL_H -#define STREAM_SSL_H 1 - -#include - -bool stream_ssl_is_configured(void); -void stream_ssl_set_private_key_file(const char *file_name); -void stream_ssl_set_certificate_file(const char *file_name); -void stream_ssl_set_ca_cert_file(const char *file_name, bool bootstrap); -void stream_ssl_set_peer_ca_cert_file(const char *file_name); -void stream_ssl_set_key_and_cert(const char *private_key_file, - const char *certificate_file); -void stream_ssl_set_protocols(const char *arg); -void stream_ssl_set_ciphers(const char *arg); - -#define SSL_OPTION_ENUMS \ - OPT_SSL_PROTOCOLS, \ - OPT_SSL_CIPHERS - -#define STREAM_SSL_LONG_OPTIONS \ - {"private-key", required_argument, NULL, 'p'}, \ - {"certificate", required_argument, NULL, 'c'}, \ - {"ca-cert", required_argument, NULL, 'C'}, \ - {"ssl-protocols", required_argument, NULL, OPT_SSL_PROTOCOLS}, \ - {"ssl-ciphers", required_argument, NULL, OPT_SSL_CIPHERS} - -#define STREAM_SSL_OPTION_HANDLERS \ - case 'p': \ - stream_ssl_set_private_key_file(optarg); \ - break; \ - \ - case 'c': \ - stream_ssl_set_certificate_file(optarg); \ - break; \ - \ - case 'C': \ - stream_ssl_set_ca_cert_file(optarg, false); \ - break; \ - \ - case OPT_SSL_PROTOCOLS: \ - stream_ssl_set_protocols(optarg); \ - break; \ - \ - case OPT_SSL_CIPHERS: \ - stream_ssl_set_ciphers(optarg); \ - break; - -#define STREAM_SSL_CASES \ - case 'p': case 'c': case 'C': case OPT_SSL_PROTOCOLS: case OPT_SSL_CIPHERS: - -#endif /* stream-ssl.h */ Index: openvswitch-2.17.2/lib/svec.h =================================================================== --- openvswitch-2.17.2.orig/lib/svec.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2011 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef SVEC_H -#define SVEC_H 1 - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct svec { - char **names; - size_t n; - size_t allocated; -}; - -#define SVEC_EMPTY_INITIALIZER { NULL, 0, 0 } - -void svec_init(struct svec *); -void svec_clone(struct svec *, const struct svec *); -void svec_destroy(struct svec *); -void svec_clear(struct svec *); -bool svec_is_empty(const struct svec *); -void svec_add(struct svec *, const char *); -void svec_add_nocopy(struct svec *, char *); -void svec_del(struct svec *, const char *); -void svec_append(struct svec *, const struct svec *); -void svec_terminate(struct svec *); -void svec_sort(struct svec *); -void svec_sort_unique(struct svec *); -void svec_unique(struct svec *); -void svec_compact(struct svec *); -void svec_shuffle(struct svec *); -void svec_diff(const struct svec *a, const struct svec *b, - struct svec *a_only, struct svec *both, struct svec *b_only); -bool svec_contains(const struct svec *, const char *); -bool svec_contains_unsorted(const struct svec *, const char *); -size_t svec_find(const struct svec *, const char *); -bool svec_is_sorted(const struct svec *); -bool svec_is_unique(const struct svec *); -const char *svec_get_duplicate(const struct svec *); -void svec_swap(struct svec *a, struct svec *b); -void svec_print(const struct svec *svec, const char *title); -void svec_parse_words(struct svec *svec, const char *words); -bool svec_equal(const struct svec *, const struct svec *); -char *svec_join(const struct svec *, - const char *delimiter, const char *terminator); -const char *svec_back(const struct svec *); -void svec_pop_back(struct svec *); - -/* Iterates over the names in SVEC, assigning each name in turn to NAME and its - * index to INDEX. */ -#define SVEC_FOR_EACH(INDEX, NAME, SVEC) \ - for ((INDEX) = 0; \ - ((INDEX) < (SVEC)->n \ - ? (NAME) = (SVEC)->names[INDEX], 1 \ - : 0); \ - (INDEX)++) - -#ifdef __cplusplus -} -#endif - -#endif /* svec.h */ Index: openvswitch-2.17.2/lib/table.h =================================================================== --- openvswitch-2.17.2.orig/lib/table.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2009, 2010, 2011, 2012 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TABLE_H -#define TABLE_H 1 - -#include -#include -#include "openvswitch/compiler.h" -#include "openvswitch/json.h" - -struct ds; -struct table_style; - -/* Manipulating tables and their rows and columns. */ - -struct table { - struct cell *cells; - struct column *columns; - size_t n_columns, allocated_columns; - size_t n_rows, allocated_rows; - size_t current_column; - char *caption; - bool timestamp; -}; - -void table_init(struct table *); -void table_destroy(struct table *); -void table_set_caption(struct table *, char *caption); -void table_set_timestamp(struct table *, bool timestamp); - -void table_add_column(struct table *, const char *heading, ...) - OVS_PRINTF_FORMAT(2, 3); -void table_add_row(struct table *); - -/* Table cells. */ - -struct cell { - /* Literal text. */ - char *text; - - /* JSON. */ - struct json *json; - const struct ovsdb_type *type; -}; - -struct cell *table_add_cell(struct table *); - -/* Table formatting. */ - -enum table_format { - TF_TABLE, /* 2-d table. */ - TF_LIST, /* One cell per line, one row per paragraph. */ - TF_HTML, /* HTML table. */ - TF_CSV, /* Comma-separated lines. */ - TF_JSON /* JSON. */ -}; - -enum cell_format { - CF_STRING, /* String format. */ - CF_BARE, /* String format without most punctuation. */ - CF_JSON /* JSON. */ -}; - -struct table_style { - enum table_format format; /* TF_*. */ - enum cell_format cell_format; /* CF_*. */ - bool headings; /* Include headings? */ - int json_flags; /* CF_JSON: Flags for json_to_string(). */ - int max_column_width; /* CF_STRING: Limit for column width. */ -}; - -#define TABLE_STYLE_DEFAULT { TF_LIST, CF_STRING, true, JSSF_SORT, 0 } -static const struct table_style table_style_default = TABLE_STYLE_DEFAULT; - -#define TABLE_OPTION_ENUMS \ - OPT_NO_HEADINGS, \ - OPT_PRETTY, \ - OPT_BARE, \ - OPT_MAX_COLUMN_WIDTH - -#define TABLE_LONG_OPTIONS \ - {"format", required_argument, NULL, 'f'}, \ - {"data", required_argument, NULL, 'd'}, \ - {"no-headings", no_argument, NULL, OPT_NO_HEADINGS}, \ - {"pretty", no_argument, NULL, OPT_PRETTY}, \ - {"bare", no_argument, NULL, OPT_BARE}, \ - {"max-column-width", required_argument, NULL, OPT_MAX_COLUMN_WIDTH} - -#define TABLE_OPTION_HANDLERS(STYLE) \ - case 'f': \ - table_parse_format(STYLE, optarg); \ - break; \ - \ - case 'd': \ - table_parse_cell_format(STYLE, optarg); \ - break; \ - \ - case OPT_NO_HEADINGS: \ - (STYLE)->headings = false; \ - break; \ - \ - case OPT_PRETTY: \ - (STYLE)->json_flags |= JSSF_PRETTY; \ - break; \ - \ - case OPT_BARE: \ - (STYLE)->format = TF_LIST; \ - (STYLE)->cell_format = CF_BARE; \ - (STYLE)->headings = false; \ - break; \ - \ - case OPT_MAX_COLUMN_WIDTH: \ - (STYLE)->max_column_width = atoi(optarg); \ - break; - -void table_parse_format(struct table_style *, const char *format); -void table_parse_cell_format(struct table_style *, const char *format); - -void table_print(const struct table *, const struct table_style *); -void table_format(const struct table *, const struct table_style *, - struct ds *); -void table_format_reset(void); -void table_usage(void); - -#endif /* table.h */ Index: openvswitch-2.17.2/lib/unixctl.h =================================================================== --- openvswitch-2.17.2.orig/lib/unixctl.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2011 Nicira, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef UNIXCTL_H -#define UNIXCTL_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* Server for Unix domain socket control connection. */ -struct unixctl_server; -int unixctl_server_create(const char *path, struct unixctl_server **); -void unixctl_server_run(struct unixctl_server *); -void unixctl_server_wait(struct unixctl_server *); -void unixctl_server_destroy(struct unixctl_server *); - -const char *unixctl_server_get_path(const struct unixctl_server *); - -/* Client for Unix domain socket control connection. */ -struct jsonrpc; -int unixctl_client_create(const char *path, struct jsonrpc **client); -int unixctl_client_transact(struct jsonrpc *client, - const char *command, - int argc, char *argv[], - char **result, char **error); - -/* Command registration. */ -struct unixctl_conn; -typedef void unixctl_cb_func(struct unixctl_conn *, - int argc, const char *argv[], void *aux); -void unixctl_command_register(const char *name, const char *usage, - int min_args, int max_args, - unixctl_cb_func *cb, void *aux); -void unixctl_command_reply_error(struct unixctl_conn *, const char *error); -void unixctl_command_reply(struct unixctl_conn *, const char *body); - -#ifdef __cplusplus -} -#endif - -#endif /* unixctl.h */ Index: openvswitch-2.17.2/lib/uuid.h =================================================================== --- openvswitch-2.17.2.orig/lib/uuid.h +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2008, 2009, 2010, 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. - */ - -#ifndef UUID_H -#define UUID_H 1 - -#include "openvswitch/uuid.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* An initializer or expression for an all-zero UUID. */ -#define UUID_ZERO ((struct uuid) { .parts = { 0, 0, 0, 0 } }) - -/* Formats a UUID as a string, in the conventional format. - * - * Example: - * struct uuid uuid = ...; - * printf("This UUID is "UUID_FMT"\n", UUID_ARGS(&uuid)); - * - */ -#define UUID_LEN 36 -#define UUID_FMT "%08x-%04x-%04x-%04x-%04x%08x" -#define UUID_ARGS(UUID) \ - ((unsigned int) ((UUID)->parts[0])), \ - ((unsigned int) ((UUID)->parts[1] >> 16)), \ - ((unsigned int) ((UUID)->parts[1] & 0xffff)), \ - ((unsigned int) ((UUID)->parts[2] >> 16)), \ - ((unsigned int) ((UUID)->parts[2] & 0xffff)), \ - ((unsigned int) ((UUID)->parts[3])) - -/* Returns a hash value for 'uuid'. This hash value is the same regardless of - * whether we are running on a 32-bit or 64-bit or big-endian or little-endian - * architecture. */ -static inline size_t -uuid_hash(const struct uuid *uuid) -{ - return uuid->parts[0]; -} - -/* Returns true if 'a == b', false otherwise. */ -static inline bool -uuid_equals(const struct uuid *a, const struct uuid *b) -{ - return (a->parts[0] == b->parts[0] - && a->parts[1] == b->parts[1] - && a->parts[2] == b->parts[2] - && a->parts[3] == b->parts[3]); -} - -/* Returns the first 'n' hex digits of 'uuid', for 0 < 'n' <= 8. - * - * This is useful for displaying a few leading digits of the uuid, e.g. to - * display 4 digits: - * printf("%04x", uuid_prefix(uuid, 4)); - */ -static inline unsigned int -uuid_prefix(const struct uuid *uuid, int digits) -{ - return (uuid->parts[0] >> (32 - 4 * digits)); -} - -void uuid_init(void); -void uuid_generate(struct uuid *); -struct uuid uuid_random(void); -void uuid_zero(struct uuid *); -bool uuid_is_zero(const struct uuid *); -int uuid_compare_3way(const struct uuid *, const struct uuid *); -bool uuid_from_string(struct uuid *, const char *); -bool uuid_from_string_prefix(struct uuid *, const char *); -int uuid_is_partial_string(const char *); -int uuid_is_partial_match(const struct uuid *, const char *match); -void uuid_set_bits_v4(struct uuid *); - -#ifdef __cplusplus -} -#endif - -#endif /* uuid.h */