Thanks for the review, will send a v2 Eelco Chaudron <[email protected]>于2023年6月8日 周四21:48写道:
> > > On 2 Jun 2023, at 20:42, Peng He wrote: > > > OVS allows overlapping megaflows, as long as the actions of these > > megaflows are equal. However, the current implementation of action > > modification relies on flow_lookup instead of ufid, this could result > > in looking up a wrong megaflow and make the ukeys and megaflows > inconsistent > > > > Just like the test case in the patch, at first we have a rule with the > > prefix: > > > > 10.1.2.0/24 > > > > and we will get a megaflow with prefixes 10.1.2.2/24 when a packet with > IP > > 10.1.2.2 is received. > > > > Then suppose we change the rule into 10.1.0.0/16. OVS prefers to keep > the > > 10.1.2.2/24 megaflow and just changes its action instead of extending > > the prefix into 10.1.2.2/16. > > > > then suppose we have a 10.1.0.2 packet, since it misses the megaflow, > > this time, we will have an overlapping megaflow with the right prefix: > > 10.1.0.2/16 > > > > now we have two megaflows: > > 10.1.2.2/24 > > 10.1.0.2/16 > > > > last, suppose we have changed the ruleset again. The revalidator this > > time still decides to change the actions of both megaflows instead of > > deleting them. > > > > The dpif_netdev_flow_put will search the megaflow to modify with unmasked > > keys, however it might lookup the wrong megaflow as the key 10.1.2.2 > matches > > both 10.1.2.2/24 and 10.1.0.2/16! > > > > This patch changes the megaflow lookup code in modification path into > > relying the ufid to find the correct megaflow instead of key lookup. > > > > Signed-off-by: Peng He <[email protected]> > > Hi Peng, > > This patch looks good in general, some style comments, and a problem with > the tests. > > Thanks, > > Eelco > > > --- > > lib/dpif-netdev.c | 64 ++++++++++++++++++++++++++--------------------- > > tests/pmd.at | 55 ++++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 90 insertions(+), 29 deletions(-) > > > > diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c > > index 70b953ae6..1362f27e6 100644 > > --- a/lib/dpif-netdev.c > > +++ b/lib/dpif-netdev.c > > @@ -4198,36 +4198,43 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, > > memset(stats, 0, sizeof *stats); > > } > > > > - ovs_mutex_lock(&pmd->flow_mutex); > > - netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL); > > - if (!netdev_flow) { > > - if (put->flags & DPIF_FP_CREATE) { > > + if (put->flags & DPIF_FP_CREATE) { > > + ovs_mutex_lock(&pmd->flow_mutex); > > + netdev_flow = dp_netdev_pmd_lookup_flow(pmd, key, NULL); > > + if (!netdev_flow) { > > dp_netdev_flow_add(pmd, match, ufid, put->actions, > > - put->actions_len, ODPP_NONE); > > + put->actions_len, ODPP_NONE); > > } else { > > - error = ENOENT; > > + error = EEXIST; > > } > > + ovs_mutex_unlock(&pmd->flow_mutex); > > } else { > > + netdev_flow = dp_netdev_pmd_find_flow(pmd, ufid, > > + put->key, put->key_len); > > + > > if (put->flags & DPIF_FP_MODIFY) { > > - struct dp_netdev_actions *new_actions; > > - struct dp_netdev_actions *old_actions; > > + if (!netdev_flow) { > > + error = ENOENT; > > + } else { > > + struct dp_netdev_actions *new_actions; > > + struct dp_netdev_actions *old_actions; > > > > - new_actions = dp_netdev_actions_create(put->actions, > > - put->actions_len); > > + new_actions = dp_netdev_actions_create(put->actions, > > + put->actions_len); > > Indentation is off here, and below. > > > > > - old_actions = dp_netdev_flow_get_actions(netdev_flow); > > - ovsrcu_set(&netdev_flow->actions, new_actions); > > + old_actions = dp_netdev_flow_get_actions(netdev_flow); > > + ovsrcu_set(&netdev_flow->actions, new_actions); > > > > - queue_netdev_flow_put(pmd, netdev_flow, match, > > - put->actions, put->actions_len, > > - DP_NETDEV_FLOW_OFFLOAD_OP_MOD); > > - log_netdev_flow_change(netdev_flow, match, old_actions, > > - put->actions, put->actions_len); > > + queue_netdev_flow_put(pmd, netdev_flow, match, > > + put->actions, put->actions_len, > > + DP_NETDEV_FLOW_OFFLOAD_OP_MOD); > > + log_netdev_flow_change(netdev_flow, match, old_actions, > > + put->actions, put->actions_len); > > > > - if (stats) { > > - get_dpif_flow_status(pmd->dp, netdev_flow, stats, NULL); > > - } > > - if (put->flags & DPIF_FP_ZERO_STATS) { > > + if (stats) { > > + get_dpif_flow_status(pmd->dp, netdev_flow, stats, > NULL); > > + } > > + if (put->flags & DPIF_FP_ZERO_STATS) { > > /* XXX: The userspace datapath uses thread local > statistics > > * (for flows), which should be updated only by the > owning > > * thread. Since we cannot write on stats memory here, > > @@ -4237,18 +4244,17 @@ flow_put_on_pmd(struct dp_netdev_pmd_thread *pmd, > > * - Should the need arise, this operation can be > implemented > > * by keeping a base value (to be update here) for > each > > * counter, and subtracting it before outputting the > stats */ > > - error = EOPNOTSUPP; > > + error = EOPNOTSUPP; > > + } > > + ovsrcu_postpone(dp_netdev_actions_free, old_actions); > > } > > - > > - ovsrcu_postpone(dp_netdev_actions_free, old_actions); > > - } else if (put->flags & DPIF_FP_CREATE) { > > - error = EEXIST; > > } else { > > - /* Overlapping flow. */ > > - error = EINVAL; > > + if (netdev_flow) { > > + /* Overlapping flow. */ > > + error = EINVAL; > > In general, as we only take care of DPIF_FP_CREATE or DPIF_FP_MODIFY we > could simplify the if/then tree. > Something like: > > if (!(put->flags & DPIF_FP_CREATE || put->flags & DPIF_FP_MODIFY)) { > return EINVAL > } > > > if (put->flags & DPIF_FP_CREATE) { > > > } else { > > > } > > > + } > > } > > } > > - ovs_mutex_unlock(&pmd->flow_mutex); > > return error; > > } > > > > diff --git a/tests/pmd.at b/tests/pmd.at > > index 48f3d432d..8e18ed5dd 100644 > > --- a/tests/pmd.at > > +++ b/tests/pmd.at > > @@ -1300,3 +1300,58 @@ OVS_WAIT_UNTIL([tail -n +$LINENUM > ovs-vswitchd.log | grep "PMD load based sleeps > > > > OVS_VSWITCHD_STOP > > AT_CLEANUP > > + > > +AT_SETUP([pmd - revalidator wrongly modify userspace megaflows]) > OVS_VSWITCHD_START( > > PMD should be in capitals like with all other tests. > > Also OVS_VSWITCHD_START() should start on a new line. > > > + [add-port br0 p1 \ > > + -- set interface p1 type=dummy-pmd \ > > + -- set bridge br0 datapath-type=dummy \ > > + -- add-port br0 p2 \ > > + -- set interface p2 type=dummy-pmd -- > > + ]) > > + > > +AT_DATA([flows.txt], [dnl > > +table=0,in_port=p1,ip,nw_dst=10.1.2.0/24,actions=p2 > > +]) > > + > > +dnl replace openflow, let revalidator work > > Please rework all comments, start the sentence with a Capital and end with > a dot. > > > +AT_DATA([flows2.txt], [dnl > > +table=0,in_port=p1,ip,nw_dst=10.1.0.0/16 actions=ct(commit) > > +]) > > + > > +AT_DATA([flows3.txt], [dnl > > +table=0,in_port=p1,ip,nw_dst=10.1.0.0/16 actions=p2 > > +]) > > + > > +ovs-ofctl add-flows br0 flows.txt > > +ovs-appctl netdev-dummy/receive p1 > 'ipv4(src=10.0.0.1,dst=10.1.2.2),tcp(src=1,dst=2)' > > + > > +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*core: 0//'], [0], [ > > This regex needs changing as it’s failing on my system: > > +++ > /home/echaudron/Documents/review/ovs_quick/tests/testsuite.dir/at-groups/1084/stdout > 2023-06-08 14:52:39.256073655 +0200 > @@ -1,3 +1,3 @@ > - > +flow-dump from pmd on cpu core: 11 > recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst= > 10.1.2.2/255.255.255.0,frag=no), packets:0, bytes:0, used:never, actions:2 > > > Maybe something like: > > -AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*core: 0//'], [0], [ > +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*core: [[0-9]]\+//'], > [0], [ > > Here and 2x more below. > > > > +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst= > 10.1.2.2/255.255.255.0,frag=no), packets:0, bytes:0, used:never, actions:2 > > +]) > > + > > +ovs-appctl netdev-dummy/receive p1 > 'ipv4(src=10.0.0.1,dst=10.1.2.2),tcp(src=1,dst=2)' > > + > > +dnl trigger revalidating and wait > > +AT_CHECK([ovs-ofctl --bundle replace-flows br0 flows2.txt]) > > +ovs-appctl revalidator/wait > > + > > +ovs-appctl netdev-dummy/receive p1 > 'ipv4(src=10.0.0.1,dst=10.1.0.2),tcp(src=1,dst=2)' > > +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*core: 0//' | > strip_xout_keep_actions], [0], [ > > > +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst= > 10.1.0.2/255.255.0.0,frag=no), packets:0, bytes:0, used:never, > actions:ct(commit) > > > +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst= > 10.1.2.2/255.255.255.0,frag=no), packets:0, bytes:0, used:0.0s, > actions:ct(commit) > > +]) > > + > > +dnl send more 10.1.0.2 to make 10.1.0.0/16 tuple preprend 10.1.2.0/24 > tuple in pvector of subtable > > +for i in `seq 0 512`;do > > for i in `seq 0 512`; do > > > +ovs-appctl netdev-dummy/receive p1 > 'ipv4(src=10.0.0.1,dst=10.1.0.2),tcp(src=1,dst=2)' > > Indent this comment. > > > +done > > + > > +AT_CHECK([ovs-ofctl --bundle replace-flows br0 flows3.txt]) > > + > > +AT_CHECK([ovs-appctl dpctl/dump-flows | sed 's/.*core: 0//' | > strip_xout_keep_actions], [0], [ > > > +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst= > 10.1.0.2/255.255.0.0,frag=no), packets:0, bytes:0, used:0.0s, actions:2 > > > +recirc_id(0),in_port(1),packet_type(ns=0,id=0),eth_type(0x0800),ipv4(dst= > 10.1.2.2/255.255.255.0,frag=no), packets:0, bytes:0, used:0.0s, actions:2 > > +]) > > + > > +OVS_VSWITCHD_STOP > > +AT_CLEANUP > > -- > > 2.25.1 > > -- hepeng _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
