To support taas function, this patch add two type of logica_switch_port, "mirror" and "taas". port with type "mirror" is used as inport for monitor flow in logica_switch, and port with type "taas" is used as outport for monitor flow in logica_switch.
The ovn-controller will make the relations of the ports in tap_service and tap_flow to mirror port and taas port. Signed-off-by: wang qianyu <[email protected]> --- ovn/controller/binding.c | 3 + ovn/controller/ovn-controller.c | 2 + ovn/controller/physical.c | 168 +++++++++++++++++++++++- ovn/northd/ovn-northd.c | 276 +++++++++++++++++++++++++++++++++++++++- ovn/ovn-nb.xml | 57 +++++++++ 5 files changed, 502 insertions(+), 4 deletions(-) diff --git a/ovn/controller/binding.c b/ovn/controller/binding.c index ca1d433..bbd391f 100644 --- a/ovn/controller/binding.c +++ b/ovn/controller/binding.c @@ -437,6 +437,9 @@ consider_local_datapath(struct controller_ctx *ctx, * for them. */ sset_add(local_lports, binding_rec->logical_port); our_chassis = false; + } else if (!strcmp(binding_rec->type, "mirror")) { + add_local_datapath(ctx, binding_rec->datapath, + false, local_datapaths); } if (ctx->ovnsb_idl_txn) { diff --git a/ovn/controller/ovn-controller.c b/ovn/controller/ovn-controller.c index e2c9652..0a148e4 100644 --- a/ovn/controller/ovn-controller.c +++ b/ovn/controller/ovn-controller.c @@ -150,6 +150,8 @@ update_sb_monitors(struct ovsdb_idl *ovnsb_idl, struct ovsdb_idl_condition mg = OVSDB_IDL_CONDITION_INIT(&mg); struct ovsdb_idl_condition dns = OVSDB_IDL_CONDITION_INIT(&dns); sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "patch"); + sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "mirror"); + sbrec_port_binding_add_clause_type(&pb, OVSDB_F_EQ, "taas"); /* XXX: We can optimize this, if we find a way to only monitor * ports that have a Gateway_Chassis that point's to our own * chassis */ diff --git a/ovn/controller/physical.c b/ovn/controller/physical.c index df71979..9070459 100644 --- a/ovn/controller/physical.c +++ b/ovn/controller/physical.c @@ -291,9 +291,83 @@ load_logical_ingress_metadata(const struct sbrec_port_binding *binding, } static void +taas_port_handle(const struct sbrec_port_binding *binding, + struct ofpbuf *ofpacts_p, + struct hmap *flow_table, + uint32_t dp_key, + uint32_t port_key) +{ + ofp_port_t ofport = u16_to_ofp(simap_get(&localvif_to_ofport, + binding->logical_port)); + if (!ofport) { + VLOG_INFO("can not find ofport of %s in this switch", + binding->logical_port); + return; + } + struct match match; + + /* Table 33, priority 100. + * ======================= + * + * Implements output to local hypervisor. Each flow matches a + * logical output port on the local hypervisor, and resubmits to + * table 34. + */ + match_init_catchall(&match); + ofpbuf_clear(ofpacts_p); + match_set_metadata(&match, htonll(dp_key)); + match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key); + + /* Resubmit to table 34. */ + put_resubmit(OFTABLE_CHECK_LOOPBACK, ofpacts_p); + ofctrl_add_flow(flow_table, OFTABLE_LOCAL_OUTPUT, 100, 0, + &match, ofpacts_p); + + /* Table 65, Priority 100. + * ======================= + * + * Deliver the packet to the local vif. */ + match_init_catchall(&match); + ofpbuf_clear(ofpacts_p); + match_set_metadata(&match, htonll(dp_key)); + match_set_reg(&match, MFF_LOG_OUTPORT - MFF_REG0, port_key); + ofpact_put_OUTPUT(ofpacts_p)->port = ofport; + ofctrl_add_flow(flow_table, OFTABLE_LOG_TO_PHY, 100, 0, + &match, ofpacts_p); +} + +struct mirror_port { + struct sbrec_port_binding *port; + struct ovs_list list; +}; + +static void +get_mports_from_lport(struct shash *mports, + char *logical_port_name, + struct ovs_list *mport_list) +{ + struct shash_node *node, *next_node; + SHASH_FOR_EACH_SAFE (node, next_node, mports) { + struct sbrec_port_binding *binding = node->data; + const char *source_port_name = smap_get(&binding->options, + "source-port"); + if (!source_port_name) { + continue; + } + if (strcmp(source_port_name, logical_port_name)) { + continue; + } + struct mirror_port *mport = xzalloc(sizeof *mport); + mport->port = binding; + ovs_list_push_back(mport_list, &mport->list); + } +} + +static void consider_port_binding(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, const struct simap *ct_zones, + struct shash *mports, const struct chassis_index *chassis_index, struct sset *active_tunnels, struct hmap *local_datapaths, @@ -360,6 +434,13 @@ consider_port_binding(struct controller_ctx *ctx, return; } + if (!strcmp(binding->type, "taas") && + binding->chassis == chassis) { + taas_port_handle(binding, ofpacts_p, flow_table, + dp_key, port_key); + return; + } + struct ovs_list *gateway_chassis = gateway_chassis_get_ordered(binding, chassis_index); @@ -531,13 +612,44 @@ consider_port_binding(struct controller_ctx *ctx, ofpbuf_clear(ofpacts_p); match_init_catchall(&match); match_set_in_port(&match, ofport); + if (tag || !strcmp(binding->type, "localnet") + || !strcmp(binding->type, "l2gateway")) { + match_set_dl_vlan(&match, htons(tag)); + } + + struct ovs_list local_mports; + ovs_list_init(&local_mports); + get_mports_from_lport(mports, binding->logical_port, &local_mports); + struct mirror_port *mp, *next; + /* add mirror action of flow mirrored port in table 0 */ + LIST_FOR_EACH_SAFE (mp, next, list, &local_mports) { + const struct sbrec_port_binding *mirror_port = mp->port; + if (!mirror_port) { + continue; + } + const char *direction = smap_get(&mirror_port->options, + "direction"); + if (direction && (!strcmp(direction, "from-port") || + !strcmp(direction, "both"))) { + size_t clone_ofs = ofpacts_p->size; + struct ofpact_nest *clone = ofpact_put_CLONE(ofpacts_p); + put_load(mirror_port->datapath->tunnel_key, MFF_LOG_DATAPATH, + 0, 64, ofpacts_p); + put_load(mirror_port->tunnel_key, MFF_LOG_INPORT, 0, 32, + ofpacts_p); + put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p); + + clone = ofpbuf_at_assert(ofpacts_p, clone_ofs, sizeof *clone); + ofpacts_p->header = clone; + ofpact_finish_CLONE(ofpacts_p, &clone); + } + } /* Match a VLAN tag and strip it, including stripping priority tags * (e.g. VLAN ID 0). In the latter case we'll add a second flow * for frames that lack any 802.1Q header later. */ if (tag || !strcmp(binding->type, "localnet") || !strcmp(binding->type, "l2gateway")) { - match_set_dl_vlan(&match, htons(tag)); if (nested_container) { /* When a packet comes from a container sitting behind a * parent_port, we should let it loopback to other containers @@ -586,6 +698,49 @@ consider_port_binding(struct controller_ctx *ctx, vlan_vid->push_vlan_if_needed = true; } ofpact_put_OUTPUT(ofpacts_p)->port = ofport; + + /* add mirror action of flow mirrored port in table 65 */ + LIST_FOR_EACH_SAFE (mp, next, list, &local_mports) { + const struct sbrec_port_binding *mirror_port = mp->port; + if (!mirror_port) { + continue; + } + const char *direction = smap_get(&mirror_port->options, + "direction"); + if (direction && (!strcmp(direction, "to-port") || + !strcmp(direction, "both"))) { + size_t clone_ofs = ofpacts_p->size; + struct ofpact_nest *clone = ofpact_put_CLONE(ofpacts_p); + ofpact_put_CT_CLEAR(ofpacts_p); + put_load(0, MFF_LOG_DNAT_ZONE, 0, 32, ofpacts_p); + put_load(0, MFF_LOG_SNAT_ZONE, 0, 32, ofpacts_p); + put_load(0, MFF_LOG_CT_ZONE, 0, 32, ofpacts_p); + put_load(0, MFF_LOG_FLAGS, 0, 32, ofpacts_p); + put_load(0, MFF_LOG_OUTPORT, 0, 32, ofpacts_p); + for (int i = 0; i < MFF_N_LOG_REGS; i++) { + put_load(0, MFF_LOG_REG0 + i, 0, 32, ofpacts_p); + } + + /* taas port may have the same chassis as the src port, + * so here need clear inport */ + put_load(0, MFF_IN_PORT, 0, 16, ofpacts_p); + put_load(mirror_port->datapath->tunnel_key, MFF_LOG_DATAPATH, + 0, 64, ofpacts_p); + put_load(mirror_port->tunnel_key, MFF_LOG_INPORT, + 0, 32, ofpacts_p); + put_resubmit(OFTABLE_LOG_INGRESS_PIPELINE, ofpacts_p); + + clone = ofpbuf_at_assert(ofpacts_p, clone_ofs, sizeof *clone); + ofpacts_p->header = clone; + ofpact_finish_CLONE(ofpacts_p, &clone); + } + } + + LIST_FOR_EACH_SAFE (mp, next, list, &local_mports) { + ovs_list_remove(&mp->list); + free(mp); + } + if (tag) { /* Revert the tag added to the packets headed to containers * in the previous step. If we don't do this, the packets @@ -983,12 +1138,21 @@ physical_run(struct controller_ctx *ctx, enum mf_field_id mff_ovn_geneve, /* Set up flows in table 0 for physical-to-logical translation and in table * 64 for logical-to-physical translation. */ const struct sbrec_port_binding *binding; + + struct shash mports = SHASH_INITIALIZER(&mports); + SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) { + if (!strcmp(binding->type, "mirror")) { + shash_add(&mports, binding->logical_port, binding); + } + } + SBREC_PORT_BINDING_FOR_EACH (binding, ctx->ovnsb_idl) { - consider_port_binding(ctx, mff_ovn_geneve, ct_zones, + consider_port_binding(ctx, mff_ovn_geneve, ct_zones, &mports, chassis_index, active_tunnels, local_datapaths, binding, chassis, &ofpacts, flow_table); } + shash_destroy(&mports); /* Handle output to multicast groups, in tables 32 and 33. */ const struct sbrec_multicast_group *mc; diff --git a/ovn/northd/ovn-northd.c b/ovn/northd/ovn-northd.c index 49e4ac3..55b4752 100644 --- a/ovn/northd/ovn-northd.c +++ b/ovn/northd/ovn-northd.c @@ -172,6 +172,8 @@ enum ovn_stage { * logical router dropping packets with source IP address equals * one of the logical router's own IP addresses. */ #define REGBIT_EGRESS_LOOPBACK "reg9[1]" +/* Indicate that a packet is cloned. */ +#define REGBIT_CLONED_FLOW "reg10[4]" /* Returns an "enum ovn_stage" built from the arguments. */ static enum ovn_stage @@ -1887,8 +1889,9 @@ ovn_port_update_sbrec(struct northd_context *ctx, /* If we found the chassis, and the gw chassis on record * differs from what we expect go ahead and update */ if (op->sb->n_gateway_chassis != 1 - || strcmp(op->sb->gateway_chassis[0]->chassis->name, - chassis->name) + || (op->sb->gateway_chassis[0]->chassis && + strcmp(op->sb->gateway_chassis[0]->chassis->name, + chassis->name)) || op->sb->gateway_chassis[0]->priority != 0) { /* Construct a single Gateway_Chassis entry on the * Port_Binding attached to the redirect_chassis @@ -3478,6 +3481,237 @@ build_stateful(struct ovn_datapath *od, struct hmap *lflows) } static void +build_mirror_flows(struct ovn_port *op, + struct hmap *ports, + struct hmap *lflows) +{ + struct ds match = DS_EMPTY_INITIALIZER; + struct ds actions = DS_EMPTY_INITIALIZER; + + /* Logical switch ingress table 15: L2_LKUP. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + /* build mirror flows */ + const char *taas_port_name = + smap_get(&op->nbsp->options, "taas-port"); + if (!taas_port_name) { + return; + } + struct ovn_port *taas_port = + ovn_port_find(ports, taas_port_name); + if (!taas_port) { + return; + } + if (taas_port->od != op->od) { + VLOG_INFO(" in valid configuration, inport: %s and outport %s is " + "not in same logical switch", op->nbsp->name, taas_port_name); + return; + } + + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_format(&actions, "outport = %s; output;", taas_port->json_key); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_L2_LKUP, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + + /* Logical switch ingress table 0: PORT_SEC_L2. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_L2, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 1: PORT_SEC_IP. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_IP, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 2: PORT_SEC_ND. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_ND, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 3: PRE_ACL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PRE_ACL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 4: PRE_LB. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PRE_LB, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 5: PRE_STATEFUL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PRE_STATEFUL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 6: ACL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ACL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 7: QOS_MARK. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_QOS_MARK, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 8: LB. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_LB, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 9: STATEFUL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_STATEFUL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 10: ARP_ND_RSP. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_ARP_ND_RSP, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 11: DHCP_OPTIONS. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_OPTIONS, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 12: DHCP_RESPONSE. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DHCP_RESPONSE, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 13: DNS_LOOKUP. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DNS_LOOKUP, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch ingress table 14: DNS_RESPONSE. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_DNS_RESPONSE, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 0: PRE_LB. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PRE_LB, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 1: PRE_ACL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PRE_ACL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 2: PRE_STATEFUL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PRE_STATEFUL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 3: LB. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_LB, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 4: ACL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_ACL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 5: QOS_MARK. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_QOS_MARK, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 6: STATEFUL. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_STATEFUL, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 7: PORT_SEC_IP. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "next;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PORT_SEC_IP, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + /* Logical switch egress table 8: PORT_SEC_L2. (priority 65535) */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "outport == %s", taas_port->json_key); + ds_put_cstr(&actions, "output;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_OUT_PORT_SEC_L2, 65535, + ds_cstr(&match), ds_cstr(&actions)); + + ds_destroy(&match); + ds_destroy(&actions); +} +static void build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, struct hmap *lflows, struct hmap *mcgroups) { @@ -3533,6 +3767,20 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, if (!op->nbsp) { continue; } + if (!strcmp(op->nbsp->type, "taas")) { + /* drop all packet receive from taas port */ + ds_clear(&match); + ds_clear(&actions); + ds_put_format(&match, "inport == %s", op->json_key); + ds_put_cstr(&actions, "drop;"); + ovn_lflow_add(lflows, op->od, S_SWITCH_IN_PORT_SEC_L2, 65535, + ds_cstr(&match), ds_cstr(&actions)); + continue; + } + if (!strcmp(op->nbsp->type, "mirror")) { + build_mirror_flows(op, ports, lflows); + continue; + } if (!lsp_is_enabled(op->nbsp)) { /* Drop packets from disabled logical ports (since logical flow @@ -3578,6 +3826,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, if (!op->nbsp) { continue; } + if (!strcmp(op->nbsp->type, "taas") || + !strcmp(op->nbsp->type, "mirror")) { + continue; + } if ((!strcmp(op->nbsp->type, "localnet")) || (!strcmp(op->nbsp->type, "vtep"))) { @@ -3594,6 +3846,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, if (!op->nbsp) { continue; } + if (!strcmp(op->nbsp->type, "taas") || + !strcmp(op->nbsp->type, "mirror")) { + continue; + } /* * Add ARP/ND reply flows if either the @@ -3699,6 +3955,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, if (!op->nbsp) { continue; } + if (!strcmp(op->nbsp->type, "taas") || + !strcmp(op->nbsp->type, "mirror")) { + continue; + } if (!lsp_is_enabled(op->nbsp) || !strcmp(op->nbsp->type, "router")) { /* Don't add the DHCP flows if the port is not enabled or if the @@ -3849,6 +4109,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, if (!op->nbsp) { continue; } + if (!strcmp(op->nbsp->type, "taas") || + !strcmp(op->nbsp->type, "mirror")) { + continue; + } if (lsp_is_enabled(op->nbsp)) { ovn_multicast_add(mcgroups, &mc_flood, op); @@ -3868,6 +4132,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, if (!op->nbsp) { continue; } + if (!strcmp(op->nbsp->type, "taas") || + !strcmp(op->nbsp->type, "mirror")) { + continue; + } for (size_t i = 0; i < op->nbsp->n_addresses; i++) { /* Addresses are owned by the logical port. @@ -4001,6 +4269,10 @@ build_lswitch_flows(struct hmap *datapaths, struct hmap *ports, if (!op->nbsp) { continue; } + if (!strcmp(op->nbsp->type, "taas") || + !strcmp(op->nbsp->type, "mirror")) { + continue; + } ds_clear(&match); ds_put_format(&match, "outport == %s", op->json_key); diff --git a/ovn/ovn-nb.xml b/ovn/ovn-nb.xml index 9869d7e..20593fa 100644 --- a/ovn/ovn-nb.xml +++ b/ovn/ovn-nb.xml @@ -301,6 +301,20 @@ <dd> A port to a logical switch on a VTEP gateway. </dd> + + <dt><code>mirror</code></dt> + <dd> + A port indicate the inport of mirrored flows. The user need to + create this port in the logical_switch. This port should one to + one correspondence with the the tap_flows + </dd> + + <dt><code>taas</code></dt> + <dd> + A port indicate the outport of mirrored flows. The user need to + set the type of tap_service port to taas when create a + taas_service. + </dd> </dl> </column> </group> @@ -454,6 +468,49 @@ interface, in bits. </column> </group> + + <group title="Options for mirror ports"> + <p> + These options apply when <ref column="type"/> is + <code>mirror</code>. + </p> + + <column name="options" key="source-port"> + Required. The <ref column="name"/> of the <ref + table="Logical_switch_Port"/> that indicates where the + cloned flows come from. + </column> + + <column name="options" key="taas-port"> + Required. The <ref column="name"/> of the <ref + table="Logical_switch_Port"/> with type taas. + </column> + + <column name="options" key="direction"> + <p> + This option indicates whitch direction(from-port/to-port/all) of + packet will be cloned to the taas-port. The directions are defined + as follow: + </p> + <dl> + <dt><code>from-port</code></dt> + <dd> + The packets from this port will be cloned to specified mirror + port. + </dd> + <dt><code>to-port</code></dt> + <dd> + The packets to this port will be cloned to specified mirror + port. + </dd> + <dt><code>both</code></dt> + <dd> + The packets both from and to this port will be cloned to + specified mirror port. + </dd> + </dl> + </column> + </group> </group> <group title="Containers"> -- 1.8.3.1 _______________________________________________ dev mailing list [email protected] https://mail.openvswitch.org/mailman/listinfo/ovs-dev
