- if (controller_ip) {
- /* Allow ARP replies to the controller's IP. */
- memset(&flow, 0, sizeof flow);
- flow.dl_type = htons(ETH_TYPE_ARP);
- flow.nw_proto = ARP_OP_REPLY;
- flow.nw_dst = controller_ip;
- setup_flow(in_band, IBR_TO_CTL_ARP, &flow,
- (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_DST_MASK),
- OFPP_NORMAL);
-
- /* Allow ARP requests from the controller's IP. */
- memset(&flow, 0, sizeof flow);
- flow.dl_type = htons(ETH_TYPE_ARP);
- flow.nw_proto = ARP_OP_REQUEST;
- flow.nw_src = controller_ip;
- setup_flow(in_band, IBR_FROM_CTL_ARP, &flow,
- (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK),
- 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);
- flow.nw_proto = IP_TYPE_TCP;
- flow.nw_src = controller_ip;
- flow.nw_dst = controller_ip;
- flow.tp_src = htons(OFP_TCP_PORT);
- flow.tp_dst = htons(OFP_TCP_PORT);
- setup_flow(in_band, IBR_TO_CTL_OFP, &flow,
- (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_DST_MASK
- | OFPFW_TP_DST), OFPP_NORMAL);
- setup_flow(in_band, IBR_FROM_CTL_OFP, &flow,
- (OFPFW_DL_TYPE | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK
- | OFPFW_TP_SRC), OFPP_NORMAL);
- } else {
- drop_flow(in_band, IBR_TO_CTL_ARP);
- drop_flow(in_band, IBR_FROM_CTL_ARP);
- drop_flow(in_band, IBR_TO_CTL_OFP);
- drop_flow(in_band, IBR_FROM_CTL_OFP);
+ 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);