Hi Taimur The attached patch is what you need. I hope it works for you.
- Volkan ________________________________________ From: ovs-discuss-boun...@openvswitch.org [ovs-discuss-boun...@openvswitch.org] on behalf of Taimur Hafeez [taimurhafee...@gmail.com] Sent: Wednesday, March 21, 2018 11:58 AM To: ovs-discuss@openvswitch.org Subject: [ovs-discuss] Setting TCP rwnd value in Open vSwitch Dear All, I want to modify value of receiver window field(used for flow control) in the TCP header using OpenFlow rule at Open vSwitch. To make it clear what I am trying to do, lets illustrate this in the following way, In_port=1, match src_ip=10.0.0.1, action:set_tcp_rwnd=10, out_port=2 Specifications: Controller ryu OpenFlow 1.3 OVS 2.5.2 Help/Clue would be highly appreciated, If anyone has done similar work. Thanks in advance! Best regards, -------------------- Taimur Hafeez NUST School of Electrical Engineering and Computer Science (SEECS), Islamabad, Pakistan.
diff --git a/datapath/linux/compat/include/linux/openvswitch.h b/datapath/linux/compat/include/linux/openvswitch.h index 12260d8..dd84b04 100644 --- a/datapath/linux/compat/include/linux/openvswitch.h +++ b/datapath/linux/compat/include/linux/openvswitch.h @@ -352,6 +352,8 @@ enum ovs_key_attr { OVS_KEY_ATTR_MPLS, /* array of struct ovs_key_mpls. * The implementation may restrict * the accepted length of the array. */ + OVS_KEY_ATTR_REDUCE_RWND, + OVS_KEY_ATTR_SET_RWND, OVS_KEY_ATTR_CT_STATE, /* u32 bitmask of OVS_CS_F_* */ OVS_KEY_ATTR_CT_ZONE, /* u16 connection tracking zone. */ OVS_KEY_ATTR_CT_MARK, /* u32 connection tracking mark */ @@ -433,6 +435,14 @@ struct ovs_key_ipv6 { __u8 ipv6_frag; /* One of OVS_FRAG_TYPE_*. */ }; +struct ovs_key_reduce_rwnd { + uint8_t rate; +}; + +struct ovs_key_set_rwnd { + ovs_be16 rwnd; +}; + struct ovs_key_tcp { __be16 tcp_src; __be16 tcp_dst; diff --git a/include/openvswitch/flow.h b/include/openvswitch/flow.h index df80dfe..64da205 100644 --- a/include/openvswitch/flow.h +++ b/include/openvswitch/flow.h @@ -120,7 +120,9 @@ struct flow { struct eth_addr arp_sha; /* ARP/ND source hardware address. */ struct eth_addr arp_tha; /* ARP/ND target hardware address. */ ovs_be16 tcp_flags; /* TCP flags. With L3 to avoid matching L4. */ - ovs_be16 pad3; /* Pad to 64 bits. */ + ovs_be16 rwnd; + uint8_t rate; + uint8_t pad3[7]; /* Pad to 64 bits. */ /* L4 (64-bit aligned) */ ovs_be16 tp_src; /* TCP/UDP/SCTP source port/ICMP type. */ @@ -135,7 +137,7 @@ BUILD_ASSERT_DECL(sizeof(struct flow_tnl) % sizeof(uint64_t) == 0); /* Remember to update FLOW_WC_SEQ when changing 'struct flow'. */ BUILD_ASSERT_DECL(offsetof(struct flow, igmp_group_ip4) + sizeof(uint32_t) - == sizeof(struct flow_tnl) + 248 + == sizeof(struct flow_tnl) + 256 && FLOW_WC_SEQ == 36); /* Incremental points at which flow classification may be performed in diff --git a/include/openvswitch/ofp-actions.h b/include/openvswitch/ofp-actions.h index 74e9dcc..a7512e5 100644 --- a/include/openvswitch/ofp-actions.h +++ b/include/openvswitch/ofp-actions.h @@ -86,6 +86,8 @@ OFPACT(DEC_MPLS_TTL, ofpact_null, ofpact, "dec_mpls_ttl") \ OFPACT(PUSH_MPLS, ofpact_push_mpls, ofpact, "push_mpls") \ OFPACT(POP_MPLS, ofpact_pop_mpls, ofpact, "pop_mpls") \ + OFPACT(REDUCE_RWND, ofpact_reduce_rwnd, ofpact, "reduce_rwnd") \ + OFPACT(SET_RWND, ofpact_set_rwnd, ofpact, "set_rwnd") \ \ /* Metadata. */ \ OFPACT(SET_TUNNEL, ofpact_tunnel, ofpact, "set_tunnel") \ @@ -426,6 +428,16 @@ struct ofpact_ip_ttl { uint8_t ttl; }; +struct ofpact_reduce_rwnd { + struct ofpact ofpact; + uint8_t rate; +}; + +struct ofpact_set_rwnd { + struct ofpact ofpact; + uint16_t rwnd; +}; + /* OFPACT_SET_L4_SRC_PORT, OFPACT_SET_L4_DST_PORT. * * Used for OFPAT10_SET_TP_SRC, OFPAT10_SET_TP_DST. */ diff --git a/lib/odp-execute.c b/lib/odp-execute.c index 65a6fcd..b052f1c 100644 --- a/lib/odp-execute.c +++ b/lib/odp-execute.c @@ -271,6 +271,21 @@ odp_execute_set_action(struct dp_packet *packet, const struct nlattr *a) } break; + case OVS_KEY_ATTR_REDUCE_RWND: + if (OVS_LIKELY(dp_packet_get_tcp_payload(packet))) { + const uint8_t rate = nl_attr_get_u8(a); + packet_reduce_rwnd(packet, rate); + } + + break; + case OVS_KEY_ATTR_SET_RWND: + if (OVS_LIKELY(dp_packet_get_tcp_payload(packet))) { + const uint16_t rwnd = nl_attr_get_u16(a); + packet_set_rwnd(packet, rwnd); + } + + break; + case OVS_KEY_ATTR_UDP: if (OVS_LIKELY(dp_packet_get_udp_payload(packet))) { const struct ovs_key_udp *udp_key @@ -422,6 +437,8 @@ odp_execute_masked_set_action(struct dp_packet *packet, | (md->recirc_id & ~*get_mask(a, uint32_t)); break; + case OVS_KEY_ATTR_REDUCE_RWND: + case OVS_KEY_ATTR_SET_RWND: case OVS_KEY_ATTR_TUNNEL: /* Masked data not supported for tunnel. */ case OVS_KEY_ATTR_UNSPEC: case OVS_KEY_ATTR_CT_STATE: diff --git a/lib/odp-util.c b/lib/odp-util.c index 626a82c..a124d6e 100644 --- a/lib/odp-util.c +++ b/lib/odp-util.c @@ -121,7 +121,6 @@ odp_action_len(uint16_t type) case OVS_ACTION_ATTR_SET_MASKED: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_SAMPLE: return ATTR_LEN_VARIABLE; case OVS_ACTION_ATTR_CT: return ATTR_LEN_VARIABLE; - case OVS_ACTION_ATTR_UNSPEC: case __OVS_ACTION_ATTR_MAX: return ATTR_LEN_INVALID; @@ -154,6 +153,8 @@ ovs_key_attr_to_string(enum ovs_key_attr attr, char *namebuf, size_t bufsize) case OVS_KEY_ATTR_IPV4: return "ipv4"; case OVS_KEY_ATTR_IPV6: return "ipv6"; case OVS_KEY_ATTR_TCP: return "tcp"; + case OVS_KEY_ATTR_REDUCE_RWND: return "reduce_rwnd"; + case OVS_KEY_ATTR_SET_RWND: return "set_rwnd"; case OVS_KEY_ATTR_TCP_FLAGS: return "tcp_flags"; case OVS_KEY_ATTR_UDP: return "udp"; case OVS_KEY_ATTR_SCTP: return "sctp"; @@ -1793,6 +1794,8 @@ static const struct attr_len_tbl ovs_flow_key_attr_lens[OVS_KEY_ATTR_MAX + 1] = [OVS_KEY_ATTR_IPV4] = { .len = sizeof(struct ovs_key_ipv4) }, [OVS_KEY_ATTR_IPV6] = { .len = sizeof(struct ovs_key_ipv6) }, [OVS_KEY_ATTR_TCP] = { .len = sizeof(struct ovs_key_tcp) }, + [OVS_KEY_ATTR_REDUCE_RWND] = { .len = 1 }, + [OVS_KEY_ATTR_SET_RWND] = { .len = 2 }, [OVS_KEY_ATTR_TCP_FLAGS] = { .len = 2 }, [OVS_KEY_ATTR_UDP] = { .len = sizeof(struct ovs_key_udp) }, [OVS_KEY_ATTR_SCTP] = { .len = sizeof(struct ovs_key_sctp) }, @@ -2872,6 +2875,22 @@ format_odp_key_attr(const struct nlattr *a, const struct nlattr *ma, ds_chomp(ds, ','); break; } + + case OVS_KEY_ATTR_REDUCE_RWND: { + const struct ovs_key_reduce_rwnd *mask = ma ? nl_attr_get(ma) : NULL; + uint8_t rate = nl_attr_get_u8(a); + format_u8u(ds, "rate", rate, MASK(mask, rate), verbose); + ds_chomp(ds, ','); + break; + } + + case OVS_KEY_ATTR_SET_RWND: { + const struct ovs_key_set_rwnd *mask = ma ? nl_attr_get(ma) : NULL; + ovs_be16 rwnd = nl_attr_get_be16(a); + format_be16(ds, "rwnd", rwnd, MASK(mask, rwnd), verbose); + break; + } + case OVS_KEY_ATTR_TCP_FLAGS: if (!is_exact) { format_flags_masked(ds, NULL, packet_tcp_flag_to_string, @@ -3393,6 +3412,22 @@ scan_tcp_flags(const char *s, ovs_be16 *key, ovs_be16 *mask) return 0; } +static int +scan_rwnd(const char *s, ovs_be16 *key, ovs_be16 *mask) +{ + OVS_NOT_REACHED();; + return 0; +} + +static int +scan_rate(const char *s, uint8_t *key, uint8_t *mask) +{ + OVS_NOT_REACHED();; + return 0; +} + static uint32_t ovs_to_odp_ct_state(uint8_t state) { @@ -4112,6 +4147,9 @@ parse_odp_key_mask_attr(const char *s, const struct simap *port_names, SCAN_FIELD("dst=", be16, tcp_dst); } SCAN_END(OVS_KEY_ATTR_TCP); + SCAN_SINGLE("reduce_rwnd(", uint8_t, rate, OVS_KEY_ATTR_REDUCE_RWND); + SCAN_SINGLE("set_rwnd(", ovs_be16, rwnd, OVS_KEY_ATTR_SET_RWND); + SCAN_SINGLE("tcp_flags(", ovs_be16, tcp_flags, OVS_KEY_ATTR_TCP_FLAGS); SCAN_BEGIN("udp(", struct ovs_key_udp) { @@ -5843,6 +5881,68 @@ commit_set_port_action(const struct flow *flow, struct flow *base_flow, } static void +commit_reduce_rwnd_action(const struct flow *flow, struct flow *base_flow, + struct ofpbuf *odp_actions, struct flow_wildcards *wc, + bool use_masked) +{ + uint8_t key, mask, base; + + /* Check if 'flow' really has an L3 header. */ + if (!flow->nw_proto) { + return; + } + + if (!is_ip_any(base_flow)) { + return; + } + + if (flow->nw_proto != IPPROTO_TCP) { + return; + } + + key = flow->rate; + base = base_flow->rate; + mask = wc->masks.rate; + + if (commit(OVS_KEY_ATTR_REDUCE_RWND, use_masked, &key, &base, &mask, sizeof key, + odp_actions)) { + base_flow->rate = base; + wc->masks.rate = mask; + } +} + +static void +commit_set_rwnd_action(const struct flow *flow, struct flow *base_flow, + struct ofpbuf *odp_actions, struct flow_wildcards *wc, + bool use_masked) +{ + uint16_t key, mask, base; + + /* Check if 'flow' really has an L3 header. */ + if (!flow->nw_proto) { + return; + } + + if (!is_ip_any(base_flow)) { + return; + } + + if (flow->nw_proto != IPPROTO_TCP) { + return; + } + + key = flow->rwnd; + base = base_flow->rwnd; + mask = wc->masks.rwnd; + + if (commit(OVS_KEY_ATTR_SET_RWND, use_masked, &key, &base, &mask, sizeof key, + odp_actions)) { + base_flow->rwnd = base; + wc->masks.rwnd = mask; + } +} + +static void commit_set_priority_action(const struct flow *flow, struct flow *base_flow, struct ofpbuf *odp_actions, struct flow_wildcards *wc, @@ -5899,6 +5999,8 @@ commit_odp_actions(const struct flow *flow, struct flow *base, commit_set_ether_addr_action(flow, base, odp_actions, wc, use_masked); slow1 = commit_set_nw_action(flow, base, odp_actions, wc, use_masked); commit_set_port_action(flow, base, odp_actions, wc, use_masked); + commit_reduce_rwnd_action(flow, base, odp_actions, wc, use_masked); + commit_set_rwnd_action(flow, base, odp_actions, wc, use_masked); slow2 = commit_set_icmp_action(flow, base, odp_actions, wc); commit_mpls_action(flow, base, odp_actions); commit_vlan_action(flow->vlan_tci, base, odp_actions, wc); diff --git a/lib/ofp-actions.c b/lib/ofp-actions.c index 16f0f7c..3e2e334 100644 --- a/lib/ofp-actions.c +++ b/lib/ofp-actions.c @@ -229,6 +229,11 @@ enum ofp_raw_action_type { /* NX1.0-1.4(6): struct nx_action_reg_move, ... */ NXAST_RAW_REG_MOVE, + /* OF1.3+(41): uint8_t. */ + OFPAT_RAW_REDUCE_RWND, + /* OF1.3+(42): uint16_t. */ + OFPAT_RAW_SET_RWND, + /* ## ------------------------- ## */ /* ## Nicira extension actions. ## */ /* ## ------------------------- ## */ @@ -431,6 +436,8 @@ ofpact_next_flattened(const struct ofpact *ofpact) case OFPACT_WRITE_METADATA: case OFPACT_GOTO_TABLE: case OFPACT_NAT: + case OFPACT_REDUCE_RWND: + case OFPACT_SET_RWND: return ofpact_next(ofpact); case OFPACT_CT: @@ -1995,6 +2002,18 @@ format_SET_IP_TTL(const struct ofpact_ip_ttl *a, struct ds *s) { ds_put_format(s, "%smod_nw_ttl:%s%d", colors.param, colors.end, a->ttl); } + +static void +format_REDUCE_RWND(const struct ofpact_reduce_rwnd *a, struct ds *s) +{ + ds_put_format(s, "%sreduce_rwnd:%s%d", colors.param, colors.end, a->rate); +} + +static void +format_SET_RWND(const struct ofpact_set_rwnd *a, struct ds *s) +{ + ds_put_format(s, "%sset_rwnd:%s%d", colors.param, colors.end, a->rwnd); +} /* Set TCP/UDP/SCTP port actions. */ @@ -2016,6 +2035,24 @@ decode_OFPAT_RAW_SET_TP_DST(ovs_be16 port, return 0; } +static enum ofperr +decode_OFPAT_RAW_REDUCE_RWND(uint8_t rate, + enum ofp_version ofp_version OVS_UNUSED, + struct ofpbuf *out) +{ + ofpact_put_REDUCE_RWND(out)->rate = rate; + return 0; +} + +static enum ofperr +decode_OFPAT_RAW_SET_RWND(uint16_t rwnd, + enum ofp_version ofp_version OVS_UNUSED, + struct ofpbuf *out) +{ + ofpact_put_SET_RWND(out)->rwnd = ntohs(rwnd); + return 0; +} + static void encode_SET_L4_port(const struct ofpact_l4_port *l4_port, enum ofp_version ofp_version, enum ofp_raw_action_type raw, @@ -2057,6 +2094,20 @@ encode_SET_L4_DST_PORT(const struct ofpact_l4_port *l4_port, encode_SET_L4_port(l4_port, ofp_version, OFPAT_RAW_SET_TP_DST, field, out); } +static void +encode_REDUCE_RWND(const struct ofpact_reduce_rwnd *reduce_rwnd, + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out) +{ + put_OFPAT_REDUCE_RWND(out, reduce_rwnd->rate); +} + +static void +encode_SET_RWND(const struct ofpact_set_rwnd *set_rwnd, + enum ofp_version ofp_version OVS_UNUSED, struct ofpbuf *out) +{ + put_OFPAT_SET_RWND(out, set_rwnd->rwnd); +} + static char * OVS_WARN_UNUSED_RESULT parse_SET_L4_SRC_PORT(char *arg, struct ofpbuf *ofpacts, enum ofputil_protocol *usable_protocols OVS_UNUSED) @@ -2084,6 +2135,39 @@ format_SET_L4_DST_PORT(const struct ofpact_l4_port *a, struct ds *s) { ds_put_format(s, "%smod_tp_dst:%s%d", colors.param, colors.end, a->port); } + +static char * OVS_WARN_UNUSED_RESULT +parse_SET_RWND(char *arg, struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) +{ + uint16_t rwnd; + char *error; + + error = str_to_u16(arg, "rwnd", &rwnd); + if (error) { + return error; + } + + ofpact_put_SET_RWND(ofpacts)->rwnd = rwnd; + return NULL; +} + +static char * OVS_WARN_UNUSED_RESULT +parse_REDUCE_RWND(char *arg, struct ofpbuf *ofpacts, + enum ofputil_protocol *usable_protocols OVS_UNUSED) +{ + uint8_t rate; + char *error; + + error = str_to_u8(arg, "rate", &rate); + if (error) { + return error; + } + + ofpact_put_REDUCE_RWND(ofpacts)->rate = rate; + return NULL; +} + /* Action structure for OFPAT_COPY_FIELD. */ struct ofp15_action_copy_field { @@ -6156,6 +6240,8 @@ ofpact_is_set_or_move_action(const struct ofpact *a) case OFPACT_SET_TUNNEL: case OFPACT_SET_VLAN_PCP: case OFPACT_SET_VLAN_VID: + case OFPACT_SET_RWND: + case OFPACT_REDUCE_RWND: return true; case OFPACT_BUNDLE: case OFPACT_CLEAR_ACTIONS: @@ -6229,6 +6315,8 @@ ofpact_is_allowed_in_actions_set(const struct ofpact *a) case OFPACT_SET_VLAN_PCP: case OFPACT_SET_VLAN_VID: case OFPACT_STRIP_VLAN: + case OFPACT_REDUCE_RWND: + case OFPACT_SET_RWND: return true; /* In general these actions are excluded because they are not part of @@ -6472,6 +6560,8 @@ ovs_instruction_type_from_ofpact_type(enum ofpact_type type) case OFPACT_DEBUG_RECIRC: case OFPACT_CT: case OFPACT_NAT: + case OFPACT_REDUCE_RWND: + case OFPACT_SET_RWND: default: return OVSINST_OFPIT11_APPLY_ACTIONS; } @@ -6920,7 +7010,13 @@ ofpact_check__(enum ofputil_protocol *usable_protocols, struct ofpact *a, inconsistent_match(usable_protocols); } return 0; + case OFPACT_REDUCE_RWND: + case OFPACT_SET_RWND: + if (!is_ip_any(flow) || (flow->nw_proto != IPPROTO_TCP)) { + inconsistent_match(usable_protocols); + } + return 0; case OFPACT_SET_IP_DSCP: case OFPACT_SET_IP_ECN: case OFPACT_SET_IP_TTL: @@ -7457,6 +7553,9 @@ get_ofpact_map(enum ofp_version version) { OFPACT_SET_IP_TTL, 23 }, { OFPACT_DEC_TTL, 24 }, { OFPACT_SET_FIELD, 25 }, + + { OFPACT_REDUCE_RWND, 41 }, + { OFPACT_SET_RWND, 42 }, /* OF1.3+ OFPAT_PUSH_PBB (26) not supported. */ /* OF1.3+ OFPAT_POP_PBB (27) not supported. */ { 0, -1 }, @@ -7590,6 +7689,8 @@ ofpact_outputs_to_port(const struct ofpact *ofpact, ofp_port_t port) case OFPACT_DEBUG_RECIRC: case OFPACT_CT: case OFPACT_NAT: + case OFPACT_REDUCE_RWND: + case OFPACT_SET_RWND: default: return false; } @@ -7824,6 +7925,11 @@ ofpacts_parse__(char *str, struct ofpbuf *ofpacts, return xstrdup("apply_actions is the default instruction"); } else if (ofputil_port_from_string(key, &port)) { ofpact_put_OUTPUT(ofpacts)->port = port; + + } else if (!strcasecmp(key, "reduce_rwnd")) { + error = parse_REDUCE_RWND(value, ofpacts, usable_protocols); + } else if (!strcasecmp(key, "set_rwnd")) { + error = parse_SET_RWND(value, ofpacts, usable_protocols); } else { return xasprintf("unknown action %s", key); } diff --git a/lib/packets.c b/lib/packets.c index 990c407..772a991 100644 --- a/lib/packets.c +++ b/lib/packets.c @@ -1118,6 +1118,25 @@ packet_set_udp_port(struct dp_packet *packet, ovs_be16 src, ovs_be16 dst) } } +void packet_set_rwnd(struct dp_packet *packet, ovs_be16 rwnd) +{ + struct tcp_header *th = dp_packet_l4(packet); + if (ntohs(rwnd) < ntohs(th->tcp_winsz)) { + th->tcp_csum = recalc_csum16(th->tcp_csum, th->tcp_winsz, rwnd); + th->tcp_winsz = rwnd; + } +} + +void packet_reduce_rwnd(struct dp_packet *packet, uint8_t rate) +{ + if (rate > 0 && rate < 100) { + struct tcp_header *th = dp_packet_l4(packet); + ovs_be16 new_winsz = th->tcp_winsz * (rate / 100u); + th->tcp_csum = recalc_csum16(th->tcp_csum, th->tcp_winsz, new_winsz); + th->tcp_winsz = new_winsz; + } +} + /* Sets the SCTP source and destination port ('src' and 'dst' respectively) of * the SCTP header contained in 'packet'. 'packet' must be a valid SCTP packet * with its l4 offset properly populated. */ diff --git a/lib/packets.h b/lib/packets.h index 21bd35c..b1c77d8 100644 --- a/lib/packets.h +++ b/lib/packets.h @@ -1098,6 +1098,9 @@ void packet_set_ipv6(struct dp_packet *, const ovs_be32 src[4], ovs_be32 fl, uint8_t hlmit); 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_rwnd(struct dp_packet *, ovs_be16 rwnd); +void packet_reduce_rwnd(struct dp_packet *, uint8_t rate); + 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 ovs_be32 target[4], diff --git a/ofproto/ofproto-dpif-sflow.c b/ofproto/ofproto-dpif-sflow.c index 37992b4..29a7b80 100644 --- a/ofproto/ofproto-dpif-sflow.c +++ b/ofproto/ofproto-dpif-sflow.c @@ -1024,6 +1024,8 @@ sflow_read_set_action(const struct nlattr *attr, case OVS_KEY_ATTR_CT_LABELS: case OVS_KEY_ATTR_UNSPEC: case __OVS_KEY_ATTR_MAX: + case OVS_KEY_ATTR_REDUCE_RWND: + case OVS_KEY_ATTR_SET_RWND: default: break; } diff --git a/ofproto/ofproto-dpif-xlate.c b/ofproto/ofproto-dpif-xlate.c index 4d10a54..3b21f17 100644 --- a/ofproto/ofproto-dpif-xlate.c +++ b/ofproto/ofproto-dpif-xlate.c @@ -4428,6 +4428,8 @@ freeze_unroll_actions(const struct ofpact *a, const struct ofpact *end, case OFPACT_DEBUG_RECIRC: case OFPACT_CT: case OFPACT_NAT: + case OFPACT_REDUCE_RWND: + case OFPACT_SET_RWND: /* These may not generate PACKET INs. */ break; @@ -4682,6 +4684,8 @@ recirc_for_mpls(const struct ofpact *a, struct xlate_ctx *ctx) case OFPACT_WRITE_ACTIONS: case OFPACT_WRITE_METADATA: case OFPACT_GOTO_TABLE: + case OFPACT_REDUCE_RWND: + case OFPACT_SET_RWND: default: break; } @@ -4857,6 +4861,19 @@ do_xlate_actions(const struct ofpact *ofpacts, size_t ofpacts_len, } break; + case OFPACT_REDUCE_RWND: + if (is_ip_any(flow)) { + wc->masks.rate = 0xff; + flow->rate = ofpact_get_REDUCE_RWND(a)->rate; + } + break; + case OFPACT_SET_RWND: + if (is_ip_any(flow)) { + wc->masks.rwnd = 0xffff; + flow->rwnd = ofpact_get_SET_RWND(a)->rwnd; + } + break; + case OFPACT_RESUBMIT: /* Freezing complicates resubmit. Some action in the flow * entry found by resubmit might trigger freezing. If that
_______________________________________________ discuss mailing list disc...@openvswitch.org https://mail.openvswitch.org/mailman/listinfo/ovs-discuss