]> Git Repo - qemu.git/blame - hw/net/rocker/rocker_tlv.h
Merge remote-tracking branch 'remotes/cody/tags/block-pull-request' into staging
[qemu.git] / hw / net / rocker / rocker_tlv.h
CommitLineData
dc488f88
SF
1/*
2 * QEMU rocker switch emulation - TLV parsing and composing
3 *
4 * Copyright (c) 2014 Jiri Pirko <[email protected]>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
2a6a4076
MA
17#ifndef ROCKER_TLV_H
18#define ROCKER_TLV_H
dc488f88
SF
19
20#define ROCKER_TLV_ALIGNTO 8U
21#define ROCKER_TLV_ALIGN(len) \
22 (((len) + ROCKER_TLV_ALIGNTO - 1) & ~(ROCKER_TLV_ALIGNTO - 1))
23#define ROCKER_TLV_HDRLEN ROCKER_TLV_ALIGN(sizeof(RockerTlv))
24
25/*
26 * <------- ROCKER_TLV_HDRLEN -------> <--- ROCKER_TLV_ALIGN(payload) --->
27 * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+
28 * | Header | Pad | Payload | Pad |
29 * | (RockerTlv) | ing | | ing |
30 * +-----------------------------+- - -+- - - - - - - - - - - - - - -+- - -+
31 * <--------------------------- tlv->len -------------------------->
32 */
33
34static inline RockerTlv *rocker_tlv_next(const RockerTlv *tlv, int *remaining)
35{
36 int totlen = ROCKER_TLV_ALIGN(le16_to_cpu(tlv->len));
37
38 *remaining -= totlen;
39 return (RockerTlv *) ((char *) tlv + totlen);
40}
41
42static inline int rocker_tlv_ok(const RockerTlv *tlv, int remaining)
43{
44 return remaining >= (int) ROCKER_TLV_HDRLEN &&
45 le16_to_cpu(tlv->len) >= ROCKER_TLV_HDRLEN &&
46 le16_to_cpu(tlv->len) <= remaining;
47}
48
49#define rocker_tlv_for_each(pos, head, len, rem) \
50 for (pos = head, rem = len; \
51 rocker_tlv_ok(pos, rem); \
52 pos = rocker_tlv_next(pos, &(rem)))
53
54#define rocker_tlv_for_each_nested(pos, tlv, rem) \
55 rocker_tlv_for_each(pos, rocker_tlv_data(tlv), rocker_tlv_len(tlv), rem)
56
57static inline int rocker_tlv_size(int payload)
58{
59 return ROCKER_TLV_HDRLEN + payload;
60}
61
62static inline int rocker_tlv_total_size(int payload)
63{
64 return ROCKER_TLV_ALIGN(rocker_tlv_size(payload));
65}
66
67static inline int rocker_tlv_padlen(int payload)
68{
69 return rocker_tlv_total_size(payload) - rocker_tlv_size(payload);
70}
71
72static inline int rocker_tlv_type(const RockerTlv *tlv)
73{
74 return le32_to_cpu(tlv->type);
75}
76
77static inline void *rocker_tlv_data(const RockerTlv *tlv)
78{
79 return (char *) tlv + ROCKER_TLV_HDRLEN;
80}
81
82static inline int rocker_tlv_len(const RockerTlv *tlv)
83{
84 return le16_to_cpu(tlv->len) - ROCKER_TLV_HDRLEN;
85}
86
87static inline uint8_t rocker_tlv_get_u8(const RockerTlv *tlv)
88{
89 return *(uint8_t *) rocker_tlv_data(tlv);
90}
91
92static inline uint16_t rocker_tlv_get_u16(const RockerTlv *tlv)
93{
94 return *(uint16_t *) rocker_tlv_data(tlv);
95}
96
97static inline uint32_t rocker_tlv_get_u32(const RockerTlv *tlv)
98{
99 return *(uint32_t *) rocker_tlv_data(tlv);
100}
101
102static inline uint64_t rocker_tlv_get_u64(const RockerTlv *tlv)
103{
104 return *(uint64_t *) rocker_tlv_data(tlv);
105}
106
107static inline uint16_t rocker_tlv_get_le16(const RockerTlv *tlv)
108{
4071887b 109 return lduw_le_p(rocker_tlv_data(tlv));
dc488f88
SF
110}
111
112static inline uint32_t rocker_tlv_get_le32(const RockerTlv *tlv)
113{
4071887b 114 return ldl_le_p(rocker_tlv_data(tlv));
dc488f88
SF
115}
116
117static inline uint64_t rocker_tlv_get_le64(const RockerTlv *tlv)
118{
4071887b 119 return ldq_le_p(rocker_tlv_data(tlv));
dc488f88
SF
120}
121
122static inline void rocker_tlv_parse(RockerTlv **tb, int maxtype,
123 const char *buf, int buf_len)
124{
125 const RockerTlv *tlv;
126 const RockerTlv *head = (const RockerTlv *) buf;
127 int rem;
128
129 memset(tb, 0, sizeof(RockerTlv *) * (maxtype + 1));
130
131 rocker_tlv_for_each(tlv, head, buf_len, rem) {
132 uint32_t type = rocker_tlv_type(tlv);
133
134 if (type > 0 && type <= maxtype) {
135 tb[type] = (RockerTlv *) tlv;
136 }
137 }
138}
139
140static inline void rocker_tlv_parse_nested(RockerTlv **tb, int maxtype,
141 const RockerTlv *tlv)
142{
143 rocker_tlv_parse(tb, maxtype, rocker_tlv_data(tlv), rocker_tlv_len(tlv));
144}
145
146static inline RockerTlv *rocker_tlv_start(char *buf, int buf_pos)
147{
148 return (RockerTlv *) (buf + buf_pos);
149}
150
151static inline void rocker_tlv_put_iov(char *buf, int *buf_pos,
152 int type, const struct iovec *iov,
153 const unsigned int iovcnt)
154{
155 size_t len = iov_size(iov, iovcnt);
156 int total_size = rocker_tlv_total_size(len);
157 RockerTlv *tlv;
158
159 tlv = rocker_tlv_start(buf, *buf_pos);
160 *buf_pos += total_size;
161 tlv->type = cpu_to_le32(type);
162 tlv->len = cpu_to_le16(rocker_tlv_size(len));
163 iov_to_buf(iov, iovcnt, 0, rocker_tlv_data(tlv), len);
164 memset((char *) tlv + le16_to_cpu(tlv->len), 0, rocker_tlv_padlen(len));
165}
166
167static inline void rocker_tlv_put(char *buf, int *buf_pos,
168 int type, int len, void *data)
169{
170 struct iovec iov = {
171 .iov_base = data,
172 .iov_len = len,
173 };
174
175 rocker_tlv_put_iov(buf, buf_pos, type, &iov, 1);
176}
177
178static inline void rocker_tlv_put_u8(char *buf, int *buf_pos,
179 int type, uint8_t value)
180{
181 rocker_tlv_put(buf, buf_pos, type, sizeof(uint8_t), &value);
182}
183
184static inline void rocker_tlv_put_u16(char *buf, int *buf_pos,
185 int type, uint16_t value)
186{
187 rocker_tlv_put(buf, buf_pos, type, sizeof(uint16_t), &value);
188}
189
190static inline void rocker_tlv_put_u32(char *buf, int *buf_pos,
191 int type, uint32_t value)
192{
193 rocker_tlv_put(buf, buf_pos, type, sizeof(uint32_t), &value);
194}
195
196static inline void rocker_tlv_put_u64(char *buf, int *buf_pos,
197 int type, uint64_t value)
198{
199 rocker_tlv_put(buf, buf_pos, type, sizeof(uint64_t), &value);
200}
201
202static inline void rocker_tlv_put_le16(char *buf, int *buf_pos,
203 int type, uint16_t value)
204{
205 value = cpu_to_le16(value);
206 rocker_tlv_put(buf, buf_pos, type, sizeof(uint16_t), &value);
207}
208
209static inline void rocker_tlv_put_le32(char *buf, int *buf_pos,
210 int type, uint32_t value)
211{
212 value = cpu_to_le32(value);
213 rocker_tlv_put(buf, buf_pos, type, sizeof(uint32_t), &value);
214}
215
216static inline void rocker_tlv_put_le64(char *buf, int *buf_pos,
217 int type, uint64_t value)
218{
219 value = cpu_to_le64(value);
220 rocker_tlv_put(buf, buf_pos, type, sizeof(uint64_t), &value);
221}
222
223static inline RockerTlv *rocker_tlv_nest_start(char *buf, int *buf_pos,
224 int type)
225{
226 RockerTlv *start = rocker_tlv_start(buf, *buf_pos);
227
228 rocker_tlv_put(buf, buf_pos, type, 0, NULL);
229 return start;
230}
231
232static inline void rocker_tlv_nest_end(char *buf, int *buf_pos,
233 RockerTlv *start)
234{
235 start->len = (char *) rocker_tlv_start(buf, *buf_pos) - (char *) start;
236}
237
238static inline void rocker_tlv_nest_cancel(char *buf, int *buf_pos,
239 RockerTlv *start)
240{
241 *buf_pos = (char *) start - buf;
242}
243
244#endif
This page took 0.159279 seconds and 4 git commands to generate.