@@ -145,8 +145,6 @@ static void update_mirror_stats(struct ofproto_dpif *ofproto,
145145 mirror_mask_t mirrors ,
146146 uint64_t packets , uint64_t bytes );
147147
148- /* A group of one or more OpenFlow ports. */
149- #define OFBUNDLE_FLOOD ((struct ofbundle *) 1)
150148struct ofbundle {
151149 struct ofproto_dpif * ofproto ; /* Owning ofproto. */
152150 struct hmap_node hmap_node ; /* In struct ofproto's "bundles" hmap. */
@@ -178,6 +176,8 @@ static void bundle_destroy(struct ofbundle *);
178176static void bundle_del_port (struct ofport_dpif * );
179177static void bundle_run (struct ofbundle * );
180178static void bundle_wait (struct ofbundle * );
179+ static struct ofport_dpif * lookup_input_bundle (struct ofproto_dpif * ,
180+ uint16_t in_port , bool warn );
181181
182182static void stp_run (struct ofproto_dpif * ofproto );
183183static void stp_wait (struct ofproto_dpif * ofproto );
@@ -559,6 +559,8 @@ static int send_packet(const struct ofport_dpif *, struct ofpbuf *packet);
559559static size_t
560560compose_sflow_action (const struct ofproto_dpif * , struct ofpbuf * odp_actions ,
561561 const struct flow * , uint32_t odp_port );
562+ static void add_mirror_actions (struct action_xlate_ctx * ctx ,
563+ const struct flow * flow );
562564/* Global variables. */
563565static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT (1 , 5 );
564566
@@ -4723,6 +4725,8 @@ static struct ofpbuf *
47234725xlate_actions (struct action_xlate_ctx * ctx ,
47244726 const union ofp_action * in , size_t n_in )
47254727{
4728+ struct flow orig_flow = ctx -> flow ;
4729+
47264730 COVERAGE_INC (ofproto_dpif_xlate );
47274731
47284732 ctx -> odp_actions = ofpbuf_new (512 );
@@ -4775,6 +4779,7 @@ xlate_actions(struct action_xlate_ctx *ctx,
47754779 compose_output_action (ctx , OFPP_LOCAL );
47764780 }
47774781 }
4782+ add_mirror_actions (ctx , & orig_flow );
47784783 fix_sflow_action (ctx );
47794784 }
47804785
@@ -4951,34 +4956,6 @@ ofbundle_get_a_port(const struct ofbundle *bundle)
49514956 struct ofport_dpif , bundle_node );
49524957}
49534958
4954- static mirror_mask_t
4955- compose_dsts (struct action_xlate_ctx * ctx , uint16_t vlan ,
4956- const struct ofbundle * in_bundle ,
4957- const struct ofbundle * out_bundle )
4958- {
4959- mirror_mask_t dst_mirrors = 0 ;
4960-
4961- if (out_bundle == OFBUNDLE_FLOOD ) {
4962- struct ofbundle * bundle ;
4963-
4964- HMAP_FOR_EACH (bundle , hmap_node , & ctx -> ofproto -> bundles ) {
4965- if (bundle != in_bundle
4966- && ofbundle_includes_vlan (bundle , vlan )
4967- && bundle -> floodable
4968- && !bundle -> mirror_out ) {
4969- output_normal (ctx , bundle , vlan );
4970- dst_mirrors |= bundle -> dst_mirrors ;
4971- }
4972- }
4973- ctx -> nf_output_iface = NF_OUT_FLOOD ;
4974- } else if (out_bundle ) {
4975- output_normal (ctx , out_bundle , vlan );
4976- dst_mirrors = out_bundle -> dst_mirrors ;
4977- }
4978-
4979- return dst_mirrors ;
4980- }
4981-
49824959static bool
49834960vlan_is_mirrored (const struct ofmirror * m , int vlan )
49844961{
@@ -5027,18 +5004,68 @@ eth_dst_may_rspan(const uint8_t dst[ETH_ADDR_LEN])
50275004}
50285005
50295006static void
5030- output_mirrors (struct action_xlate_ctx * ctx ,
5031- uint16_t vlan , const struct ofbundle * in_bundle ,
5032- mirror_mask_t dst_mirrors )
5007+ add_mirror_actions (struct action_xlate_ctx * ctx , const struct flow * orig_flow )
50335008{
50345009 struct ofproto_dpif * ofproto = ctx -> ofproto ;
50355010 mirror_mask_t mirrors ;
5011+ struct ofport_dpif * in_port ;
5012+ struct ofbundle * in_bundle ;
5013+ uint16_t vlan ;
5014+ uint16_t vid ;
5015+ const struct nlattr * a ;
5016+ size_t left ;
5017+
5018+ /* Obtain in_port from orig_flow.in_port.
5019+ *
5020+ * lookup_input_bundle() also ensures that in_port belongs to a bundle. */
5021+ in_port = lookup_input_bundle (ctx -> ofproto , orig_flow -> in_port ,
5022+ ctx -> packet != NULL );
5023+ if (!in_port ) {
5024+ return ;
5025+ }
5026+ in_bundle = in_port -> bundle ;
5027+ mirrors = in_bundle -> src_mirrors ;
5028+
5029+ /* Drop frames on bundles reserved for mirroring. */
5030+ if (in_bundle -> mirror_out ) {
5031+ if (ctx -> packet != NULL ) {
5032+ static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT (1 , 5 );
5033+ VLOG_WARN_RL (& rl , "bridge %s: dropping packet received on port "
5034+ "%s, which is reserved exclusively for mirroring" ,
5035+ ctx -> ofproto -> up .name , in_bundle -> name );
5036+ }
5037+ return ;
5038+ }
5039+
5040+ /* Check VLAN. */
5041+ vid = vlan_tci_to_vid (orig_flow -> vlan_tci );
5042+ if (!input_vid_is_valid (vid , in_bundle , ctx -> packet != NULL )) {
5043+ return ;
5044+ }
5045+ vlan = input_vid_to_vlan (in_bundle , vid );
5046+
5047+ /* Look at the output ports to check for destination selections. */
5048+
5049+ NL_ATTR_FOR_EACH (a , left , ctx -> odp_actions -> data ,
5050+ ctx -> odp_actions -> size ) {
5051+ enum ovs_action_attr type = nl_attr_type (a );
5052+ struct ofport_dpif * ofport ;
5053+
5054+ if (type != OVS_ACTION_ATTR_OUTPUT ) {
5055+ continue ;
5056+ }
5057+
5058+ ofport = get_odp_port (ofproto , nl_attr_get_u32 (a ));
5059+ mirrors |= ofport ? ofport -> bundle -> dst_mirrors : 0 ;
5060+ }
50365061
5037- mirrors = in_bundle -> src_mirrors | dst_mirrors ;
50385062 if (!mirrors ) {
50395063 return ;
50405064 }
50415065
5066+ /* Restore the original packet before adding the mirror actions. */
5067+ ctx -> flow = * orig_flow ;
5068+
50425069 while (mirrors ) {
50435070 struct ofmirror * m ;
50445071
@@ -5053,7 +5080,7 @@ output_mirrors(struct action_xlate_ctx *ctx,
50535080 ctx -> mirrors |= m -> dup_mirrors ;
50545081 if (m -> out ) {
50555082 output_normal (ctx , m -> out , vlan );
5056- } else if (eth_dst_may_rspan (ctx -> flow . dl_dst )
5083+ } else if (eth_dst_may_rspan (orig_flow -> dl_dst )
50575084 && vlan != m -> out_vlan ) {
50585085 struct ofbundle * bundle ;
50595086
@@ -5229,10 +5256,8 @@ is_admissible(struct ofproto_dpif *ofproto, const struct flow *flow,
52295256static void
52305257xlate_normal (struct action_xlate_ctx * ctx )
52315258{
5232- mirror_mask_t dst_mirrors = 0 ;
52335259 struct ofport_dpif * in_port ;
52345260 struct ofbundle * in_bundle ;
5235- struct ofbundle * out_bundle ;
52365261 struct mac_entry * mac ;
52375262 uint16_t vlan ;
52385263 uint16_t vid ;
@@ -5281,7 +5306,6 @@ xlate_normal(struct action_xlate_ctx *ctx)
52815306
52825307 /* Check other admissibility requirements. */
52835308 if (!is_admissible (ctx -> ofproto , & ctx -> flow , in_port , vlan , & ctx -> tags )) {
5284- output_mirrors (ctx , vlan , in_bundle , 0 );
52855309 return ;
52865310 }
52875311
@@ -5294,7 +5318,9 @@ xlate_normal(struct action_xlate_ctx *ctx)
52945318 mac = mac_learning_lookup (ctx -> ofproto -> ml , ctx -> flow .dl_dst , vlan ,
52955319 & ctx -> tags );
52965320 if (mac ) {
5297- out_bundle = mac -> port .p ;
5321+ if (mac -> port .p != in_bundle ) {
5322+ output_normal (ctx , mac -> port .p , vlan );
5323+ }
52985324 } else if (!ctx -> packet && !eth_addr_is_multicast (ctx -> flow .dl_dst )) {
52995325 /* If we are revalidating but don't have a learning entry then eject
53005326 * the flow. Installing a flow that floods packets opens up a window
@@ -5304,14 +5330,18 @@ xlate_normal(struct action_xlate_ctx *ctx)
53045330 ctx -> may_set_up_flow = false;
53055331 return ;
53065332 } else {
5307- out_bundle = OFBUNDLE_FLOOD ;
5308- }
5333+ struct ofbundle * bundle ;
53095334
5310- /* Don't send packets out their input bundles. */
5311- if (in_bundle != out_bundle ) {
5312- dst_mirrors = compose_dsts (ctx , vlan , in_bundle , out_bundle );
5335+ HMAP_FOR_EACH (bundle , hmap_node , & ctx -> ofproto -> bundles ) {
5336+ if (bundle != in_bundle
5337+ && ofbundle_includes_vlan (bundle , vlan )
5338+ && bundle -> floodable
5339+ && !bundle -> mirror_out ) {
5340+ output_normal (ctx , bundle , vlan );
5341+ }
5342+ }
5343+ ctx -> nf_output_iface = NF_OUT_FLOOD ;
53135344 }
5314- output_mirrors (ctx , vlan , in_bundle , dst_mirrors );
53155345}
53165346
53175347/* Optimized flow revalidation.
0 commit comments