Skip to content

Commit 1a03fc7

Browse files
anbu-enovanceblp
authored andcommitted
DSCP marking on packets
This patch adds support for marking qos on IP packets based on arbitrary match criteria for a logical switch. Signed-off-by: Babu Shanmugam <bschanmu@redhat.com> Suggested-by: Mickey Spiegel <mickeys.dev@gmail.com> Acked-by: Mickey Spiegel <mickeys.dev@gmail.com> [blp@ovn.org fixes races in the test and added ovn-trace checks] Signed-off-by: Ben Pfaff <blp@ovn.org>
1 parent 644ecb1 commit 1a03fc7

8 files changed

Lines changed: 263 additions & 41 deletions

File tree

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ Post-v2.6.0
22
---------------------
33
- OVN:
44
* QoS is now implemented via egress shaping rather than ingress policing.
5+
* DSCP marking is now supported, via the new northbound QoS table.
56
- Fixed regression in table stats maintenance introduced in OVS
67
2.3.0, wherein the number of OpenFlow table hits and misses was
78
not accurate.

ovn/lib/logical-fields.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ ovn_init_symtab(struct shash *symtab)
137137
expr_symtab_add_predicate(symtab, "ip6", "eth.type == 0x86dd");
138138
expr_symtab_add_predicate(symtab, "ip", "ip4 || ip6");
139139
expr_symtab_add_field(symtab, "ip.proto", MFF_IP_PROTO, "ip", true);
140-
expr_symtab_add_field(symtab, "ip.dscp", MFF_IP_DSCP, "ip", false);
140+
expr_symtab_add_field(symtab, "ip.dscp", MFF_IP_DSCP_SHIFTED, "ip", false);
141141
expr_symtab_add_field(symtab, "ip.ecn", MFF_IP_ECN, "ip", false);
142142
expr_symtab_add_field(symtab, "ip.ttl", MFF_IP_TTL, "ip", false);
143143

ovn/northd/ovn-northd.8.xml

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,27 @@
362362
</li>
363363
</ul>
364364

365-
<h3>Ingress Table 7: LB</h3>
365+
<h3>Ingress Table 7: <code>from-lport</code> QoS marking</h3>
366+
367+
<p>
368+
Logical flows in this table closely reproduce those in the
369+
<code>QoS</code> table in the <code>OVN_Northbound</code> database
370+
for the <code>from-lport</code> direction.
371+
</p>
372+
373+
<ul>
374+
<li>
375+
For every qos_rules for every logical switch a flow will be added at
376+
priorities mentioned in the QoS table.
377+
</li>
378+
379+
<li>
380+
One priority-0 fallback flow that matches all packets and advances to
381+
the next table.
382+
</li>
383+
</ul>
384+
385+
<h3>Ingress Table 8: LB</h3>
366386

367387
<p>
368388
It contains a priority-0 flow that simply moves traffic to the next
@@ -375,7 +395,7 @@
375395
connection.)
376396
</p>
377397

378-
<h3>Ingress Table 8: Stateful</h3>
398+
<h3>Ingress Table 9: Stateful</h3>
379399

380400
<ul>
381401
<li>
@@ -412,7 +432,7 @@
412432
</li>
413433
</ul>
414434

415-
<h3>Ingress Table 9: ARP/ND responder</h3>
435+
<h3>Ingress Table 10: ARP/ND responder</h3>
416436

417437
<p>
418438
This table implements ARP/ND responder for known IPs. It contains these
@@ -507,7 +527,7 @@ nd_na {
507527
</li>
508528
</ul>
509529

510-
<h3>Ingress Table 10: DHCP option processing</h3>
530+
<h3>Ingress Table 11: DHCP option processing</h3>
511531

512532
<p>
513533
This table adds the DHCPv4 options to a DHCPv4 packet from the
@@ -567,7 +587,7 @@ next;
567587
</li>
568588
</ul>
569589

570-
<h3>Ingress Table 11: DHCP responses</h3>
590+
<h3>Ingress Table 12: DHCP responses</h3>
571591

572592
<p>
573593
This table implements DHCP responder for the DHCP replies generated by
@@ -649,7 +669,7 @@ output;
649669
</li>
650670
</ul>
651671

652-
<h3>Ingress Table 12: Destination Lookup</h3>
672+
<h3>Ingress Table 13 Destination Lookup</h3>
653673

654674
<p>
655675
This table implements switching behavior. It contains these logical
@@ -716,7 +736,14 @@ output;
716736
<code>to-lport</code> ACLs.
717737
</p>
718738

719-
<h3>Egress Table 5: Stateful</h3>
739+
<h3>Egress Table 5: <code>to-lport</code> QoS marking</h3>
740+
741+
<p>
742+
This is similar to ingress table <code>QoS marking</code> except for
743+
<code>to-lport</code> qos rules.
744+
</p>
745+
746+
<h3>Egress Table 6: Stateful</h3>
720747

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

733-
<h3>Egress Table 6: Egress Port Security - IP</h3>
760+
<h3>Egress Table 7: Egress Port Security - IP</h3>
734761

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

743-
<h3>Egress Table 7: Egress Port Security - L2</h3>
770+
<h3>Egress Table 8: Egress Port Security - L2</h3>
744771

745772
<p>
746773
This is similar to the ingress port security logic in ingress table

ovn/northd/ovn-northd.c

Lines changed: 53 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -96,31 +96,33 @@ enum ovn_datapath_type {
9696
* form the stage's full name, e.g. S_SWITCH_IN_PORT_SEC_L2,
9797
* S_ROUTER_OUT_DELIVERY. */
9898
enum ovn_stage {
99-
#define PIPELINE_STAGES \
100-
/* Logical switch ingress stages. */ \
101-
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_L2, 0, "ls_in_port_sec_l2") \
102-
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_IP, 1, "ls_in_port_sec_ip") \
103-
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_ND, 2, "ls_in_port_sec_nd") \
104-
PIPELINE_STAGE(SWITCH, IN, PRE_ACL, 3, "ls_in_pre_acl") \
105-
PIPELINE_STAGE(SWITCH, IN, PRE_LB, 4, "ls_in_pre_lb") \
106-
PIPELINE_STAGE(SWITCH, IN, PRE_STATEFUL, 5, "ls_in_pre_stateful") \
107-
PIPELINE_STAGE(SWITCH, IN, ACL, 6, "ls_in_acl") \
108-
PIPELINE_STAGE(SWITCH, IN, LB, 7, "ls_in_lb") \
109-
PIPELINE_STAGE(SWITCH, IN, STATEFUL, 8, "ls_in_stateful") \
110-
PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 9, "ls_in_arp_rsp") \
111-
PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 10, "ls_in_dhcp_options") \
112-
PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 11, "ls_in_dhcp_response") \
113-
PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 12, "ls_in_l2_lkup") \
99+
#define PIPELINE_STAGES \
100+
/* Logical switch ingress stages. */ \
101+
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_L2, 0, "ls_in_port_sec_l2") \
102+
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_IP, 1, "ls_in_port_sec_ip") \
103+
PIPELINE_STAGE(SWITCH, IN, PORT_SEC_ND, 2, "ls_in_port_sec_nd") \
104+
PIPELINE_STAGE(SWITCH, IN, PRE_ACL, 3, "ls_in_pre_acl") \
105+
PIPELINE_STAGE(SWITCH, IN, PRE_LB, 4, "ls_in_pre_lb") \
106+
PIPELINE_STAGE(SWITCH, IN, PRE_STATEFUL, 5, "ls_in_pre_stateful") \
107+
PIPELINE_STAGE(SWITCH, IN, ACL, 6, "ls_in_acl") \
108+
PIPELINE_STAGE(SWITCH, IN, QOS_MARK, 7, "ls_in_qos_mark") \
109+
PIPELINE_STAGE(SWITCH, IN, LB, 8, "ls_in_lb") \
110+
PIPELINE_STAGE(SWITCH, IN, STATEFUL, 9, "ls_in_stateful") \
111+
PIPELINE_STAGE(SWITCH, IN, ARP_ND_RSP, 10, "ls_in_arp_rsp") \
112+
PIPELINE_STAGE(SWITCH, IN, DHCP_OPTIONS, 11, "ls_in_dhcp_options") \
113+
PIPELINE_STAGE(SWITCH, IN, DHCP_RESPONSE, 12, "ls_in_dhcp_response") \
114+
PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 13, "ls_in_l2_lkup") \
114115
\
115116
/* Logical switch egress stages. */ \
116117
PIPELINE_STAGE(SWITCH, OUT, PRE_LB, 0, "ls_out_pre_lb") \
117118
PIPELINE_STAGE(SWITCH, OUT, PRE_ACL, 1, "ls_out_pre_acl") \
118119
PIPELINE_STAGE(SWITCH, OUT, PRE_STATEFUL, 2, "ls_out_pre_stateful") \
119120
PIPELINE_STAGE(SWITCH, OUT, LB, 3, "ls_out_lb") \
120121
PIPELINE_STAGE(SWITCH, OUT, ACL, 4, "ls_out_acl") \
121-
PIPELINE_STAGE(SWITCH, OUT, STATEFUL, 5, "ls_out_stateful") \
122-
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_IP, 6, "ls_out_port_sec_ip") \
123-
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2, 7, "ls_out_port_sec_l2") \
122+
PIPELINE_STAGE(SWITCH, OUT, QOS_MARK, 5, "ls_out_qos_mark") \
123+
PIPELINE_STAGE(SWITCH, OUT, STATEFUL, 6, "ls_out_stateful") \
124+
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_IP, 7, "ls_out_port_sec_ip") \
125+
PIPELINE_STAGE(SWITCH, OUT, PORT_SEC_L2, 8, "ls_out_port_sec_l2") \
124126
\
125127
/* Logical router ingress stages. */ \
126128
PIPELINE_STAGE(ROUTER, IN, ADMISSION, 0, "lr_in_admission") \
@@ -2610,6 +2612,29 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows)
26102612
}
26112613
}
26122614

2615+
static void
2616+
build_qos(struct ovn_datapath *od, struct hmap *lflows) {
2617+
ovn_lflow_add(lflows, od, S_SWITCH_IN_QOS_MARK, 0, "1", "next;");
2618+
ovn_lflow_add(lflows, od, S_SWITCH_OUT_QOS_MARK, 0, "1", "next;");
2619+
2620+
for (size_t i = 0; i < od->nbs->n_qos_rules; i++) {
2621+
struct nbrec_qos *qos = od->nbs->qos_rules[i];
2622+
bool ingress = !strcmp(qos->direction, "from-lport") ? true :false;
2623+
enum ovn_stage stage = ingress ? S_SWITCH_IN_QOS_MARK : S_SWITCH_OUT_QOS_MARK;
2624+
2625+
if (!strcmp(qos->key_action, "dscp")) {
2626+
struct ds dscp_action = DS_EMPTY_INITIALIZER;
2627+
2628+
ds_put_format(&dscp_action, "ip.dscp = %d; next;",
2629+
(uint8_t)qos->value_action);
2630+
ovn_lflow_add(lflows, od, stage,
2631+
qos->priority,
2632+
qos->match, ds_cstr(&dscp_action));
2633+
ds_destroy(&dscp_action);
2634+
}
2635+
}
2636+
}
2637+
26132638
static void
26142639
build_lb(struct ovn_datapath *od, struct hmap *lflows)
26152640
{
@@ -2715,7 +2740,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
27152740
struct ds actions = DS_EMPTY_INITIALIZER;
27162741

27172742
/* Build pre-ACL and ACL tables for both ingress and egress.
2718-
* Ingress tables 3 and 4. Egress tables 0 and 1. */
2743+
* Ingress tables 3 through 9. Egress tables 0 through 6. */
27192744
struct ovn_datapath *od;
27202745
HMAP_FOR_EACH (od, key_node, datapaths) {
27212746
if (!od->nbs) {
@@ -2726,6 +2751,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
27262751
build_pre_lb(od, lflows);
27272752
build_pre_stateful(od, lflows);
27282753
build_acls(od, lflows);
2754+
build_qos(od, lflows);
27292755
build_lb(od, lflows);
27302756
build_stateful(od, lflows);
27312757
}
@@ -2797,7 +2823,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
27972823
ovn_lflow_add(lflows, od, S_SWITCH_IN_PORT_SEC_IP, 0, "1", "next;");
27982824
}
27992825

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

2815-
/* Ingress table 9: ARP/ND responder, reply for known IPs.
2841+
/* Ingress table 10: ARP/ND responder, reply for known IPs.
28162842
* (priority 50). */
28172843
HMAP_FOR_EACH (op, key_node, ports) {
28182844
if (!op->nbsp) {
@@ -2905,7 +2931,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
29052931
}
29062932
}
29072933

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

2918-
/* Logical switch ingress table 10 and 11: DHCP options and response
2944+
/* Logical switch ingress table 11 and 12: DHCP options and response
29192945
* priority 100 flows. */
29202946
HMAP_FOR_EACH (op, key_node, ports) {
29212947
if (!op->nbsp) {
@@ -2994,7 +3020,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
29943020
}
29953021
}
29963022

2997-
/* Ingress table 10 and 11: DHCP options and response, by default goto next.
3023+
/* Ingress table 11 and 12: DHCP options and response, by default goto next.
29983024
* (priority 0). */
29993025

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

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

3029-
/* Ingress table 12: Destination lookup, unicast handling (priority 50), */
3055+
/* Ingress table 13: Destination lookup, unicast handling (priority 50), */
30303056
HMAP_FOR_EACH (op, key_node, ports) {
30313057
if (!op->nbsp) {
30323058
continue;
@@ -3073,7 +3099,7 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports,
30733099
}
30743100
}
30753101

3076-
/* Ingress table 12: Destination lookup for unknown MACs (priority 0). */
3102+
/* Ingress table 13: Destination lookup for unknown MACs (priority 0). */
30773103
HMAP_FOR_EACH (od, key_node, datapaths) {
30783104
if (!od->nbs) {
30793105
continue;

ovn/ovn-nb.ovsschema

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "OVN_Northbound",
3-
"version": "5.3.4",
4-
"cksum": "1155817817 9975",
3+
"version": "5.4.0",
4+
"cksum": "4176761817 11225",
55
"tables": {
66
"NB_Global": {
77
"columns": {
@@ -26,6 +26,11 @@
2626
"refType": "strong"},
2727
"min": 0,
2828
"max": "unlimited"}},
29+
"qos_rules": {"type": {"key": {"type": "uuid",
30+
"refTable": "QoS",
31+
"refType": "strong"},
32+
"min": 0,
33+
"max": "unlimited"}},
2934
"load_balancer": {"type": {"key": {"type": "uuid",
3035
"refTable": "Load_Balancer",
3136
"refType": "strong"},
@@ -124,6 +129,23 @@
124129
"type": {"key": "string", "value": "string",
125130
"min": 0, "max": "unlimited"}}},
126131
"isRoot": false},
132+
"QoS": {
133+
"columns": {
134+
"priority": {"type": {"key": {"type": "integer",
135+
"minInteger": 0,
136+
"maxInteger": 32767}}},
137+
"direction": {"type": {"key": {"type": "string",
138+
"enum": ["set", ["from-lport", "to-lport"]]}}},
139+
"match": {"type": "string"},
140+
"action": {"type": {"key": {"type": "string",
141+
"enum": ["set", ["dscp"]]},
142+
"value": {"type": "integer",
143+
"minInteger": 0,
144+
"maxInteger": 63}}},
145+
"external_ids": {
146+
"type": {"key": "string", "value": "string",
147+
"min": 0, "max": "unlimited"}}},
148+
"isRoot": false},
127149
"Logical_Router": {
128150
"columns": {
129151
"name": {"type": "string"},

0 commit comments

Comments
 (0)