Skip to content

Commit

Permalink
DSCP marking on packets
Browse files Browse the repository at this point in the history
This patch adds support for marking qos on IP packets based on arbitrary
match criteria for a logical switch.

Signed-off-by: Babu Shanmugam <[email protected]>
Suggested-by: Mickey Spiegel <[email protected]>
Acked-by: Mickey Spiegel <[email protected]>
[[email protected] fixes races in the test and added ovn-trace checks]
Signed-off-by: Ben Pfaff <[email protected]>
  • Loading branch information
anbu-enovance authored and blp committed Oct 6, 2016
1 parent 644ecb1 commit 1a03fc7
Show file tree
Hide file tree
Showing 8 changed files with 263 additions and 41 deletions.
1 change: 1 addition & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Post-v2.6.0
---------------------
- OVN:
* QoS is now implemented via egress shaping rather than ingress policing.
* DSCP marking is now supported, via the new northbound QoS table.
- Fixed regression in table stats maintenance introduced in OVS
2.3.0, wherein the number of OpenFlow table hits and misses was
not accurate.
Expand Down
2 changes: 1 addition & 1 deletion ovn/lib/logical-fields.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ ovn_init_symtab(struct shash *symtab)
expr_symtab_add_predicate(symtab, "ip6", "eth.type == 0x86dd");
expr_symtab_add_predicate(symtab, "ip", "ip4 || ip6");
expr_symtab_add_field(symtab, "ip.proto", MFF_IP_PROTO, "ip", true);
expr_symtab_add_field(symtab, "ip.dscp", MFF_IP_DSCP, "ip", false);
expr_symtab_add_field(symtab, "ip.dscp", MFF_IP_DSCP_SHIFTED, "ip", false);
expr_symtab_add_field(symtab, "ip.ecn", MFF_IP_ECN, "ip", false);
expr_symtab_add_field(symtab, "ip.ttl", MFF_IP_TTL, "ip", false);

Expand Down
47 changes: 37 additions & 10 deletions ovn/northd/ovn-northd.8.xml
Original file line number Diff line number Diff line change
Expand Up @@ -362,7 +362,27 @@
</li>
</ul>

<h3>Ingress Table 7: LB</h3>
<h3>Ingress Table 7: <code>from-lport</code> QoS marking</h3>

<p>
Logical flows in this table closely reproduce those in the
<code>QoS</code> table in the <code>OVN_Northbound</code> database
for the <code>from-lport</code> direction.
</p>

<ul>
<li>
For every qos_rules for every logical switch a flow will be added at
priorities mentioned in the QoS table.
</li>

<li>
One priority-0 fallback flow that matches all packets and advances to
the next table.
</li>
</ul>

<h3>Ingress Table 8: LB</h3>

<p>
It contains a priority-0 flow that simply moves traffic to the next
Expand All @@ -375,7 +395,7 @@
connection.)
</p>

<h3>Ingress Table 8: Stateful</h3>
<h3>Ingress Table 9: Stateful</h3>

<ul>
<li>
Expand Down Expand Up @@ -412,7 +432,7 @@
</li>
</ul>

<h3>Ingress Table 9: ARP/ND responder</h3>
<h3>Ingress Table 10: ARP/ND responder</h3>

<p>
This table implements ARP/ND responder for known IPs. It contains these
Expand Down Expand Up @@ -507,7 +527,7 @@ nd_na {
</li>
</ul>

<h3>Ingress Table 10: DHCP option processing</h3>
<h3>Ingress Table 11: DHCP option processing</h3>

<p>
This table adds the DHCPv4 options to a DHCPv4 packet from the
Expand Down Expand Up @@ -567,7 +587,7 @@ next;
</li>
</ul>

<h3>Ingress Table 11: DHCP responses</h3>
<h3>Ingress Table 12: DHCP responses</h3>

<p>
This table implements DHCP responder for the DHCP replies generated by
Expand Down Expand Up @@ -649,7 +669,7 @@ output;
</li>
</ul>

<h3>Ingress Table 12: Destination Lookup</h3>
<h3>Ingress Table 13 Destination Lookup</h3>

<p>
This table implements switching behavior. It contains these logical
Expand Down Expand Up @@ -716,7 +736,14 @@ output;
<code>to-lport</code> ACLs.
</p>

<h3>Egress Table 5: Stateful</h3>
<h3>Egress Table 5: <code>to-lport</code> QoS marking</h3>

<p>
This is similar to ingress table <code>QoS marking</code> except for
<code>to-lport</code> qos rules.
</p>

<h3>Egress Table 6: Stateful</h3>

<p>
This is similar to ingress table <code>Stateful</code> except that
Expand All @@ -727,10 +754,10 @@ output;
Also a priority 34000 logical flow is added for each logical port which
has DHCPv4 options defined to allow the DHCPv4 reply packet and which has
DHCPv6 options defined to allow the DHCPv6 reply packet from the
<code>Ingress Table 11: DHCP responses</code>.
<code>Ingress Table 12: DHCP responses</code>.
</p>

<h3>Egress Table 6: Egress Port Security - IP</h3>
<h3>Egress Table 7: Egress Port Security - IP</h3>

<p>
This is similar to the port security logic in table
Expand All @@ -740,7 +767,7 @@ output;
<code>ip4.src</code> and <code>ip6.src</code>
</p>

<h3>Egress Table 7: Egress Port Security - L2</h3>
<h3>Egress Table 8: Egress Port Security - L2</h3>

<p>
This is similar to the ingress port security logic in ingress table
Expand Down
80 changes: 53 additions & 27 deletions ovn/northd/ovn-northd.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,31 +96,33 @@ enum ovn_datapath_type {
* form the stage's full name, e.g. S_SWITCH_IN_PORT_SEC_L2,
* S_ROUTER_OUT_DELIVERY. */
enum ovn_stage {
#define PIPELINE_STAGES \
/* Logical switch ingress stages. */ \
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_L2, 0, "ls_in_port_sec_l2") \
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_IP, 1, "ls_in_port_sec_ip") \
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_ND, 2, "ls_in_port_sec_nd") \
PIPELINE_STAGE(SWITCH, IN, PRE_ACL, 3, "ls_in_pre_acl") \
PIPELINE_STAGE(SWITCH, IN, PRE_LB, 4, "ls_in_pre_lb") \
PIPELINE_STAGE(SWITCH, IN, PRE_STATEFUL, 5, "ls_in_pre_stateful") \
PIPELINE_STAGE(SWITCH, IN, ACL, 6, "ls_in_acl") \
PIPELINE_STAGE(SWITCH, IN, LB, 7, "ls_in_lb") \
PIPELINE_STAGE(SWITCH, IN, STATEFUL, 8, "ls_in_stateful") \
PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 9, "ls_in_arp_rsp") \
PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 10, "ls_in_dhcp_options") \
PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 11, "ls_in_dhcp_response") \
PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 12, "ls_in_l2_lkup") \
#define PIPELINE_STAGES \
/* Logical switch ingress stages. */ \
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_L2, 0, "ls_in_port_sec_l2") \
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_IP, 1, "ls_in_port_sec_ip") \
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_ND, 2, "ls_in_port_sec_nd") \
PIPELINE_STAGE(SWITCH, IN, PRE_ACL, 3, "ls_in_pre_acl") \
PIPELINE_STAGE(SWITCH, IN, PRE_LB, 4, "ls_in_pre_lb") \
PIPELINE_STAGE(SWITCH, IN, PRE_STATEFUL, 5, "ls_in_pre_stateful") \
PIPELINE_STAGE(SWITCH, IN, ACL, 6, "ls_in_acl") \
PIPELINE_STAGE(SWITCH, IN, QOS_MARK, 7, "ls_in_qos_mark") \
PIPELINE_STAGE(SWITCH, IN, LB, 8, "ls_in_lb") \
PIPELINE_STAGE(SWITCH, IN, STATEFUL, 9, "ls_in_stateful") \
PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 10, "ls_in_arp_rsp") \
PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 11, "ls_in_dhcp_options") \
PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 12, "ls_in_dhcp_response") \
PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 13, "ls_in_l2_lkup") \
\
/* Logical switch egress stages. */ \
PIPELINE_STAGE(SWITCH, OUT, PRE_LB, 0, "ls_out_pre_lb") \
PIPELINE_STAGE(SWITCH, OUT, PRE_ACL, 1, "ls_out_pre_acl") \
PIPELINE_STAGE(SWITCH, OUT, PRE_STATEFUL, 2, "ls_out_pre_stateful") \
PIPELINE_STAGE(SWITCH, OUT, LB, 3, "ls_out_lb") \
PIPELINE_STAGE(SWITCH, OUT, ACL, 4, "ls_out_acl") \
PIPELINE_STAGE(SWITCH, OUT, STATEFUL, 5, "ls_out_stateful") \
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_IP, 6, "ls_out_port_sec_ip") \
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2, 7, "ls_out_port_sec_l2") \
PIPELINE_STAGE(SWITCH, OUT, QOS_MARK, 5, "ls_out_qos_mark") \
PIPELINE_STAGE(SWITCH, OUT, STATEFUL, 6, "ls_out_stateful") \
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_IP, 7, "ls_out_port_sec_ip") \
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2, 8, "ls_out_port_sec_l2") \
\
/* Logical router ingress stages. */ \
PIPELINE_STAGE(ROUTER, IN, ADMISSION, 0, "lr_in_admission") \
Expand Down Expand Up @@ -2610,6 +2612,29 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
}
}

static void
build_qos(struct ovn_datapath *od, struct hmap *lflows) {
ovn_lflow_add(lflows, od, S_SWITCH_IN_QOS_MARK, 0, "1", "next;");
ovn_lflow_add(lflows, od, S_SWITCH_OUT_QOS_MARK, 0, "1", "next;");

for (size_t i = 0; i < od->nbs->n_qos_rules; i++) {
struct nbrec_qos *qos = od->nbs->qos_rules[i];
bool ingress = !strcmp(qos->direction, "from-lport") ? true :false;
enum ovn_stage stage = ingress ? S_SWITCH_IN_QOS_MARK : S_SWITCH_OUT_QOS_MARK;

if (!strcmp(qos->key_action, "dscp")) {
struct ds dscp_action = DS_EMPTY_INITIALIZER;

ds_put_format(&dscp_action, "ip.dscp = %d; next;",
(uint8_t)qos->value_action);
ovn_lflow_add(lflows, od, stage,
qos->priority,
qos->match, ds_cstr(&dscp_action));
ds_destroy(&dscp_action);
}
}
}

static void
build_lb(struct ovn_datapath *od, struct hmap *lflows)
{
Expand Down Expand Up @@ -2715,7 +2740,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
struct ds actions = DS_EMPTY_INITIALIZER;

/* Build pre-ACL and ACL tables for both ingress and egress.
* Ingress tables 3 and 4. Egress tables 0 and 1. */
* Ingress tables 3 through 9. Egress tables 0 through 6. */
struct ovn_datapath *od;
HMAP_FOR_EACH (od, key_node, datapaths) {
if (!od->nbs) {
Expand All @@ -2726,6 +2751,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
build_pre_lb(od, lflows);
build_pre_stateful(od, lflows);
build_acls(od, lflows);
build_qos(od, lflows);
build_lb(od, lflows);
build_stateful(od, lflows);
}
Expand Down Expand Up @@ -2797,7 +2823,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
ovn_lflow_add(lflows, od, S_SWITCH_IN_PORT_SEC_IP, 0, "1", "next;");
}

/* Ingress table 9: ARP/ND responder, skip requests coming from localnet
/* Ingress table 10: ARP/ND responder, skip requests coming from localnet
* ports. (priority 100). */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbsp) {
Expand All @@ -2812,7 +2838,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
}
}

/* Ingress table 9: ARP/ND responder, reply for known IPs.
/* Ingress table 10: ARP/ND responder, reply for known IPs.
* (priority 50). */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbsp) {
Expand Down Expand Up @@ -2905,7 +2931,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
}
}

/* Ingress table 9: ARP/ND responder, by default goto next.
/* Ingress table 10: ARP/ND responder, by default goto next.
* (priority 0)*/
HMAP_FOR_EACH (od, key_node, datapaths) {
if (!od->nbs) {
Expand All @@ -2915,7 +2941,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
ovn_lflow_add(lflows, od, S_SWITCH_IN_ARP_ND_RSP, 0, "1", "next;");
}

/* Logical switch ingress table 10 and 11: DHCP options and response
/* Logical switch ingress table 11 and 12: DHCP options and response
* priority 100 flows. */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbsp) {
Expand Down Expand Up @@ -2994,7 +3020,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
}
}

/* Ingress table 10 and 11: DHCP options and response, by default goto next.
/* Ingress table 11 and 12: DHCP options and response, by default goto next.
* (priority 0). */

HMAP_FOR_EACH (od, key_node, datapaths) {
Expand All @@ -3006,7 +3032,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
ovn_lflow_add(lflows, od, S_SWITCH_IN_DHCP_RESPONSE, 0, "1", "next;");
}

/* Ingress table 12: Destination lookup, broadcast and multicast handling
/* Ingress table 13: Destination lookup, broadcast and multicast handling
* (priority 100). */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbsp) {
Expand All @@ -3026,7 +3052,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
"outport = \""MC_FLOOD"\"; output;");
}

/* Ingress table 12: Destination lookup, unicast handling (priority 50), */
/* Ingress table 13: Destination lookup, unicast handling (priority 50), */
HMAP_FOR_EACH (op, key_node, ports) {
if (!op->nbsp) {
continue;
Expand Down Expand Up @@ -3073,7 +3099,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
}
}

/* Ingress table 12: Destination lookup for unknown MACs (priority 0). */
/* Ingress table 13: Destination lookup for unknown MACs (priority 0). */
HMAP_FOR_EACH (od, key_node, datapaths) {
if (!od->nbs) {
continue;
Expand Down
26 changes: 24 additions & 2 deletions ovn/ovn-nb.ovsschema
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "OVN_Northbound",
"version": "5.3.4",
"cksum": "1155817817 9975",
"version": "5.4.0",
"cksum": "4176761817 11225",
"tables": {
"NB_Global": {
"columns": {
Expand All @@ -26,6 +26,11 @@
"refType": "strong"},
"min": 0,
"max": "unlimited"}},
"qos_rules": {"type": {"key": {"type": "uuid",
"refTable": "QoS",
"refType": "strong"},
"min": 0,
"max": "unlimited"}},
"load_balancer": {"type": {"key": {"type": "uuid",
"refTable": "Load_Balancer",
"refType": "strong"},
Expand Down Expand Up @@ -124,6 +129,23 @@
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": false},
"QoS": {
"columns": {
"priority": {"type": {"key": {"type": "integer",
"minInteger": 0,
"maxInteger": 32767}}},
"direction": {"type": {"key": {"type": "string",
"enum": ["set", ["from-lport", "to-lport"]]}}},
"match": {"type": "string"},
"action": {"type": {"key": {"type": "string",
"enum": ["set", ["dscp"]]},
"value": {"type": "integer",
"minInteger": 0,
"maxInteger": 63}}},
"external_ids": {
"type": {"key": "string", "value": "string",
"min": 0, "max": "unlimited"}}},
"isRoot": false},
"Logical_Router": {
"columns": {
"name": {"type": "string"},
Expand Down
Loading

0 comments on commit 1a03fc7

Please sign in to comment.