- 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);
+ init_rule(&rule, IBR_TO_CTL_ARP);
+ set_dl_type(&rule, ETH_TYPE_ARP);
+ set_nw_proto(&rule, ARP_OP_REPLY);
+ set_nw_dst(&rule, remote_ip);
+ cb(ib, &rule);
+
+ /* Allow ARP requests from the controller's IP. */
+ init_rule(&rule, IBR_FROM_CTL_ARP);
+ set_dl_type(&rule, ETH_TYPE_ARP);
+ set_nw_proto(&rule, ARP_OP_REQUEST);
+ set_nw_src(&rule, remote_ip);
+ cb(ib, &rule);
+
+ /* OpenFlow traffic to the controller. */
+ init_rule(&rule, IBR_TO_CTL_OFP);
+ set_dl_type(&rule, ETH_TYPE_IP);
+ set_nw_proto(&rule, IP_TYPE_TCP);
+ set_nw_dst(&rule, remote_ip);
+ set_tp_dst(&rule, OFP_TCP_PORT);
+ cb(ib, &rule);
+
+ /* OpenFlow traffic from the controller. */
+ init_rule(&rule, IBR_FROM_CTL_OFP);
+ set_dl_type(&rule, ETH_TYPE_IP);
+ set_nw_proto(&rule, IP_TYPE_TCP);
+ set_nw_src(&rule, remote_ip);
+ set_tp_src(&rule, OFP_TCP_PORT);
+ cb(ib, &rule);
+ }
+}
+
+static void
+clear_rules(struct in_band *ib)
+{
+ memset(ib->installed_local_mac, 0, sizeof ib->installed_local_mac);
+
+ free(ib->remote_ips);
+ ib->remote_ips = NULL;
+ ib->n_remote_ips = 0;
+
+ free(ib->remote_macs);
+ ib->remote_macs = NULL;
+ ib->n_remote_macs = 0;
+}
+
+static void
+drop_rule(struct in_band *ib, const struct in_band_rule *rule)
+{
+ ofproto_delete_flow(ib->ofproto, &rule->flow,
+ rule->wildcards, rule->priority);
+}
+
+static void
+drop_rules(struct in_band *ib)
+{
+ make_rules(ib, drop_rule);
+ clear_rules(ib);
+}
+
+static void
+add_rule(struct in_band *ib, const struct in_band_rule *rule)
+{
+ union ofp_action action;
+
+ action.type = htons(OFPAT_OUTPUT);
+ action.output.len = htons(sizeof action);
+ action.output.port = htons(OFPP_NORMAL);
+ action.output.max_len = htons(0);
+ ofproto_add_flow(ib->ofproto, &rule->flow, rule->wildcards,
+ rule->priority, &action, 1, 0);
+}
+
+static void
+add_rules(struct in_band *ib)
+{
+ make_rules(ib, add_rule);
+}
+
+static int
+compare_ips(const void *a, const void *b)
+{
+ return memcmp(a, b, sizeof(uint32_t));
+}
+
+static int
+compare_macs(const void *a, const void *b)
+{
+ return memcmp(a, b, ETH_ADDR_LEN);
+}
+
+void
+in_band_run(struct in_band *ib)
+{
+ struct in_band_remote *r;
+ bool local_change, remote_change;
+
+ local_change = refresh_local(ib);
+ remote_change = refresh_remotes(ib);
+ if (!local_change && !remote_change) {
+ /* Nothing changed, nothing to do. */
+ return;
+ }
+
+ /* Drop old rules. */
+ drop_rules(ib);
+
+ /* Figure out new rules. */
+ memcpy(ib->installed_local_mac, ib->local_mac, ETH_ADDR_LEN);
+ ib->remote_ips = xmalloc(ib->n_remotes * sizeof *ib->remote_ips);
+ ib->n_remote_ips = 0;
+ ib->remote_macs = xmalloc(ib->n_remotes * ETH_ADDR_LEN);
+ ib->n_remote_macs = 0;
+ for (r = ib->remotes; r < &ib->remotes[ib->n_remotes]; r++) {
+ if (r->remote_ip) {
+ ib->remote_ips[ib->n_remote_ips++] = r->remote_ip;
+ }
+ if (!eth_addr_is_zero(r->remote_mac)) {
+ memcpy(&ib->remote_macs[ib->n_remote_macs * ETH_ADDR_LEN],
+ r->remote_mac, ETH_ADDR_LEN);
+ ib->n_remote_macs++;
+ }