- cls_rule_init_catchall(&rule, IBR_FROM_NEXT_HOP_ARP);
- cls_rule_set_dl_type(&rule, htons(ETH_TYPE_ARP));
- cls_rule_set_dl_src(&rule, remote_mac);
- cls_rule_set_nw_proto(&rule, ARP_OP_REQUEST);
- cb(ib, &rule);
- }
-
- for (i = 0; i < ib->n_remote_addrs; i++) {
- const struct sockaddr_in *a = &ib->remote_addrs[i];
-
- if (!i || a->sin_addr.s_addr != a[-1].sin_addr.s_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);
- cb(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);
- cb(ib, &rule);
- }
-
- if (!i
- || a->sin_addr.s_addr != a[-1].sin_addr.s_addr
- || a->sin_port != a[-1].sin_port) {
- /* (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);
- cb(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);
- cb(ib, &rule);
- }
- }
-}
-
-static void
-drop_rule(struct in_band *ib, const struct cls_rule *rule)
-{
- ofproto_delete_flow(ib->ofproto, rule);
-}
-
-/* Drops from the flow table all of the flows set up by 'ib', then clears out
- * the information about the installed flows so that they can be filled in
- * again if necessary. */
-static void
-drop_rules(struct in_band *ib)
-{
- /* Drop rules. */
- make_rules(ib, drop_rule);
-
- /* Clear out state. */
- memset(ib->installed_local_mac, 0, sizeof ib->installed_local_mac);
-
- free(ib->remote_addrs);
- ib->remote_addrs = NULL;
- ib->n_remote_addrs = 0;
-
- free(ib->remote_macs);
- ib->remote_macs = NULL;
- ib->n_remote_macs = 0;
-}
-
-static void
-add_rule(struct in_band *ib, const struct cls_rule *rule)
-{
- struct {
- struct nx_action_set_queue nxsq;
- union ofp_action oa;
- } actions;
-
- memset(&actions, 0, sizeof actions);
-
- actions.oa.output.type = htons(OFPAT_OUTPUT);
- actions.oa.output.len = htons(sizeof actions.oa);
- actions.oa.output.port = htons(OFPP_NORMAL);
- actions.oa.output.max_len = htons(0);
-
- if (ib->queue_id < 0) {
- ofproto_add_flow(ib->ofproto, rule, &actions.oa, 1);
- } else {
- actions.nxsq.type = htons(OFPAT_VENDOR);
- actions.nxsq.len = htons(sizeof actions.nxsq);
- actions.nxsq.vendor = htonl(NX_VENDOR_ID);
- actions.nxsq.subtype = htons(NXAST_SET_QUEUE);
- actions.nxsq.queue_id = htonl(ib->queue_id);
-
- ofproto_add_flow(ib->ofproto, rule, (union ofp_action *) &actions,
- sizeof actions / sizeof(union ofp_action));