]>
Commit | Line | Data |
---|---|---|
582c2af2 | 1 | #include "squid.h" |
f4f6c2e0 | 2 | |
425de4c8 | 3 | #include "acl/Gadgets.h" |
8a01b99e | 4 | #include "cache_cf.h" |
b5523edc | 5 | #include "comm/Connection.h" |
425de4c8 AJ |
6 | #include "ConfigParser.h" |
7 | #include "fde.h" | |
582c2af2 | 8 | #include "globals.h" |
425de4c8 | 9 | #include "hier_code.h" |
f4f6c2e0 | 10 | #include "ip/QosConfig.h" |
602d9612 | 11 | #include "ip/tools.h" |
425de4c8 | 12 | #include "Parsing.h" |
575cb927 | 13 | |
21d845b1 FC |
14 | #if HAVE_ERRNO_H |
15 | #include <errno.h> | |
16 | #endif | |
17 | ||
425de4c8 | 18 | /* Qos namespace */ |
575cb927 | 19 | |
425de4c8 | 20 | void |
b5523edc | 21 | Ip::Qos::getTosFromServer(const Comm::ConnectionPointer &server, fde *clientFde) |
425de4c8 | 22 | { |
f4f6c2e0 AJ |
23 | #if USE_QOS_TOS && _SQUID_LINUX_ |
24 | /* Bug 2537: This part of ZPH only applies to patched Linux kernels. */ | |
425de4c8 | 25 | tos_t tos = 1; |
b5523edc | 26 | int tos_len = sizeof(tos); |
425de4c8 | 27 | clientFde->tosFromServer = 0; |
b5523edc | 28 | if (setsockopt(server->fd,SOL_IP,IP_RECVTOS,&tos,tos_len)==0) { |
425de4c8 AJ |
29 | unsigned char buf[512]; |
30 | int len = 512; | |
b5523edc | 31 | if (getsockopt(server->fd,SOL_IP,IP_PKTOPTIONS,buf,(socklen_t*)&len) == 0) { |
425de4c8 AJ |
32 | /* Parse the PKTOPTIONS structure to locate the TOS data message |
33 | * prepared in the kernel by the ZPH incoming TCP TOS preserving | |
34 | * patch. | |
35 | */ | |
36 | unsigned char * pbuf = buf; | |
37 | while (pbuf-buf < len) { | |
38 | struct cmsghdr *o = (struct cmsghdr*)pbuf; | |
39 | if (o->cmsg_len<=0) | |
40 | break; | |
575cb927 | 41 | |
425de4c8 AJ |
42 | if (o->cmsg_level == SOL_IP && o->cmsg_type == IP_TOS) { |
43 | int *tmp = (int*)CMSG_DATA(o); | |
44 | clientFde->tosFromServer = (tos_t)*tmp; | |
45 | break; | |
46 | } | |
47 | pbuf += CMSG_LEN(o->cmsg_len); | |
48 | } | |
49 | } else { | |
b5523edc | 50 | debugs(33, DBG_IMPORTANT, "QOS: error in getsockopt(IP_PKTOPTIONS) on " << server << " " << xstrerror()); |
425de4c8 AJ |
51 | } |
52 | } else { | |
b5523edc | 53 | debugs(33, DBG_IMPORTANT, "QOS: error in setsockopt(IP_RECVTOS) on " << server << " " << xstrerror()); |
425de4c8 AJ |
54 | } |
55 | #endif | |
56 | } | |
b7ac5457 | 57 | |
b5523edc | 58 | void Ip::Qos::getNfmarkFromServer(const Comm::ConnectionPointer &server, const fde *clientFde) |
575cb927 | 59 | { |
425de4c8 AJ |
60 | #if USE_LIBNETFILTERCONNTRACK |
61 | /* Allocate a new conntrack */ | |
62 | if (struct nf_conntrack *ct = nfct_new()) { | |
63 | ||
64 | /* Prepare data needed to find the connection in the conntrack table. | |
65 | * We need the local and remote IP address, and the local and remote | |
66 | * port numbers. | |
67 | */ | |
68 | ||
4dd643d5 | 69 | if (Ip::EnableIpv6 && server->local.isIPv6()) { |
425de4c8 AJ |
70 | nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET6); |
71 | struct in6_addr serv_fde_remote_ip6; | |
4dd643d5 | 72 | server->remote.getInAddr(serv_fde_remote_ip6); |
425de4c8 | 73 | nfct_set_attr(ct, ATTR_IPV6_DST, serv_fde_remote_ip6.s6_addr); |
b5523edc | 74 | struct in6_addr serv_fde_local_ip6; |
4dd643d5 | 75 | server->local.getInAddr(serv_fde_local_ip6); |
b5523edc | 76 | nfct_set_attr(ct, ATTR_IPV6_SRC, serv_fde_local_ip6.s6_addr); |
425de4c8 | 77 | } else { |
425de4c8 | 78 | nfct_set_attr_u8(ct, ATTR_L3PROTO, AF_INET); |
8bbb16e3 | 79 | struct in_addr serv_fde_remote_ip; |
4dd643d5 | 80 | server->remote.getInAddr(serv_fde_remote_ip); |
b5523edc AJ |
81 | nfct_set_attr_u32(ct, ATTR_IPV4_DST, serv_fde_remote_ip.s_addr); |
82 | struct in_addr serv_fde_local_ip; | |
4dd643d5 | 83 | server->local.getInAddr(serv_fde_local_ip); |
b5523edc | 84 | nfct_set_attr_u32(ct, ATTR_IPV4_SRC, serv_fde_local_ip.s_addr); |
425de4c8 AJ |
85 | } |
86 | ||
87 | nfct_set_attr_u8(ct, ATTR_L4PROTO, IPPROTO_TCP); | |
4dd643d5 AJ |
88 | nfct_set_attr_u16(ct, ATTR_PORT_DST, htons(server->remote.port())); |
89 | nfct_set_attr_u16(ct, ATTR_PORT_SRC, htons(server->local.port())); | |
425de4c8 AJ |
90 | |
91 | /* Open a handle to the conntrack */ | |
92 | if (struct nfct_handle *h = nfct_open(CONNTRACK, 0)) { | |
93 | /* Register the callback. The callback function will record the mark value. */ | |
b5523edc | 94 | nfct_callback_register(h, NFCT_T_ALL, getNfMarkCallback, (void *)clientFde); |
425de4c8 AJ |
95 | /* Query the conntrack table using the data previously set */ |
96 | int x = nfct_query(h, NFCT_Q_GET, ct); | |
97 | if (x == -1) { | |
98 | debugs(17, 2, "QOS: Failed to retrieve connection mark: (" << x << ") " << strerror(errno) | |
b5523edc | 99 | << " (Destination " << server->remote << ", source " << server->local << ")" ); |
425de4c8 | 100 | } |
425de4c8 AJ |
101 | nfct_close(h); |
102 | } else { | |
103 | debugs(17, 2, "QOS: Failed to open conntrack handle for upstream netfilter mark retrieval."); | |
104 | } | |
425de4c8 AJ |
105 | nfct_destroy(ct); |
106 | ||
107 | } else { | |
108 | debugs(17, 2, "QOS: Failed to allocate new conntrack for upstream netfilter mark retrieval."); | |
109 | } | |
110 | #endif | |
111 | } | |
112 | ||
113 | #if USE_LIBNETFILTERCONNTRACK | |
114 | int | |
115 | Ip::Qos::getNfMarkCallback(enum nf_conntrack_msg_type type, | |
ab745b44 A |
116 | struct nf_conntrack *ct, |
117 | void *data) | |
425de4c8 | 118 | { |
ab745b44 A |
119 | fde *clientFde = (fde *)data; |
120 | clientFde->nfmarkFromServer = nfct_get_attr_u32(ct, ATTR_MARK); | |
121 | debugs(17, 3, "QOS: Retrieved connection mark value: " << clientFde->nfmarkFromServer); | |
425de4c8 | 122 | |
ab745b44 | 123 | return NFCT_CB_CONTINUE; |
425de4c8 AJ |
124 | } |
125 | #endif | |
126 | ||
127 | int | |
b5523edc | 128 | Ip::Qos::doTosLocalMiss(const Comm::ConnectionPointer &conn, const hier_code hierCode) |
425de4c8 AJ |
129 | { |
130 | tos_t tos = 0; | |
131 | if (Ip::Qos::TheConfig.tosSiblingHit && hierCode==SIBLING_HIT) { | |
132 | tos = Ip::Qos::TheConfig.tosSiblingHit; | |
133 | debugs(33, 2, "QOS: Sibling Peer hit with hier code=" << hierCode << ", TOS=" << int(tos)); | |
134 | } else if (Ip::Qos::TheConfig.tosParentHit && hierCode==PARENT_HIT) { | |
135 | tos = Ip::Qos::TheConfig.tosParentHit; | |
136 | debugs(33, 2, "QOS: Parent Peer hit with hier code=" << hierCode << ", TOS=" << int(tos)); | |
a29d2a95 | 137 | } else if (Ip::Qos::TheConfig.preserveMissTos) { |
b5523edc | 138 | tos = fd_table[conn->fd].tosFromServer & Ip::Qos::TheConfig.preserveMissTosMask; |
a29d2a95 | 139 | tos = (tos & ~Ip::Qos::TheConfig.tosMissMask) | (Ip::Qos::TheConfig.tosMiss & Ip::Qos::TheConfig.tosMissMask); |
425de4c8 | 140 | debugs(33, 2, "QOS: Preserving TOS on miss, TOS=" << int(tos)); |
a29d2a95 AB |
141 | } else if (Ip::Qos::TheConfig.tosMiss) { |
142 | tos = Ip::Qos::TheConfig.tosMiss & Ip::Qos::TheConfig.tosMissMask; | |
143 | debugs(33, 2, "QOS: Cache miss, setting TOS=" << int(tos)); | |
425de4c8 | 144 | } |
b5523edc | 145 | return setSockTos(conn, tos); |
425de4c8 AJ |
146 | } |
147 | ||
148 | int | |
b5523edc | 149 | Ip::Qos::doNfmarkLocalMiss(const Comm::ConnectionPointer &conn, const hier_code hierCode) |
425de4c8 AJ |
150 | { |
151 | nfmark_t mark = 0; | |
152 | if (Ip::Qos::TheConfig.markSiblingHit && hierCode==SIBLING_HIT) { | |
153 | mark = Ip::Qos::TheConfig.markSiblingHit; | |
154 | debugs(33, 2, "QOS: Sibling Peer hit with hier code=" << hierCode << ", Mark=" << mark); | |
155 | } else if (Ip::Qos::TheConfig.markParentHit && hierCode==PARENT_HIT) { | |
156 | mark = Ip::Qos::TheConfig.markParentHit; | |
157 | debugs(33, 2, "QOS: Parent Peer hit with hier code=" << hierCode << ", Mark=" << mark); | |
425de4c8 | 158 | } else if (Ip::Qos::TheConfig.preserveMissMark) { |
b5523edc | 159 | mark = fd_table[conn->fd].nfmarkFromServer & Ip::Qos::TheConfig.preserveMissMarkMask; |
a29d2a95 | 160 | mark = (mark & ~Ip::Qos::TheConfig.markMissMask) | (Ip::Qos::TheConfig.markMiss & Ip::Qos::TheConfig.markMissMask); |
425de4c8 | 161 | debugs(33, 2, "QOS: Preserving mark on miss, Mark=" << mark); |
a29d2a95 AB |
162 | } else if (Ip::Qos::TheConfig.markMiss) { |
163 | mark = Ip::Qos::TheConfig.markMiss & Ip::Qos::TheConfig.markMissMask; | |
164 | debugs(33, 2, "QOS: Cache miss, setting Mark=" << mark); | |
425de4c8 | 165 | } |
b5523edc | 166 | return setSockNfmark(conn, mark); |
425de4c8 AJ |
167 | } |
168 | ||
169 | int | |
b5523edc | 170 | Ip::Qos::doTosLocalHit(const Comm::ConnectionPointer &conn) |
425de4c8 AJ |
171 | { |
172 | debugs(33, 2, "QOS: Setting TOS for local hit, TOS=" << int(Ip::Qos::TheConfig.tosLocalHit)); | |
b5523edc | 173 | return setSockTos(conn, Ip::Qos::TheConfig.tosLocalHit); |
425de4c8 AJ |
174 | } |
175 | ||
176 | int | |
b5523edc | 177 | Ip::Qos::doNfmarkLocalHit(const Comm::ConnectionPointer &conn) |
425de4c8 AJ |
178 | { |
179 | debugs(33, 2, "QOS: Setting netfilter mark for local hit, mark=" << Ip::Qos::TheConfig.markLocalHit); | |
b5523edc | 180 | return setSockNfmark(conn, Ip::Qos::TheConfig.markLocalHit); |
425de4c8 AJ |
181 | } |
182 | ||
183 | /* Qos::Config class */ | |
184 | ||
185 | Ip::Qos::Config Ip::Qos::TheConfig; | |
186 | ||
fad2588a | 187 | Ip::Qos::Config::Config() : tosLocalHit(0), tosSiblingHit(0), tosParentHit(0), |
f53156c2 A |
188 | tosMiss(0), tosMissMask(0), preserveMissTos(false), |
189 | preserveMissTosMask(0xFF), markLocalHit(0), markSiblingHit(0), | |
190 | markParentHit(0), markMiss(0), markMissMask(0), | |
191 | preserveMissMark(false), preserveMissMarkMask(0xFFFFFFFF), | |
192 | tosToServer(NULL), tosToClient(NULL), nfmarkToServer(NULL), | |
193 | nfmarkToClient(NULL) | |
425de4c8 | 194 | { |
575cb927 AJ |
195 | } |
196 | ||
197 | void | |
425de4c8 | 198 | Ip::Qos::Config::parseConfigLine() |
575cb927 | 199 | { |
575cb927 AJ |
200 | /* parse options ... */ |
201 | char *token; | |
425de4c8 AJ |
202 | /* These are set as appropriate and then used to check whether the initial loop has been done */ |
203 | bool mark = false; | |
204 | bool tos = false; | |
205 | /* Assume preserve is true. We don't set at initialisation as this affects isHitTosActive(). | |
206 | We have to do this now, as we may never match the 'tos' parameter below */ | |
207 | #if !USE_QOS_TOS | |
208 | debugs(3, DBG_CRITICAL, "ERROR: Invalid option 'qos_flows'. QOS features not enabled in this build"); | |
209 | self_destruct(); | |
210 | #endif | |
211 | ||
2eceb328 | 212 | while ( (token = ConfigParser::NextToken()) ) { |
575cb927 | 213 | |
425de4c8 AJ |
214 | // Work out TOS or mark. Default to TOS for backwards compatibility |
215 | if (!(mark || tos)) { | |
216 | if (strncmp(token, "mark",4) == 0) { | |
11e8cfe3 | 217 | #if SO_MARK && USE_LIBCAP |
425de4c8 AJ |
218 | mark = true; |
219 | // Assume preserve is true. We don't set at initialisation as this affects isHitNfmarkActive() | |
220 | #if USE_LIBNETFILTERCONNTRACK | |
221 | preserveMissMark = true; | |
222 | # else // USE_LIBNETFILTERCONNTRACK | |
223 | preserveMissMark = false; | |
224 | debugs(3, DBG_IMPORTANT, "WARNING: Squid not compiled with Netfilter conntrack library. " | |
ab745b44 | 225 | << "Netfilter mark preservation not available."); |
425de4c8 | 226 | #endif // USE_LIBNETFILTERCONNTRACK |
11e8cfe3 | 227 | #elif SO_MARK // SO_MARK && USE_LIBCAP |
425de4c8 | 228 | debugs(3, DBG_CRITICAL, "ERROR: Invalid parameter 'mark' in qos_flows option. " |
11e8cfe3 | 229 | << "Linux Netfilter marking not available without LIBCAP support."); |
425de4c8 | 230 | self_destruct(); |
11e8cfe3 AB |
231 | #else // SO_MARK && USE_LIBCAP |
232 | debugs(3, DBG_CRITICAL, "ERROR: Invalid parameter 'mark' in qos_flows option. " | |
233 | << "Linux Netfilter marking not available on this platform."); | |
234 | self_destruct(); | |
235 | #endif // SO_MARK && USE_LIBCAP | |
425de4c8 AJ |
236 | } else if (strncmp(token, "tos",3) == 0) { |
237 | preserveMissTos = true; | |
238 | tos = true; | |
239 | } else { | |
240 | preserveMissTos = true; | |
241 | tos = true; | |
242 | } | |
243 | } | |
244 | ||
af6a12ee | 245 | if (strncmp(token, "local-hit=",10) == 0) { |
425de4c8 AJ |
246 | |
247 | if (mark) { | |
248 | if (!xstrtoui(&token[10], NULL, &markLocalHit, 0, std::numeric_limits<nfmark_t>::max())) { | |
ab745b44 A |
249 | debugs(3, DBG_CRITICAL, "ERROR: Bad mark local-hit value " << &token[10]); |
250 | self_destruct(); | |
425de4c8 AJ |
251 | } |
252 | } else { | |
253 | unsigned int v = 0; | |
254 | if (!xstrtoui(&token[10], NULL, &v, 0, std::numeric_limits<tos_t>::max())) { | |
ab745b44 A |
255 | debugs(3, DBG_CRITICAL, "ERROR: Bad TOS local-hit value " << &token[10]); |
256 | self_destruct(); | |
425de4c8 AJ |
257 | } |
258 | tosLocalHit = (tos_t)v; | |
259 | } | |
260 | ||
af6a12ee | 261 | } else if (strncmp(token, "sibling-hit=",12) == 0) { |
425de4c8 AJ |
262 | |
263 | if (mark) { | |
264 | if (!xstrtoui(&token[12], NULL, &markSiblingHit, 0, std::numeric_limits<nfmark_t>::max())) { | |
ab745b44 A |
265 | debugs(3, DBG_CRITICAL, "ERROR: Bad mark sibling-hit value " << &token[12]); |
266 | self_destruct(); | |
425de4c8 AJ |
267 | } |
268 | } else { | |
269 | unsigned int v = 0; | |
270 | if (!xstrtoui(&token[12], NULL, &v, 0, std::numeric_limits<tos_t>::max())) { | |
ab745b44 A |
271 | debugs(3, DBG_CRITICAL, "ERROR: Bad TOS sibling-hit value " << &token[12]); |
272 | self_destruct(); | |
425de4c8 AJ |
273 | } |
274 | tosSiblingHit = (tos_t)v; | |
275 | } | |
276 | ||
af6a12ee | 277 | } else if (strncmp(token, "parent-hit=",11) == 0) { |
425de4c8 AJ |
278 | |
279 | if (mark) { | |
280 | if (!xstrtoui(&token[11], NULL, &markParentHit, 0, std::numeric_limits<nfmark_t>::max())) { | |
ab745b44 A |
281 | debugs(3, DBG_CRITICAL, "ERROR: Bad mark parent-hit value " << &token[11]); |
282 | self_destruct(); | |
425de4c8 AJ |
283 | } |
284 | } else { | |
285 | unsigned int v = 0; | |
286 | if (!xstrtoui(&token[11], NULL, &v, 0, std::numeric_limits<tos_t>::max())) { | |
ab745b44 A |
287 | debugs(3, DBG_CRITICAL, "ERROR: Bad TOS parent-hit value " << &token[11]); |
288 | self_destruct(); | |
425de4c8 AJ |
289 | } |
290 | tosParentHit = (tos_t)v; | |
291 | } | |
292 | ||
293 | } else if (strncmp(token, "miss=",5) == 0) { | |
294 | ||
a29d2a95 | 295 | char *end; |
425de4c8 | 296 | if (mark) { |
a29d2a95 | 297 | if (!xstrtoui(&token[5], &end, &markMiss, 0, std::numeric_limits<nfmark_t>::max())) { |
ab745b44 A |
298 | debugs(3, DBG_CRITICAL, "ERROR: Bad mark miss value " << &token[5]); |
299 | self_destruct(); | |
425de4c8 | 300 | } |
a29d2a95 AB |
301 | if (*end == '/') { |
302 | if (!xstrtoui(end + 1, NULL, &markMissMask, 0, std::numeric_limits<nfmark_t>::max())) { | |
303 | debugs(3, DBG_CRITICAL, "ERROR: Bad mark miss mask value " << (end + 1) << ". Using 0xFFFFFFFF instead."); | |
304 | markMissMask = 0xFFFFFFFF; | |
305 | } | |
306 | } else { | |
307 | markMissMask = 0xFFFFFFFF; | |
308 | } | |
425de4c8 AJ |
309 | } else { |
310 | unsigned int v = 0; | |
a29d2a95 | 311 | if (!xstrtoui(&token[5], &end, &v, 0, std::numeric_limits<tos_t>::max())) { |
ab745b44 A |
312 | debugs(3, DBG_CRITICAL, "ERROR: Bad TOS miss value " << &token[5]); |
313 | self_destruct(); | |
425de4c8 AJ |
314 | } |
315 | tosMiss = (tos_t)v; | |
a29d2a95 AB |
316 | if (*end == '/') { |
317 | if (!xstrtoui(end + 1, NULL, &v, 0, std::numeric_limits<tos_t>::max())) { | |
318 | debugs(3, DBG_CRITICAL, "ERROR: Bad TOS miss mask value " << (end + 1) << ". Using 0xFF instead."); | |
319 | tosMissMask = 0xFF; | |
320 | } else | |
321 | tosMissMask = (tos_t)v; | |
322 | } else { | |
323 | tosMissMask = 0xFF; | |
324 | } | |
425de4c8 AJ |
325 | } |
326 | ||
af6a12ee | 327 | } else if (strcmp(token, "disable-preserve-miss") == 0) { |
425de4c8 AJ |
328 | |
329 | if (preserveMissTosMask!=0xFFU || preserveMissMarkMask!=0xFFFFFFFFU) { | |
330 | debugs(3, DBG_CRITICAL, "ERROR: miss-mask feature cannot be set with disable-preserve-miss"); | |
331 | self_destruct(); | |
332 | } | |
333 | if (mark) { | |
334 | preserveMissMark = false; | |
335 | preserveMissMarkMask = 0; | |
336 | } else { | |
337 | preserveMissTos = false; | |
338 | preserveMissTosMask = 0; | |
339 | } | |
340 | ||
341 | } else if (strncmp(token, "miss-mask=",10) == 0) { | |
342 | ||
343 | if (mark && preserveMissMark) { | |
344 | if (!xstrtoui(&token[10], NULL, &preserveMissMarkMask, 0, std::numeric_limits<nfmark_t>::max())) { | |
ab745b44 A |
345 | debugs(3, DBG_CRITICAL, "ERROR: Bad mark miss-mark value " << &token[10]); |
346 | self_destruct(); | |
425de4c8 AJ |
347 | } |
348 | } else if (preserveMissTos) { | |
349 | unsigned int v = 0; | |
350 | if (!xstrtoui(&token[10], NULL, &v, 0, std::numeric_limits<tos_t>::max())) { | |
ab745b44 A |
351 | debugs(3, DBG_CRITICAL, "ERROR: Bad TOS miss-mark value " << &token[10]); |
352 | self_destruct(); | |
425de4c8 AJ |
353 | } |
354 | preserveMissTosMask = (tos_t)v; | |
355 | } else { | |
356 | debugs(3, DBG_CRITICAL, "ERROR: miss-mask feature cannot be set without miss-preservation enabled"); | |
357 | self_destruct(); | |
358 | } | |
359 | ||
575cb927 AJ |
360 | } |
361 | } | |
362 | } | |
363 | ||
dbe6f864 AJ |
364 | /** |
365 | * NOTE: Due to the low-level nature of the library these | |
366 | * objects are part of the dump function must be self-contained. | |
367 | * which means no StoreEntry refrences. Just a basic char* buffer. | |
425de4c8 | 368 | */ |
575cb927 | 369 | void |
425de4c8 | 370 | Ip::Qos::Config::dumpConfigLine(char *entry, const char *name) const |
575cb927 | 371 | { |
dbe6f864 | 372 | char *p = entry; |
425de4c8 | 373 | if (isHitTosActive()) { |
575cb927 | 374 | |
425de4c8 AJ |
375 | p += snprintf(p, 11, "%s", name); // strlen("qos_flows "); |
376 | p += snprintf(p, 4, "%s", "tos"); | |
575cb927 | 377 | |
425de4c8 AJ |
378 | if (tosLocalHit > 0) { |
379 | p += snprintf(p, 16, " local-hit=0x%02X", tosLocalHit); | |
380 | } | |
381 | if (tosSiblingHit > 0) { | |
382 | p += snprintf(p, 18, " sibling-hit=0x%02X", tosSiblingHit); | |
383 | } | |
384 | if (tosParentHit > 0) { | |
385 | p += snprintf(p, 17, " parent-hit=0x%02X", tosParentHit); | |
386 | } | |
387 | if (tosMiss > 0) { | |
388 | p += snprintf(p, 11, " miss=0x%02X", tosMiss); | |
a29d2a95 AB |
389 | if (tosMissMask!=0xFFU) { |
390 | p += snprintf(p, 6, "/0x%02X", markMissMask); | |
391 | } | |
425de4c8 AJ |
392 | } |
393 | if (preserveMissTos == 0) { | |
394 | p += snprintf(p, 23, " disable-preserve-miss"); | |
395 | } | |
396 | if (preserveMissTos && preserveMissTosMask != 0) { | |
397 | p += snprintf(p, 16, " miss-mask=0x%02X", preserveMissTosMask); | |
398 | } | |
399 | p += snprintf(p, 2, "\n"); | |
575cb927 | 400 | } |
b5523edc | 401 | |
425de4c8 AJ |
402 | if (isHitNfmarkActive()) { |
403 | p += snprintf(p, 11, "%s", name); // strlen("qos_flows "); | |
404 | p += snprintf(p, 5, "%s", "mark"); | |
405 | ||
406 | if (markLocalHit > 0) { | |
407 | p += snprintf(p, 22, " local-hit=0x%02X", markLocalHit); | |
408 | } | |
409 | if (markSiblingHit > 0) { | |
410 | p += snprintf(p, 24, " sibling-hit=0x%02X", markSiblingHit); | |
411 | } | |
412 | if (markParentHit > 0) { | |
413 | p += snprintf(p, 23, " parent-hit=0x%02X", markParentHit); | |
414 | } | |
415 | if (markMiss > 0) { | |
416 | p += snprintf(p, 17, " miss=0x%02X", markMiss); | |
a29d2a95 AB |
417 | if (markMissMask!=0xFFFFFFFFU) { |
418 | p += snprintf(p, 12, "/0x%02X", markMissMask); | |
419 | } | |
425de4c8 AJ |
420 | } |
421 | if (preserveMissMark == false) { | |
422 | p += snprintf(p, 23, " disable-preserve-miss"); | |
423 | } | |
424 | if (preserveMissMark && preserveMissMarkMask != 0) { | |
425 | p += snprintf(p, 22, " miss-mask=0x%02X", preserveMissMarkMask); | |
426 | } | |
427 | p += snprintf(p, 2, "\n"); | |
575cb927 | 428 | } |
575cb927 AJ |
429 | } |
430 | ||
425de4c8 AJ |
431 | #if !_USE_INLINE_ |
432 | #include "Qos.cci" | |
433 | #endif |