Ejemplo n.º 1
0
static void
format_generic_odp_action(struct ds *ds, const struct nlattr *a)
{
    size_t len = nl_attr_get_size(a);

    ds_put_format(ds, "action%"PRId16, nl_attr_type(a));
    if (len) {
        const uint8_t *unspec;
        unsigned int i;

        unspec = nl_attr_get(a);
        for (i = 0; i < len; i++) {
            ds_put_char(ds, i ? ' ': '(');
            ds_put_format(ds, "%02x", unspec[i]);
        }
        ds_put_char(ds, ')');
    }
}
Ejemplo n.º 2
0
/* Tries to receive an openflow message from datapath 'dp_idx' on 'sock'.  If
 * successful, stores the received message into '*msgp' and returns 0.  The
 * caller is responsible for destroying the message with ofpbuf_delete().  On
 * failure, returns a positive errno value and stores a null pointer into
 * '*msgp'.
 *
 * Only Netlink messages with embedded OpenFlow messages are accepted.  Other
 * Netlink messages provoke errors.
 *
 * If 'wait' is true, dpif_recv_openflow waits for a message to be ready;
 * otherwise, returns EAGAIN if the 'sock' receive buffer is empty. */
int
dpif_recv_openflow(struct dpif *dp, int dp_idx, struct ofpbuf **bufferp,
                   bool wait)
{
    struct nlattr *attrs[ARRAY_SIZE(openflow_policy)];
    struct ofpbuf *buffer;
    struct ofp_header *oh;
    uint16_t ofp_len;

    buffer = *bufferp = NULL;
    do {
        int retval;

        do {
            ofpbuf_delete(buffer);
            retval = nl_sock_recv(dp->sock, &buffer, wait);
        } while (retval == ENOBUFS
                 || (!retval
                     && (nl_msg_nlmsghdr(buffer)->nlmsg_type == NLMSG_DONE
                         || nl_msg_nlmsgerr(buffer, NULL))));
        if (retval) {
            if (retval != EAGAIN) {
                VLOG_WARN_RL(&rl, "dpif_recv_openflow: %s", strerror(retval));
            }
            return retval;
        }

        if (nl_msg_genlmsghdr(buffer) == NULL) {
            VLOG_DBG_RL(&rl, "received packet too short for Generic Netlink");
            goto error;
        }
        if (nl_msg_nlmsghdr(buffer)->nlmsg_type != openflow_family) {
            VLOG_DBG_RL(&rl,
                        "received type (%"PRIu16") != openflow family (%d)",
                        nl_msg_nlmsghdr(buffer)->nlmsg_type, openflow_family);
            goto error;
        }

        if (!nl_policy_parse(buffer, NLMSG_HDRLEN + GENL_HDRLEN,
                             openflow_policy, attrs,
                             ARRAY_SIZE(openflow_policy))) {
            goto error;
        }
    } while (nl_attr_get_u32(attrs[DP_GENL_A_DP_IDX]) != dp_idx);

    oh = buffer->data = (void *) nl_attr_get(attrs[DP_GENL_A_OPENFLOW]);
    buffer->size = nl_attr_get_size(attrs[DP_GENL_A_OPENFLOW]);
    ofp_len = ntohs(oh->length);
    if (ofp_len != buffer->size) {
        VLOG_WARN_RL(&rl,
                     "ofp_header.length %"PRIu16" != attribute length %zu\n",
                     ofp_len, buffer->size);
        buffer->size = MIN(ofp_len, buffer->size);
    }
    *bufferp = buffer;
    return 0;

error:
    ofpbuf_delete(buffer);
    return EPROTO;
}
Ejemplo n.º 3
0
            }
            break;

        case OVS_SAMPLE_ATTR_ACTIONS:
            subactions = a;
            break;

        case OVS_SAMPLE_ATTR_UNSPEC:
        case __OVS_SAMPLE_ATTR_MAX:
        default:
            OVS_NOT_REACHED();
        }
    }

    odp_execute_actions__(dp, &packet, 1, steal, md, nl_attr_get(subactions),
                          nl_attr_get_size(subactions), dp_execute_action,
                          more_actions);
}

static void
odp_execute_actions__(void *dp, struct dpif_packet **packets, int cnt,
                      bool steal, struct pkt_metadata *md,
                      const struct nlattr *actions, size_t actions_len,
                      odp_execute_cb dp_execute_action, bool more_actions)
{
    const struct nlattr *a;
    unsigned int left;

    int i;

    NL_ATTR_FOR_EACH_UNSAFE (a, left, actions, actions_len) {
Ejemplo n.º 4
0
void
format_odp_action(struct ds *ds, const struct nlattr *a)
{
    const uint8_t *eth;
    ovs_be32 ip;

    if (nl_attr_get_size(a) != odp_action_len(nl_attr_type(a))) {
        ds_put_format(ds, "bad length %zu, expected %d for: ",
                      nl_attr_get_size(a), odp_action_len(nl_attr_type(a)));
        format_generic_odp_action(ds, a);
        return;
    }

    switch (nl_attr_type(a)) {
    case OVS_ACTION_ATTR_OUTPUT:
        ds_put_format(ds, "%"PRIu16, nl_attr_get_u32(a));
        break;
    case OVS_ACTION_ATTR_USERSPACE:
        ds_put_format(ds, "userspace(%"PRIu64")", nl_attr_get_u64(a));
        break;
    case OVS_ACTION_ATTR_SET_TUNNEL:
        ds_put_format(ds, "set_tunnel(%#"PRIx64")",
                      ntohll(nl_attr_get_be64(a)));
        break;
    case OVS_ACTION_ATTR_PUSH_VLAN:
        ds_put_format(ds, "push_vlan(vid=%"PRIu16",pcp=%d)",
                      vlan_tci_to_vid(nl_attr_get_be16(a)),
                      vlan_tci_to_pcp(nl_attr_get_be16(a)));
        break;
    case OVS_ACTION_ATTR_POP_VLAN:
        ds_put_format(ds, "pop_vlan");
        break;
    case OVS_ACTION_ATTR_SET_DL_SRC:
        eth = nl_attr_get_unspec(a, ETH_ADDR_LEN);
        ds_put_format(ds, "set_dl_src("ETH_ADDR_FMT")", ETH_ADDR_ARGS(eth));
        break;
    case OVS_ACTION_ATTR_SET_DL_DST:
        eth = nl_attr_get_unspec(a, ETH_ADDR_LEN);
        ds_put_format(ds, "set_dl_dst("ETH_ADDR_FMT")", ETH_ADDR_ARGS(eth));
        break;
    case OVS_ACTION_ATTR_SET_NW_SRC:
        ip = nl_attr_get_be32(a);
        ds_put_format(ds, "set_nw_src("IP_FMT")", IP_ARGS(&ip));
        break;
    case OVS_ACTION_ATTR_SET_NW_DST:
        ip = nl_attr_get_be32(a);
        ds_put_format(ds, "set_nw_dst("IP_FMT")", IP_ARGS(&ip));
        break;
    case OVS_ACTION_ATTR_SET_NW_TOS:
        ds_put_format(ds, "set_nw_tos(%"PRIu8")", nl_attr_get_u8(a));
        break;
    case OVS_ACTION_ATTR_SET_TP_SRC:
        ds_put_format(ds, "set_tp_src(%"PRIu16")", ntohs(nl_attr_get_be16(a)));
        break;
    case OVS_ACTION_ATTR_SET_TP_DST:
        ds_put_format(ds, "set_tp_dst(%"PRIu16")", ntohs(nl_attr_get_be16(a)));
        break;
    case OVS_ACTION_ATTR_SET_PRIORITY:
        ds_put_format(ds, "set_priority(%#"PRIx32")", nl_attr_get_u32(a));
        break;
    case OVS_ACTION_ATTR_POP_PRIORITY:
        ds_put_cstr(ds, "pop_priority");
        break;
    default:
        format_generic_odp_action(ds, a);
        break;
    }
}