VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PDMNetShaper.cpp@ 93631

Last change on this file since 93631 was 93631, checked in by vboxsync, 3 years ago

VMM/PDMNetShaper: Don't start the unchoke thread unless there are are one or more bandwidth groups configured. Make the unchoke thread wait on an event sempahore so it can be woken up when needed and stop wasting cpu cycles and battery on lots of unnecessary wakups. Use a timer (real time clock) to wake up the unchoke timer when needed. bugref:10093 bugref:5582

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 18.1 KB
Line 
1/* $Id: PDMNetShaper.cpp 93631 2022-02-07 00:45:08Z vboxsync $ */
2/** @file
3 * PDM Network Shaper - Limit network traffic according to bandwidth group settings.
4 */
5
6/*
7 * Copyright (C) 2011-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_NET_SHAPER
23#include <VBox/vmm/pdm.h>
24#include "PDMInternal.h"
25#include <VBox/vmm/vm.h>
26#include <VBox/vmm/uvm.h>
27#include <VBox/err.h>
28
29#include <VBox/log.h>
30#include <iprt/asm.h>
31#include <iprt/assert.h>
32#include <iprt/critsect.h>
33#include <iprt/string.h>
34#include <iprt/semaphore.h>
35#include <iprt/thread.h>
36
37#include <VBox/vmm/pdmnetshaper.h>
38
39
40
41
42/**
43 * Looks up a network bandwidth group by it's name.
44 *
45 * @returns Pointer to the group if found, NULL if not.
46 * @param pVM The cross context VM structure.
47 * @param pszName The name of the group to find.
48 */
49static PPDMNSBWGROUP pdmNsBwGroupFindByName(PVM pVM, const char *pszName)
50{
51 AssertPtrReturn(pszName, NULL);
52 AssertReturn(*pszName != '\0', NULL);
53
54 size_t const cGroups = RT_MIN(pVM->pdm.s.cNsGroups, RT_ELEMENTS(pVM->pdm.s.aNsGroups));
55 for (size_t i = 0; i < cGroups; i++)
56 if (RTStrCmp(pVM->pdm.s.aNsGroups[i].szName, pszName) == 0)
57 return &pVM->pdm.s.aNsGroups[i];
58 return NULL;
59}
60
61
62#ifdef VBOX_STRICT
63/**
64 * Checks if pFilter is attached to the given group by walking the list.
65 */
66DECLINLINE(bool) pdmR3NsIsFilterAttached(PPDMNSBWGROUP pGroup, PPDMNSFILTER pFilter)
67{
68 PPDMNSFILTER pCur;
69 RTListForEach(&pGroup->FilterList, pCur, PDMNSFILTER, ListEntry)
70 {
71 if (pCur == pFilter)
72 return true;
73 }
74 return false;
75}
76#endif
77
78/**
79 * Attaches a network filter driver to the named bandwidth group.
80 *
81 * @returns VBox status code.
82 * @retval VERR_ALREADY_INITIALIZED if already attached.
83 * @retval VERR_NOT_FOUND if the bandwidth wasn't found.
84 *
85 * @param pVM The cross context VM structure.
86 * @param pDrvIns The driver instance.
87 * @param pszName Name of the bandwidth group to attach to.
88 * @param pFilter Pointer to the filter to attach.
89 */
90VMMR3_INT_DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, PPDMNSFILTER pFilter)
91{
92 /*
93 * Validate input.
94 */
95 RT_NOREF(pDrvIns);
96 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
97 AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
98
99 uint32_t iGroup = pFilter->iGroup;
100 AssertMsgReturn(iGroup == 0, ("iGroup=%d\n", iGroup), VERR_ALREADY_INITIALIZED);
101 Assert(pFilter->ListEntry.pNext == NULL);
102 Assert(pFilter->ListEntry.pPrev == NULL);
103
104 /* Resolve the group. */
105 PPDMNSBWGROUP pGroup = pdmNsBwGroupFindByName(pVM, pszName);
106 AssertMsgReturn(pGroup, ("'%s'\n", pszName), VERR_NOT_FOUND);
107
108 /*
109 * The attach is protected by PDM::NsLock and by updating iGroup atomatically.
110 */
111 int rc = RTCritSectEnter(&pVM->pdm.s.NsLock);
112 if (RT_SUCCESS(rc))
113 {
114 if (ASMAtomicCmpXchgU32(&pFilter->iGroup, (uint32_t)(pGroup - &pVM->pdm.s.aNsGroups[0]) + 1, 0))
115 {
116 Assert(pFilter->ListEntry.pNext == NULL);
117 Assert(pFilter->ListEntry.pPrev == NULL);
118 RTListAppend(&pGroup->FilterList, &pFilter->ListEntry);
119
120 uint32_t cRefs = ASMAtomicIncU32(&pGroup->cRefs);
121 AssertMsg(cRefs > 0 && cRefs < _16K, ("%u\n", cRefs));
122 RT_NOREF_PV(cRefs);
123
124 LogFlow(("PDMR3NsAttach: Attached '%s'/%u to %s (cRefs=%u)\n",
125 pDrvIns->pReg->szName, pDrvIns->iInstance, pGroup->szName, cRefs));
126 rc = VINF_SUCCESS;
127 }
128 else
129 {
130 AssertMsgFailed(("iGroup=%d (attach race)\n", pFilter->iGroup));
131 rc = VERR_ALREADY_INITIALIZED;
132 }
133
134 int rc2 = RTCritSectLeave(&pVM->pdm.s.NsLock);
135 AssertRC(rc2);
136 }
137
138 return rc;
139}
140
141
142/**
143 * Detaches a network filter driver from its current bandwidth group (if any).
144 *
145 * @returns VBox status code.
146 * @param pVM The cross context VM structure.
147 * @param pDrvIns The driver instance.
148 * @param pFilter Pointer to the filter to detach.
149 */
150VMMR3_INT_DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter)
151{
152 /*
153 * Validate input.
154 */
155 RT_NOREF(pDrvIns);
156 VM_ASSERT_EMT_RETURN(pVM, VERR_VM_THREAD_NOT_EMT);
157 AssertPtrReturn(pFilter, VERR_INVALID_POINTER);
158
159 /* Now, return quietly if the filter isn't attached since driver/device
160 destructors are called on constructor failure. */
161 uint32_t const iGroup = ASMAtomicUoReadU32(&pFilter->iGroup);
162 if (!iGroup)
163 return VINF_SUCCESS;
164 AssertMsgReturn(iGroup - 1 < RT_MIN(pVM->pdm.s.cNsGroups, RT_ELEMENTS(pVM->pdm.s.aNsGroups)), ("iGroup=%#x\n", iGroup),
165 VERR_INVALID_HANDLE);
166 PPDMNSBWGROUP const pGroup = &pVM->pdm.s.aNsGroups[iGroup - 1];
167
168 /*
169 * The detaching is protected by PDM::NsLock and by atomically updating iGroup.
170 */
171 int rc = RTCritSectEnter(&pVM->pdm.s.NsLock);
172 if (RT_SUCCESS(rc))
173 {
174 if (ASMAtomicCmpXchgU32(&pFilter->iGroup, 0, iGroup))
175 {
176 Assert(pdmR3NsIsFilterAttached(pGroup, pFilter));
177 RTListNodeRemove(&pFilter->ListEntry);
178 Assert(pFilter->ListEntry.pNext == NULL);
179 Assert(pFilter->ListEntry.pPrev == NULL);
180 ASMAtomicWriteU32(&pFilter->iGroup, 0);
181
182 uint32_t cRefs = ASMAtomicDecU32(&pGroup->cRefs);
183 Assert(cRefs < _16K);
184 RT_NOREF_PV(cRefs);
185
186 LogFlow(("PDMR3NsDetach: Detached '%s'/%u from %s (cRefs=%u)\n",
187 pDrvIns->pReg->szName, pDrvIns->iInstance, pGroup->szName, cRefs));
188 rc = VINF_SUCCESS;
189 }
190 else
191 AssertFailedStmt(rc = VERR_WRONG_ORDER);
192
193 int rc2 = RTCritSectLeave(&pVM->pdm.s.NsLock);
194 AssertRC(rc2);
195 }
196 else
197 AssertRC(rc);
198 return rc;
199}
200
201
202/**
203 * This is used both by pdmR3NsUnchokeThread and PDMR3NsBwGroupSetLimit,
204 * the latter only when setting cbPerSecMax to zero.
205 *
206 * @param pGroup The group which filters should be unchoked.
207 * @note Caller owns the PDM::NsLock critsect.
208 */
209static void pdmR3NsUnchokeGroupFilters(PPDMNSBWGROUP pGroup)
210{
211 PPDMNSFILTER pFilter;
212 RTListForEach(&pGroup->FilterList, pFilter, PDMNSFILTER, ListEntry)
213 {
214 bool fChoked = ASMAtomicXchgBool(&pFilter->fChoked, false);
215 if (fChoked)
216 {
217 PPDMINETWORKDOWN pIDrvNet = pFilter->pIDrvNetR3;
218 if (pIDrvNet && pIDrvNet->pfnXmitPending != NULL)
219 {
220 Log3(("pdmR3NsUnchokeGroupFilters: Unchoked %p in %s, calling %p\n",
221 pFilter, pGroup->szName, pIDrvNet->pfnXmitPending));
222 pIDrvNet->pfnXmitPending(pIDrvNet);
223 }
224 else
225 Log3(("pdmR3NsUnchokeGroupFilters: Unchoked %p in %s (no callback)\n", pFilter, pGroup->szName));
226 }
227 }
228}
229
230
231/**
232 * Worker for PDMR3NsBwGroupSetLimit and pdmR3NetShaperInit.
233 *
234 * @returns New bucket size.
235 * @param pGroup The group to update.
236 * @param cbPerSecMax The new max bytes per second.
237 */
238static uint32_t pdmNsBwGroupSetLimit(PPDMNSBWGROUP pGroup, uint64_t cbPerSecMax)
239{
240 uint32_t const cbRet = RT_MAX(PDM_NETSHAPER_MIN_BUCKET_SIZE, cbPerSecMax * PDM_NETSHAPER_MAX_LATENCY / RT_MS_1SEC);
241 pGroup->cbBucket = cbRet;
242 pGroup->cbPerSecMax = cbPerSecMax;
243 LogFlow(("pdmNsBwGroupSetLimit: New rate limit is %#RX64 bytes per second, adjusted bucket size to %#x bytes\n",
244 cbPerSecMax, cbRet));
245 return cbRet;
246}
247
248
249/**
250 * Adjusts the maximum rate for the bandwidth group.
251 *
252 * @returns VBox status code.
253 * @param pUVM The user mode VM handle.
254 * @param pszName Name of the bandwidth group to attach to.
255 * @param cbPerSecMax Maximum number of bytes per second to be transmitted.
256 */
257VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PUVM pUVM, const char *pszName, uint64_t cbPerSecMax)
258{
259 /*
260 * Validate input.
261 */
262 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
263 PVM const pVM = pUVM->pVM;
264 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
265
266 int rc;
267 PPDMNSBWGROUP pGroup = pdmNsBwGroupFindByName(pVM, pszName);
268 if (pGroup)
269 {
270 /*
271 * Lock the group while we effect the changes.
272 */
273 rc = PDMCritSectEnter(pVM, &pGroup->Lock, VERR_IGNORED);
274 if (RT_SUCCESS(rc))
275 {
276 uint32_t const cbBucket = pdmNsBwGroupSetLimit(pGroup, cbPerSecMax);
277
278 /* Drop extra tokens */
279 if (pGroup->cbTokensLast > cbBucket)
280 pGroup->cbTokensLast = cbBucket;
281 Log(("PDMR3NsBwGroupSetLimit/%s: cbBucket=%#x cbPerSecMax=%#RX64\n", pGroup->szName, cbBucket, cbPerSecMax));
282
283 int rc2 = PDMCritSectLeave(pVM, &pGroup->Lock);
284 AssertRC(rc2);
285
286 /*
287 * If we disabled the group, we must make sure to unchoke all filter
288 * as the thread will ignore the group from now on.
289 *
290 * We do this after leaving the group lock to keep the locking simple.
291 * Extra pfnXmitPending calls should be harmless, of course ASSUMING
292 * nobody take offence to being called on this thread.
293 */
294 if (cbPerSecMax == 0)
295 {
296 Log(("PDMR3NsBwGroupSetLimit: cbPerSecMax was set to zero, so unchoking filters...\n"));
297 rc = RTCritSectEnter(&pVM->pdm.s.NsLock);
298 AssertRC(rc);
299
300 pdmR3NsUnchokeGroupFilters(pGroup);
301
302 rc2 = RTCritSectLeave(&pVM->pdm.s.NsLock);
303 AssertRC(rc2);
304 }
305 }
306 else
307 AssertRC(rc);
308 }
309 else
310 rc = VERR_NOT_FOUND;
311 return rc;
312}
313
314
315/**
316 * I/O thread for pending unchoking and associating transmitting.
317 *
318 * @returns VINF_SUCCESS (ignored).
319 * @param pVM The cross context VM structure.
320 * @param pThread The PDM thread data.
321 */
322static DECLCALLBACK(int) pdmR3NsUnchokeThread(PVM pVM, PPDMTHREAD pThread)
323{
324 LogFlow(("pdmR3NsUnchokeThread: pVM=%p\n", pVM));
325 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
326 {
327 int rc = RTSemEventWait(pVM->pdm.s.hNsUnchokeEvt, RT_INDEFINITE_WAIT);
328 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
329 break;
330 AssertMsgStmt(RT_SUCCESS(rc) || rc == VERR_TIMEOUT /* paranioa*/, ("%Rrc\n", rc),
331 RTThreadSleep(PDM_NETSHAPER_MAX_LATENCY));
332
333 /*
334 * Go over all bandwidth groups/filters and unchoke their filters.
335 *
336 * We take the main lock here to prevent any detaching or attaching
337 * from taking place while we're traversing the filter lists.
338 */
339 rc = RTCritSectEnter(&pVM->pdm.s.NsLock);
340 AssertRC(rc);
341
342 size_t const cGroups = RT_MIN(pVM->pdm.s.cNsGroups, RT_ELEMENTS(pVM->pdm.s.aNsGroups));
343 for (size_t i = 0; i < cGroups; i++)
344 {
345 PPDMNSBWGROUP const pGroup = &pVM->pdm.s.aNsGroups[i];
346 if ( pGroup->cRefs > 0
347 && pGroup->cbPerSecMax > 0)
348 pdmR3NsUnchokeGroupFilters(pGroup);
349 }
350
351 rc = RTCritSectLeave(&pVM->pdm.s.NsLock);
352 AssertRC(rc);
353 }
354 return VINF_SUCCESS;
355}
356
357
358/**
359 * @copydoc FNPDMTHREADWAKEUPINT
360 */
361static DECLCALLBACK(int) pdmR3NsUnchokeWakeUp(PVM pVM, PPDMTHREAD pThread)
362{
363 LogFlow(("pdmR3NsUnchokeWakeUp:\n"));
364
365 /* Wake up the thread. */
366 int rc = RTSemEventSignal(pVM->pdm.s.hNsUnchokeEvt);
367 AssertRC(rc);
368
369 RT_NOREF(pThread);
370 return VINF_SUCCESS;
371}
372
373
374/**
375 * @callback_method_impl{FNTMTIMERINT, Wakes up pdmR3NsUnchokeThread.}
376 */
377static DECLCALLBACK(void) pdmR3NsUnchokeTimer(PVM pVM, TMTIMERHANDLE hTimer, void *pvUser)
378{
379 ASMAtomicWriteBool(&pVM->pdm.s.fNsUnchokeTimerArmed, false);
380
381 /* Wake up the thread. */
382 int rc = RTSemEventSignal(pVM->pdm.s.hNsUnchokeEvt);
383 AssertRC(rc);
384
385 RT_NOREF(hTimer, pvUser);
386}
387
388
389/**
390 * Terminate the network shaper, groups, lock and everything.
391 *
392 * @returns VBox error code.
393 * @param pVM The cross context VM structure.
394 */
395void pdmR3NetShaperTerm(PVM pVM)
396{
397 size_t const cGroups = RT_MIN(pVM->pdm.s.cNsGroups, RT_ELEMENTS(pVM->pdm.s.aNsGroups));
398 for (size_t i = 0; i < cGroups; i++)
399 {
400 PPDMNSBWGROUP const pGroup = &pVM->pdm.s.aNsGroups[i];
401 AssertMsg(pGroup->cRefs == 0, ("cRefs=%s '%s'\n", pGroup->cRefs, pGroup->szName));
402 AssertContinue(PDMCritSectIsInitialized(&pGroup->Lock));
403 PDMR3CritSectDelete(pVM, &pGroup->Lock);
404 }
405
406 RTCritSectDelete(&pVM->pdm.s.NsLock);
407}
408
409
410/**
411 * Initialize the network shaper.
412 *
413 * @returns VBox status code
414 * @param pVM The cross context VM structure.
415 */
416int pdmR3NetShaperInit(PVM pVM)
417{
418 LogFlow(("pdmR3NetShaperInit: pVM=%p\n", pVM));
419 VM_ASSERT_EMT(pVM);
420
421 Assert(pVM->pdm.s.cNsGroups == 0);
422 pVM->pdm.s.hNsUnchokeEvt = NIL_RTSEMEVENT;
423 pVM->pdm.s.hNsUnchokeTimer = NIL_TMTIMERHANDLE;
424
425 /*
426 * Initialize the critical section protecting attaching, detaching and unchoking.
427 *
428 * This is a non-recursive lock to make sure nobody tries to mess with the groups
429 * from the pfnXmitPending callback.
430 */
431 int rc = RTCritSectInitEx(&pVM->pdm.s.NsLock, RTCRITSECT_FLAGS_NO_NESTING,
432 NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "PDMNetShaper");
433 AssertRCReturn(rc, rc);
434
435 /*
436 * Initialize all bandwidth groups.
437 */
438 PCFGMNODE pCfgNetShaper = CFGMR3GetChild(CFGMR3GetChild(CFGMR3GetRoot(pVM), "PDM"), "NetworkShaper");
439 PCFGMNODE pCfgBwGrp = CFGMR3GetChild(pCfgNetShaper, "BwGroups");
440 if (pCfgBwGrp)
441 {
442 uint32_t iGroup = 0;
443 for (PCFGMNODE pCur = CFGMR3GetFirstChild(pCfgBwGrp); pCur; pCur = CFGMR3GetNextChild(pCur))
444 {
445 /*
446 * Get the config data.
447 */
448 size_t cchName = CFGMR3GetNameLen(pCur);
449 AssertBreakStmt(cchName <= PDM_NET_SHAPER_MAX_NAME_LEN,
450 rc = VMR3SetError(pVM->pUVM, VERR_INVALID_NAME, RT_SRC_POS,
451 N_("Network shaper group name #%u is too long: %zu, max %u"),
452 iGroup, cchName, PDM_NET_SHAPER_MAX_NAME_LEN));
453 char szName[PDM_NET_SHAPER_MAX_NAME_LEN + 1];
454 rc = CFGMR3GetName(pCur, szName, sizeof(szName));
455 AssertRCBreak(rc);
456 AssertBreakStmt(szName[0] != '\0',
457 rc = VMR3SetError(pVM->pUVM, VERR_INVALID_NAME, RT_SRC_POS,
458 N_("Empty network shaper group name #%u"), iGroup));
459
460 uint64_t cbMax;
461 rc = CFGMR3QueryU64(pCur, "Max", &cbMax);
462 AssertRCBreakStmt(rc, rc = VMR3SetError(pVM->pUVM, rc, RT_SRC_POS,
463 N_("Failed to read 'Max' value for network shaper group '%s': %Rrc"),
464 szName, rc));
465
466 /*
467 * Initialize the group table entry.
468 */
469 AssertBreakStmt(iGroup < RT_ELEMENTS(pVM->pdm.s.aNsGroups),
470 rc = VMR3SetError(pVM->pUVM, VERR_TOO_MUCH_DATA, RT_SRC_POS, N_("Too many bandwidth groups (max %zu)"),
471 RT_ELEMENTS(pVM->pdm.s.aNsGroups)));
472
473 rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.aNsGroups[iGroup].Lock, RT_SRC_POS, "BWGRP%02u-%s", iGroup, szName);
474 AssertRCBreak(rc);
475
476 RTListInit(&pVM->pdm.s.aNsGroups[iGroup].FilterList);
477 pVM->pdm.s.aNsGroups[iGroup].cRefs = 0;
478 RTStrCopy(pVM->pdm.s.aNsGroups[iGroup].szName, sizeof(pVM->pdm.s.aNsGroups[iGroup].szName), szName);
479 pVM->pdm.s.aNsGroups[iGroup].cbTokensLast = pdmNsBwGroupSetLimit(&pVM->pdm.s.aNsGroups[iGroup], cbMax);
480 pVM->pdm.s.aNsGroups[iGroup].tsUpdatedLast = RTTimeSystemNanoTS();
481 LogFlowFunc(("PDM NetShaper Group #%u: %s - cbPerSecMax=%#RU64 cbBucket=%#x\n",
482 iGroup, pVM->pdm.s.aNsGroups[iGroup].szName, pVM->pdm.s.aNsGroups[iGroup].cbPerSecMax,
483 pVM->pdm.s.aNsGroups[iGroup].cbBucket));
484
485 pVM->pdm.s.cNsGroups = ++iGroup;
486 }
487 }
488 if (RT_SUCCESS(rc))
489 {
490 /*
491 * If there are any groups configured, create a unchoke thread and an
492 * associated timer for waking it up when needed. The timer runs on
493 * the real time clock.
494 */
495 if (pVM->pdm.s.cNsGroups == 0)
496 {
497 LogFlowFunc(("returns VINF_SUCCESS - no groups\n"));
498 return VINF_SUCCESS;
499 }
500
501 rc = RTSemEventCreate(&pVM->pdm.s.hNsUnchokeEvt);
502 if (RT_SUCCESS(rc))
503 {
504 rc = TMR3TimerCreate(pVM, TMCLOCK_REAL, pdmR3NsUnchokeTimer, NULL, TMTIMER_FLAGS_NO_RING0,
505 "PDMNetShaperUnchoke", &pVM->pdm.s.hNsUnchokeTimer);
506 if (RT_SUCCESS(rc))
507 {
508 rc = PDMR3ThreadCreate(pVM, &pVM->pdm.s.pNsUnchokeThread, NULL, pdmR3NsUnchokeThread, pdmR3NsUnchokeWakeUp,
509 0 /*cbStack*/, RTTHREADTYPE_IO, "PDMNsUnchoke");
510 if (RT_SUCCESS(rc))
511 {
512
513 LogFlowFunc(("returns VINF_SUCCESS (%u groups)\n", pVM->pdm.s.cNsGroups));
514 return VINF_SUCCESS;
515 }
516 }
517 }
518 }
519
520 RTCritSectDelete(&pVM->pdm.s.NsLock);
521 LogRel(("pdmR3NetShaperInit: failed rc=%Rrc\n", rc));
522 return rc;
523}
524
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette