Invalid packets get dropped. Established connectections need to be sent through conntrack with just "nat" so that the VIP is changed to a loadbalanced IP address (by setting reg1 = 2). New connections need to be loadbalanced to one of the destination IP addresses (by setting reg1 = 3).
This introduces 2 OVN lflow actions. 1. ct_nat. This is used to send packets to conntrack to NAT them for already established connections. 2. ct_lb($ips). This is used to choose one of the $ips as destination ip address for new connections that need to be loadbalanced. Signed-off-by: Gurucharan Shetty <g...@ovn.org> --- ovn/northd/ovn-northd.8.xml | 68 ++++++++++++++++++++++++++++++----- ovn/northd/ovn-northd.c | 86 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 140 insertions(+), 14 deletions(-) diff --git a/ovn/northd/ovn-northd.8.xml b/ovn/northd/ovn-northd.8.xml index 3117b9a..4c476ee 100644 --- a/ovn/northd/ovn-northd.8.xml +++ b/ovn/northd/ovn-northd.8.xml @@ -218,15 +218,58 @@ </li> </ul> - <h3>Ingress Table 5: STATEFUL</h3> + <h3>Ingress Table 5: loadbalancer</h3> <p> - It contains a priority-0 flow that simply moves traffic to table 5. - A priority-100 flow commits packets to connection tracker based on a hint - provided by the previous tables (with a match for reg1 == 1). + It contains a priority-0 flow that simply moves traffic to table 6. </p> - <h3>Ingress Table 6: Destination Lookup</h3> + <ul> + <li> + For any established traffic, a priority-65535 flow that sets + 'reg1 = 2' as a hint for STATEFUL table to send the packet + through connection tracker to NAT it. + </li> + + <li> + A priority-65535 flow that drops all traffic marked by the + connection tracker as invalid. + </li> + + <li> + A priority-100 flow that sets 'reg1 = 3' as a hint for STATEFUL + table to choose one of the destination endpoints associated with + a VIP when the destination IP address of the packet is that VIP. + </li> + </ul> + + <h3>Ingress Table 6: STATEFUL</h3> + + <p> + It contains a priority-0 flow that simply moves traffic to table 6. + </p> + + <ul> + <li> + A priority-100 flow commits packets to connection tracker based on a + hint provided by the previous tables (with a match for reg1 == 1). + </li> + + <li> + A priority-100 flow sends packets through connection tracker for NAT + based on a hint provided by the previous tables (with a match for + reg1 == 2). + </li> + + <li> + A priority-100 flow commits the connection to the connection tracker + for NATting (choosing the destination IP address based on choices + provided in the loadbalancer table) based on a hint provided by the + previous tables (with a match for reg1 == 3). + </li> + </ul> + + <h3>Ingress Table 7: Destination Lookup</h3> <p> This table implements switching behavior. It contains these logical @@ -294,19 +337,26 @@ output; This is similar to ingress table 3. </p> - <h3>Egress Table 3: <code>to-lport</code> ACLs</h3> + <h3>Egress Table 3: loadbalancer</h3> + + <p> + This is similar to ingress table 5 except that it does not have + any rules to loadbalance new connections. + </p> + + <h3>Egress Table 4: <code>to-lport</code> ACLs</h3> <p> This is similar to ingress table 4 except for <code>to-lport</code> ACLs. </p> - <h3>Egress Table 4: STATEFUL</h3> + <h3>Egress Table 5: STATEFUL</h3> <p> - This is similar to ingress table 5. + This is similar to ingress table 6. </p> - <h3>Egress Table 5: Egress Port Security</h3> + <h3>Egress Table 6: Egress Port Security</h3> <p> This is similar to the ingress port security logic in ingress table 0, diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 28f5b45..c5c956b 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -90,16 +90,18 @@ enum ovn_stage { PIPELINE_STAGE(SWITCH, IN, PRE_LB, 2, "ls_in_pre_lb") \ PIPELINE_STAGE(SWITCH, IN, PRE_STATEFUL, 3, "ls_in_pre_stateful") \ PIPELINE_STAGE(SWITCH, IN, ACL, 4, "ls_in_acl") \ - PIPELINE_STAGE(SWITCH, IN, STATEFUL, 5, "ls_in_stateful") \ - PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 6, "ls_in_l2_lkup") \ + PIPELINE_STAGE(SWITCH, IN, LB, 5, "ls_in_lb") \ + PIPELINE_STAGE(SWITCH, IN, STATEFUL, 6, "ls_in_stateful") \ + PIPELINE_STAGE(SWITCH, IN, L2_LKUP, 7, "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, ACL, 3, "ls_out_acl") \ - PIPELINE_STAGE(SWITCH, OUT, STATEFUL, 4, "ls_out_stateful") \ - PIPELINE_STAGE(SWITCH, OUT, PORT_SEC, 5, "ls_out_port_sec") \ + 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, 6, "ls_out_port_sec") \ \ /* Logical router ingress stages. */ \ PIPELINE_STAGE(ROUTER, IN, ADMISSION, 0, "lr_in_admission") \ @@ -1173,6 +1175,51 @@ build_acls(struct ovn_datapath *od, struct hmap *lflows) } static void +build_lb(struct ovn_datapath *od, struct hmap *lflows) +{ + /* Ingress and Egress LB Table (Priority 0): Packets are allowed by + * default. */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_LB, 0, "1", "next;"); + ovn_lflow_add(lflows, od, S_SWITCH_OUT_LB, 0, "1", "next;"); + + if (od->nbs->loadbalancer) { + struct nbrec_load_balancer *lb = od->nbs->loadbalancer; + struct smap *vips = &lb->vips; + struct smap_node *node; + + /* Ingress and Egress LB Table (Priority 65535). + * + * Always drop traffic that's in an invalid state. This is + * enforced at a higher priority than ACLs can be defined. */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_LB, UINT16_MAX, + "ct.inv", "drop;"); + ovn_lflow_add(lflows, od, S_SWITCH_OUT_LB, UINT16_MAX, + "ct.inv", "drop;"); + + /* Ingress and Egress LB Table (Priority 65535). + * + * Send established traffic through conntrack for just NAT. */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_LB, UINT16_MAX, + "ct.est && !ct.rel && !ct.new && !ct.inv", + "reg1 = 2; next;"); + ovn_lflow_add(lflows, od, S_SWITCH_OUT_LB, UINT16_MAX, + "ct.est && !ct.rel && !ct.new && !ct.inv", + "reg1 = 2; next;"); + + SMAP_FOR_EACH (node, vips) { + struct ds match = DS_EMPTY_INITIALIZER; + + /* New connections in Ingress table. */ + ds_put_format(&match, "ip && ip4.dst == %s", node->key); + ovn_lflow_add(lflows, od, S_SWITCH_IN_LB, + 100, ds_cstr(&match), "reg1 = 3; next;"); + + ds_destroy(&match); + } + } +} + +static void build_stateful(struct ovn_datapath *od, struct hmap *lflows) { /* Ingress and Egress STATEFUL Table (Priority 0): Packets are @@ -1186,6 +1233,34 @@ build_stateful(struct ovn_datapath *od, struct hmap *lflows) "ct_commit; next;"); ovn_lflow_add(lflows, od, S_SWITCH_OUT_STATEFUL, 100, "reg1 == 1", "ct_commit; next;"); + + /* If reg1 is set as 2, then packets should just be sent through + * nat (without committing). */ + ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100, "reg1 == 2", + "ct_nat;"); + ovn_lflow_add(lflows, od, S_SWITCH_OUT_STATEFUL, 100, "reg1 == 2", + "ct_nat;"); + + if (od->nbs->loadbalancer) { + struct nbrec_load_balancer *lb = od->nbs->loadbalancer; + struct smap *vips = &lb->vips; + struct smap_node *node; + + SMAP_FOR_EACH (node, vips) { + struct ds match = DS_EMPTY_INITIALIZER; + struct ds action = DS_EMPTY_INITIALIZER; + + /* If reg1 is set as 3, then packets should be sent through + * nat and committed). */ + ds_put_format(&match, "ip && ip4.dst == %s && reg1 == 3", + node->key); + ds_put_format(&action, "ct_lb(\"%s\");", node->value); + ovn_lflow_add(lflows, od, S_SWITCH_IN_STATEFUL, 100, + ds_cstr(&match), ds_cstr(&action)); + ds_destroy(&match); + ds_destroy(&action); + } + } } static void @@ -1207,6 +1282,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_lb(od, lflows); build_stateful(od, lflows); } -- 1.9.1 _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev