X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=lib%2Fnetlink.h;h=b931a412f6ce3293bc30ba74dae50d665480bf7a;hb=HEAD;hp=b1bf5858b530ab9763069de6bf43b46355715950;hpb=18c58479a14f760fb03c2062f9a35961fc74ebb5;p=cascardo%2Fovs.git diff --git a/lib/netlink.h b/lib/netlink.h index b1bf5858b..b931a412f 100644 --- a/lib/netlink.h +++ b/lib/netlink.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. + * Copyright (c) 2008, 2009, 2010, 2011, 2013, 2015 Nicira, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -31,6 +31,7 @@ * Linux-specific definitions for Netlink sockets, see netlink-socket.h. */ +#include #include #include #include @@ -46,7 +47,7 @@ struct genlmsghdr *nl_msg_genlmsghdr(const struct ofpbuf *); bool nl_msg_nlmsgerr(const struct ofpbuf *, int *error); void nl_msg_reserve(struct ofpbuf *, size_t); -/* Appending headers and raw data. */ +/* Appending and prepending headers and raw data. */ void nl_msg_put_nlmsghdr(struct ofpbuf *, size_t expected_payload, uint32_t type, uint32_t flags); void nl_msg_put_genlmsghdr(struct ofpbuf *, size_t expected_payload, @@ -54,9 +55,12 @@ void nl_msg_put_genlmsghdr(struct ofpbuf *, size_t expected_payload, uint8_t cmd, uint8_t version); void nl_msg_put(struct ofpbuf *, const void *, size_t); void *nl_msg_put_uninit(struct ofpbuf *, size_t); +void nl_msg_push(struct ofpbuf *, const void *, size_t); +void *nl_msg_push_uninit(struct ofpbuf *, size_t); /* Appending attributes. */ void *nl_msg_put_unspec_uninit(struct ofpbuf *, uint16_t type, size_t); +void *nl_msg_put_unspec_zero(struct ofpbuf *, uint16_t type, size_t); void nl_msg_put_unspec(struct ofpbuf *, uint16_t type, const void *, size_t); void nl_msg_put_flag(struct ofpbuf *, uint16_t type); void nl_msg_put_u8(struct ofpbuf *, uint16_t type, uint8_t value); @@ -66,6 +70,11 @@ void nl_msg_put_u64(struct ofpbuf *, uint16_t type, uint64_t value); void nl_msg_put_be16(struct ofpbuf *, uint16_t type, ovs_be16 value); void nl_msg_put_be32(struct ofpbuf *, uint16_t type, ovs_be32 value); void nl_msg_put_be64(struct ofpbuf *, uint16_t type, ovs_be64 value); +void nl_msg_put_in6_addr(struct ofpbuf *msg, uint16_t type, + const struct in6_addr *value); +void nl_msg_put_odp_port(struct ofpbuf *, uint16_t type, odp_port_t value); +void nl_msg_put_string__(struct ofpbuf *, uint16_t type, const char *value, + size_t len); void nl_msg_put_string(struct ofpbuf *, uint16_t type, const char *value); size_t nl_msg_start_nested(struct ofpbuf *, uint16_t type); @@ -73,8 +82,43 @@ void nl_msg_end_nested(struct ofpbuf *, size_t offset); void nl_msg_put_nested(struct ofpbuf *, uint16_t type, const void *data, size_t size); +/* Prepending attributes. */ +void *nl_msg_push_unspec_uninit(struct ofpbuf *, uint16_t type, size_t); +void nl_msg_push_unspec(struct ofpbuf *, uint16_t type, const void *, size_t); +void nl_msg_push_flag(struct ofpbuf *, uint16_t type); +void nl_msg_push_u8(struct ofpbuf *, uint16_t type, uint8_t value); +void nl_msg_push_u16(struct ofpbuf *, uint16_t type, uint16_t value); +void nl_msg_push_u32(struct ofpbuf *, uint16_t type, uint32_t value); +void nl_msg_push_u64(struct ofpbuf *, uint16_t type, uint64_t value); +void nl_msg_push_be16(struct ofpbuf *, uint16_t type, ovs_be16 value); +void nl_msg_push_be32(struct ofpbuf *, uint16_t type, ovs_be32 value); +void nl_msg_push_be64(struct ofpbuf *, uint16_t type, ovs_be64 value); +void nl_msg_push_string(struct ofpbuf *, uint16_t type, const char *value); + /* Separating buffers into individual messages. */ struct nlmsghdr *nl_msg_next(struct ofpbuf *buffer, struct ofpbuf *msg); + +/* Sizes of various attribute types, in bytes, including the attribute header + * and padding. + * + * A minimum-size attribute is 4 bytes long: 4 bytes of header, no bytes of + * payload, no padding. + * + * A maximum-size attribute is 65536 bytes long: 4 bytes of header, 65531 bytes + * of payload, 1 byte of padding. (Thus, NL_ATTR_SIZE() of a maximum length + * attribute payload does not fit in 16 bits.) */ +#define NL_ATTR_SIZE(PAYLOAD_SIZE) (NLA_HDRLEN + NLA_ALIGN(PAYLOAD_SIZE)) +#define NL_A_U8_SIZE NL_ATTR_SIZE(sizeof(uint8_t)) +#define NL_A_U16_SIZE NL_ATTR_SIZE(sizeof(uint16_t)) +#define NL_A_U32_SIZE NL_ATTR_SIZE(sizeof(uint32_t)) +#define NL_A_U64_SIZE NL_ATTR_SIZE(sizeof(uint64_t)) +#define NL_A_BE16_SIZE NL_ATTR_SIZE(sizeof(ovs_be16)) +#define NL_A_BE32_SIZE NL_ATTR_SIZE(sizeof(ovs_be32)) +#define NL_A_BE64_SIZE NL_ATTR_SIZE(sizeof(ovs_be64)) +#define NL_A_FLAG_SIZE NL_ATTR_SIZE(0) +#define NL_A_IPV6_SIZE NL_ATTR_SIZE(sizeof(struct in6_addr)) + +bool nl_attr_oversized(size_t payload_size); /* Netlink attribute types. */ enum nl_attr_type @@ -90,6 +134,7 @@ enum nl_attr_type NL_A_BE64 = NL_A_U64, NL_A_STRING, NL_A_FLAG, + NL_A_IPV6, NL_A_NESTED, N_NL_ATTR_TYPES }; @@ -98,7 +143,7 @@ enum nl_attr_type static inline struct nlattr * nl_attr_next(const struct nlattr *nla) { - return (struct nlattr *) ((uint8_t *) nla + NLA_ALIGN(nla->nla_len)); + return (void *) ((uint8_t *) nla + NLA_ALIGN(nla->nla_len)); } static inline bool @@ -106,14 +151,22 @@ nl_attr_is_valid(const struct nlattr *nla, size_t maxlen) { return (maxlen >= sizeof *nla && nla->nla_len >= sizeof *nla - && NLA_ALIGN(nla->nla_len) <= maxlen); + && nla->nla_len <= maxlen); +} + +static inline size_t +nl_attr_len_pad(const struct nlattr *nla, size_t maxlen) +{ + size_t len = NLA_ALIGN(nla->nla_len); + + return len <= maxlen ? len : nla->nla_len; } /* This macro is careful to check for attributes with bad lengths. */ #define NL_ATTR_FOR_EACH(ITER, LEFT, ATTRS, ATTRS_LEN) \ for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ nl_attr_is_valid(ITER, LEFT); \ - (LEFT) -= NLA_ALIGN((ITER)->nla_len), (ITER) = nl_attr_next(ITER)) + (LEFT) -= nl_attr_len_pad(ITER, LEFT), (ITER) = nl_attr_next(ITER)) /* This macro does not check for attributes with bad lengths. It should only @@ -122,7 +175,13 @@ nl_attr_is_valid(const struct nlattr *nla, size_t maxlen) #define NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, ATTRS, ATTRS_LEN) \ for ((ITER) = (ATTRS), (LEFT) = (ATTRS_LEN); \ (LEFT) > 0; \ - (LEFT) -= NLA_ALIGN((ITER)->nla_len), (ITER) = nl_attr_next(ITER)) + (LEFT) -= nl_attr_len_pad(ITER, LEFT), (ITER) = nl_attr_next(ITER)) + +/* These variants are convenient for iterating nested attributes. */ +#define NL_NESTED_FOR_EACH(ITER, LEFT, A) \ + NL_ATTR_FOR_EACH(ITER, LEFT, nl_attr_get(A), nl_attr_get_size(A)) +#define NL_NESTED_FOR_EACH_UNSAFE(ITER, LEFT, A) \ + NL_ATTR_FOR_EACH_UNSAFE(ITER, LEFT, nl_attr_get(A), nl_attr_get_size(A)) /* Netlink attribute parsing. */ int nl_attr_type(const struct nlattr *); @@ -137,6 +196,8 @@ uint64_t nl_attr_get_u64(const struct nlattr *); ovs_be16 nl_attr_get_be16(const struct nlattr *); ovs_be32 nl_attr_get_be32(const struct nlattr *); ovs_be64 nl_attr_get_be64(const struct nlattr *); +struct in6_addr nl_attr_get_in6_addr(const struct nlattr *nla); +odp_port_t nl_attr_get_odp_port(const struct nlattr *); const char *nl_attr_get_string(const struct nlattr *); void nl_attr_get_nested(const struct nlattr *, struct ofpbuf *); @@ -151,6 +212,11 @@ struct nl_policy bool optional; }; +#define NL_POLICY_FOR(TYPE) \ + .type = NL_A_UNSPEC, .min_len = sizeof(TYPE), .max_len = sizeof(TYPE) + +bool nl_attr_validate(const struct nlattr *, const struct nl_policy *); + bool nl_policy_parse(const struct ofpbuf *, size_t offset, const struct nl_policy[], struct nlattr *[], size_t n_attrs); @@ -160,5 +226,7 @@ bool nl_parse_nested(const struct nlattr *, const struct nl_policy[], const struct nlattr *nl_attr_find(const struct ofpbuf *, size_t hdr_len, uint16_t type); const struct nlattr *nl_attr_find_nested(const struct nlattr *, uint16_t type); +const struct nlattr *nl_attr_find__(const struct nlattr *attrs, size_t size, + uint16_t type); #endif /* netlink.h */