Skip to content

Commit

Permalink
dpif-netdev: Fix crash when add dp flow without in_port field.
Browse files Browse the repository at this point in the history
Userspace datapath relies on fact that every datapath flow has exact
match on the in_port, but flows without in_port match could be
added directly via dpctl commands.  Even though dpctl is a debug
interface, datapath should just reject such flows instead of
crashing on assertion.

Fix the following crash and add a unit test for this issue
to tests/dpif-netdev.at:

$ ovs-appctl dpctl/add-flow "eth(),eth_type(0x0800),ipv4()" "3"
  unixctl|WARN|error communicating with unix:ovs-vswitchd.ctl: End of file
  ovs-appctl: ovs-vswitchd: transaction error (End of file)

ovs-vswitchd.log record:
  util(ovs-vswitchd)|EMER|lib/dpif-netdev.c:3638:
    assertion match->wc.masks.in_port.odp_port == ODPP_NONE failed
    in dp_netdev_flow_add()
  daemon_unix(monitor)|ERR|2 crashes: pid 1995 died, killed (Aborted),
                                      core dumped, restarting

Fix result:

$ ovs-appctl dpctl/add-flow "eth(),eth_type(0x0800),ipv4()" "3"
  ovs-vswitchd: updating flow table (Invalid argument)
  ovs-appctl: ovs-vswitchd: server returned an error

ovs-vswitchd.log record:
  dpif_netdev|ERR|failed to put[create] flow: in_port is not an exact match
  dpif|WARN|netdev@ovs-netdev: failed to put[create] (Invalid argument)
    ufid:7e...d1 eth(src=00..00,dst=00..00),eth_type(0x0800),
    ipv4(src=0.0.0.0/0.0.0.0,dst=0.0.0.0/0.0.0.0,proto=0/0,tos=0/0,ttl=0/0), actions:3

Signed-off-by: Mao YingMing <maoyingming@baidu.com>
Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
  • Loading branch information
Mao YingMing authored and igsilya committed Mar 1, 2021
1 parent a7ffe40 commit 476e3b0
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
9 changes: 9 additions & 0 deletions lib/dpif-netdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -3830,6 +3830,15 @@ dpif_netdev_flow_put(struct dpif *dpif, const struct dpif_flow_put *put)
return error;
}

if (match.wc.masks.in_port.odp_port != ODPP_NONE) {
static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5);

VLOG_ERR_RL(&rl, "failed to put%s flow: in_port is not an exact match",
(put->flags & DPIF_FP_CREATE) ? "[create]"
: (put->flags & DPIF_FP_MODIFY) ? "[modify]" : "[zero]");
return EINVAL;
}

if (put->ufid) {
ufid = *put->ufid;
} else {
Expand Down
17 changes: 17 additions & 0 deletions tests/dpif-netdev.at
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,20 @@ arp,in_port=ANY,dl_vlan=11,dl_vlan_pcp=7,vlan_tci1=0x0000,dl_src=00:06:07:08:09:

DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy])
DPIF_NETDEV_FLOW_HW_OFFLOAD_OFFSETS_VID_ARP([dummy-pmd])

AT_SETUP([dpif-netdev - check dpctl/add-flow in_port exact match])
OVS_VSWITCHD_START(
[add-port br0 p1 \
-- set interface p1 type=dummy options:pstream=punix:$OVS_RUNDIR/p0.sock \
-- set bridge br0 datapath-type=dummy \
other-config:datapath-id=1234 fail-mode=secure])

AT_CHECK([ovs-appctl dpctl/add-flow "eth(),eth_type(0x0800),ipv4()" "3"], [2],
[], [dnl
ovs-vswitchd: updating flow table (Invalid argument)
ovs-appctl: ovs-vswitchd: server returned an error
])
OVS_WAIT_UNTIL([grep "flow: in_port is not an exact match" ovs-vswitchd.log])
OVS_VSWITCHD_STOP(["/flow: in_port is not an exact match/d
/failed to put/d"])
AT_CLEANUP

0 comments on commit 476e3b0

Please sign in to comment.