X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Fnetlink.c;h=ec358495946b5364380236ea6566661a3ff8d6d3;hb=ee9bed06cd2794ced29190b6c6539993159d76f5;hp=39d703aed6bbb399287383eae04d3510ab5eca1b;hpb=2fe27d5ad27f3c7879ea696209bcf9702d9b7109;p=sliver-openvswitch.git diff --git a/lib/netlink.c b/lib/netlink.c index 39d703aed..ec3584959 100644 --- a/lib/netlink.c +++ b/lib/netlink.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ #include "netlink-protocol.h" #include "ofpbuf.h" #include "timeval.h" +#include "unaligned.h" #include "vlog.h" VLOG_DEFINE_THIS_MODULE(netlink); @@ -243,30 +244,54 @@ nl_msg_put_u8(struct ofpbuf *msg, uint16_t type, uint8_t value) nl_msg_put_unspec(msg, type, &value, sizeof value); } -/* Appends a Netlink attribute of the given 'type' and the given 16-bit 'value' - * to 'msg'. */ +/* Appends a Netlink attribute of the given 'type' and the given 16-bit host + * byte order 'value' to 'msg'. */ void nl_msg_put_u16(struct ofpbuf *msg, uint16_t type, uint16_t value) { nl_msg_put_unspec(msg, type, &value, sizeof value); } -/* Appends a Netlink attribute of the given 'type' and the given 32-bit 'value' - * to 'msg'. */ +/* Appends a Netlink attribute of the given 'type' and the given 32-bit host + * byte order 'value' to 'msg'. */ void nl_msg_put_u32(struct ofpbuf *msg, uint16_t type, uint32_t value) { nl_msg_put_unspec(msg, type, &value, sizeof value); } -/* Appends a Netlink attribute of the given 'type' and the given 64-bit 'value' - * to 'msg'. */ +/* Appends a Netlink attribute of the given 'type' and the given 64-bit host + * byte order 'value' to 'msg'. */ void nl_msg_put_u64(struct ofpbuf *msg, uint16_t type, uint64_t value) { nl_msg_put_unspec(msg, type, &value, sizeof value); } +/* Appends a Netlink attribute of the given 'type' and the given 16-bit network + * byte order 'value' to 'msg'. */ +void +nl_msg_put_be16(struct ofpbuf *msg, uint16_t type, ovs_be16 value) +{ + nl_msg_put_unspec(msg, type, &value, sizeof value); +} + +/* Appends a Netlink attribute of the given 'type' and the given 32-bit network + * byte order 'value' to 'msg'. */ +void +nl_msg_put_be32(struct ofpbuf *msg, uint16_t type, ovs_be32 value) +{ + nl_msg_put_unspec(msg, type, &value, sizeof value); +} + +/* Appends a Netlink attribute of the given 'type' and the given 64-bit network + * byte order 'value' to 'msg'. */ +void +nl_msg_put_be64(struct ofpbuf *msg, uint16_t type, ovs_be64 value) +{ + nl_msg_put_unspec(msg, type, &value, sizeof value); +} + /* Appends a Netlink attribute of the given 'type' and the given * null-terminated string 'value' to 'msg'. */ void @@ -334,6 +359,14 @@ nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg) /* Attributes. */ +/* Returns the bits of 'nla->nla_type' that are significant for determining its + * type. */ +int +nl_attr_type(const struct nlattr *nla) +{ + return nla->nla_type & NLA_TYPE_MASK; +} + /* Returns the first byte in the payload of attribute 'nla'. */ const void * nl_attr_get(const struct nlattr *nla) @@ -379,7 +412,7 @@ nl_attr_get_u8(const struct nlattr *nla) return NL_ATTR_GET_AS(nla, uint8_t); } -/* Returns the 16-bit value in 'nla''s payload. +/* Returns the 16-bit host byte order value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 2 bytes long. */ uint16_t @@ -388,7 +421,7 @@ nl_attr_get_u16(const struct nlattr *nla) return NL_ATTR_GET_AS(nla, uint16_t); } -/* Returns the 32-bit value in 'nla''s payload. +/* Returns the 32-bit host byte order value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 4 bytes long. */ uint32_t @@ -397,13 +430,42 @@ nl_attr_get_u32(const struct nlattr *nla) return NL_ATTR_GET_AS(nla, uint32_t); } -/* Returns the 64-bit value in 'nla''s payload. +/* Returns the 64-bit host byte order value in 'nla''s payload. * * Asserts that 'nla''s payload is at least 8 bytes long. */ uint64_t nl_attr_get_u64(const struct nlattr *nla) { - return NL_ATTR_GET_AS(nla, uint64_t); + const ovs_32aligned_u64 *x = nl_attr_get_unspec(nla, sizeof *x); + return get_32aligned_u64(x); +} + +/* Returns the 16-bit network byte order value in 'nla''s payload. + * + * Asserts that 'nla''s payload is at least 2 bytes long. */ +ovs_be16 +nl_attr_get_be16(const struct nlattr *nla) +{ + return NL_ATTR_GET_AS(nla, ovs_be16); +} + +/* Returns the 32-bit network byte order value in 'nla''s payload. + * + * Asserts that 'nla''s payload is at least 4 bytes long. */ +ovs_be32 +nl_attr_get_be32(const struct nlattr *nla) +{ + return NL_ATTR_GET_AS(nla, ovs_be32); +} + +/* Returns the 64-bit network byte order value in 'nla''s payload. + * + * Asserts that 'nla''s payload is at least 8 bytes long. */ +ovs_be64 +nl_attr_get_be64(const struct nlattr *nla) +{ + const ovs_32aligned_be64 *x = nl_attr_get_unspec(nla, sizeof *x); + return get_32aligned_be64(x); } /* Returns the null-terminated string value in 'nla''s payload. @@ -488,12 +550,12 @@ nl_policy_parse(const struct ofpbuf *msg, size_t nla_offset, if (aligned_len > (char*)tail - (char*)p) { VLOG_DBG_RL(&rl, "%zu: attr %"PRIu16" aligned data len (%zu) " "> bytes left (%tu)", - offset, nla->nla_type, aligned_len, + offset, nl_attr_type(nla), aligned_len, (char*)tail - (char*)p); return false; } - type = nla->nla_type; + type = nl_attr_type(nla); if (type < n_attrs && policy[type].type != NL_A_NO_ATTR) { const struct nl_policy *e = &policy[type]; size_t min_len, max_len; @@ -523,6 +585,9 @@ nl_policy_parse(const struct ofpbuf *msg, size_t nla_offset, assert(n_required > 0); --n_required; } + if (attrs[type]) { + VLOG_DBG_RL(&rl, "%zu: duplicate attr %"PRIu16, offset, type); + } attrs[type] = nla; } else { /* Skip attribute type that we don't care about. */ @@ -549,3 +614,39 @@ nl_parse_nested(const struct nlattr *nla, const struct nl_policy policy[], nl_attr_get_nested(nla, &buf); return nl_policy_parse(&buf, 0, policy, attrs, n_attrs); } + +static const struct nlattr * +nl_attr_find__(const struct nlattr *attrs, size_t size, uint16_t type) +{ + const struct nlattr *nla; + size_t left; + + NL_ATTR_FOR_EACH (nla, left, attrs, size) { + if (nl_attr_type (nla) == type) { + return nla; + } + } + return NULL; +} + +/* Returns the first Netlink attribute within 'buf' with the specified 'type', + * skipping a header of 'hdr_len' bytes at the beginning of 'buf'. + * + * This function does not validate the attribute's length. */ +const struct nlattr * +nl_attr_find(const struct ofpbuf *buf, size_t hdr_len, uint16_t type) +{ + const uint8_t *start = (const uint8_t *) buf->data + hdr_len; + return nl_attr_find__((const struct nlattr *) start, buf->size - hdr_len, + type); +} + +/* Returns the first Netlink attribute within 'nla' with the specified + * 'type'. + * + * This function does not validate the attribute's length. */ +const struct nlattr * +nl_attr_find_nested(const struct nlattr *nla, uint16_t type) +{ + return nl_attr_find__(nl_attr_get(nla), nl_attr_get_size(nla), type); +}