- if (controller_mac) {
- /* Switch ARP requests sent by the controller. (OFPP_NORMAL will "do
- * the right thing" regarding VLANs here.) */
- memset(&flow, 0, sizeof flow);
- flow.dl_type = htons(ETH_TYPE_ARP);
- memcpy(flow.dl_dst, eth_addr_broadcast, ETH_ADDR_LEN);
- memcpy(flow.dl_src, controller_mac, ETH_ADDR_LEN);
- setup_flow(in_band, IBR_ARP_FROM_CTL, &flow,
- OFPFW_DL_TYPE | OFPFW_DL_DST | OFPFW_DL_SRC,
- OFPP_NORMAL);
-
- /* OpenFlow traffic to or from the controller.
- *
- * (A given field's value is completely ignored if it is wildcarded,
- * which is why we can get away with using a single 'flow' in each
- * case here.) */
- memset(&flow, 0, sizeof flow);
- flow.dl_type = htons(ETH_TYPE_IP);
- memcpy(flow.dl_src, controller_mac, ETH_ADDR_LEN);
- memcpy(flow.dl_dst, controller_mac, ETH_ADDR_LEN);
- flow.nw_proto = IP_TYPE_TCP;
- flow.tp_src = htons(OFP_TCP_PORT);
- flow.tp_dst = htons(OFP_TCP_PORT);
- setup_flow(in_band, IBR_TO_CTL_OFP_SRC, &flow,
- (OFPFW_DL_TYPE | OFPFW_DL_DST | OFPFW_NW_PROTO
- | OFPFW_TP_SRC), OFPP_NORMAL);
- setup_flow(in_band, IBR_TO_CTL_OFP_DST, &flow,
- (OFPFW_DL_TYPE | OFPFW_DL_DST | OFPFW_NW_PROTO
- | OFPFW_TP_DST), OFPP_NORMAL);
- setup_flow(in_band, IBR_FROM_CTL_OFP_SRC, &flow,
- (OFPFW_DL_TYPE | OFPFW_DL_SRC | OFPFW_NW_PROTO
- | OFPFW_TP_SRC), OFPP_NORMAL);
- setup_flow(in_band, IBR_FROM_CTL_OFP_DST, &flow,
- (OFPFW_DL_TYPE | OFPFW_DL_SRC | OFPFW_NW_PROTO
- | OFPFW_TP_DST), OFPP_NORMAL);
- } else {
- drop_flow(in_band, IBR_ARP_FROM_CTL);
- drop_flow(in_band, IBR_TO_CTL_OFP_DST);
- drop_flow(in_band, IBR_TO_CTL_OFP_SRC);
- drop_flow(in_band, IBR_FROM_CTL_OFP_DST);
- drop_flow(in_band, IBR_FROM_CTL_OFP_SRC);
+ for (r = ib->remotes; r < &ib->remotes[ib->n_remotes]; r++) {
+ const struct sockaddr_in *a = &r->remote_addr;
+
+ /* (f) Allow ARP replies containing the remote's IP address as a
+ * target. */
+ cls_rule_init_catchall(&rule, IBR_TO_REMOTE_ARP);
+ cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
+ cls_rule_set_nw_proto(&rule, ARP_OP_REPLY);
+ cls_rule_set_nw_dst(&rule, a->sin_addr.s_addr);
+ add_rule(ib, &rule);
+
+ /* (g) Allow ARP requests containing the remote's IP address as a
+ * source. */
+ cls_rule_init_catchall(&rule, IBR_FROM_REMOTE_ARP);
+ cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
+ cls_rule_set_nw_proto(&rule, ARP_OP_REQUEST);
+ cls_rule_set_nw_src(&rule, a->sin_addr.s_addr);
+ add_rule(ib, &rule);
+
+ /* (h) Allow TCP traffic to the remote's IP and port. */
+ cls_rule_init_catchall(&rule, IBR_TO_REMOTE_TCP);
+ cls_rule_set_dl_type(&rule, htons(ETH_TYPE_IP));
+ cls_rule_set_nw_proto(&rule, IPPROTO_TCP);
+ cls_rule_set_nw_dst(&rule, a->sin_addr.s_addr);
+ cls_rule_set_tp_dst(&rule, a->sin_port);
+ add_rule(ib, &rule);
+
+ /* (i) Allow TCP traffic from the remote's IP and port. */
+ cls_rule_init_catchall(&rule, IBR_FROM_REMOTE_TCP);
+ cls_rule_set_dl_type(&rule, htons(ETH_TYPE_IP));
+ cls_rule_set_nw_proto(&rule, IPPROTO_TCP);
+ cls_rule_set_nw_src(&rule, a->sin_addr.s_addr);
+ cls_rule_set_tp_src(&rule, a->sin_port);
+ add_rule(ib, &rule);