[insert project logo here (125x200px max)] Navigator Mailinglists Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums. Copyright and Licensing Information Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL). All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License. All sourcecode is made publicly available. Acknowledgement Splash and the Splash website are hosted by SourceForge.net |
Splash - DocumentationSNMP Plus a Lightweight API for SNAP Handlingsnap-1.1-wjdb/lib/bytecode.hGo to the documentation of this file.00001 /* $Id: bytecode.h,v 1.7 2003/04/02 17:01:14 wdebruij Exp $ */ 00002 00003 #include <stdio.h> 00004 #include <limits.h> 00005 #include "config.h" 00006 #include "dyncheck.h" 00007 #include "wassert.h" 00008 00009 #ifndef _SNAP_BYTECODE_H_ 00010 #define _SNAP_BYTECODE_H_ 00011 00012 #ifdef CONFIG_IP_SNAP_SMALL_INSTRS 00013 #define SMALL_INSTRS 00014 #endif 00015 #ifdef CONFIG_IP_SNAP_SMALL_VALUES 00016 #define SMALL_VALUES 00017 #endif 00018 00019 #ifdef TAG_CHECK 00020 #define DYNCHECK_TAG(v,tag) DYNCHECK(GET_TAG((v)) == (tag)) 00021 #else 00022 #define DYNCHECK_TAG(v,tag) ((void)0) 00023 #endif 00024 00025 /* having small representation for instructions requires small values 00026 as well */ 00027 #ifdef SMALL_INSTRS 00028 #ifndef SMALL_VALUES 00029 #define SMALL_VALUES 00030 #endif 00031 #endif 00032 00033 /* enumeration of all value types -- these are the tags for the values */ 00034 #ifdef SMALL_VALUES 00035 #define INTV 0 /* integers (32-bit) */ 00036 #define ADDRV 1 /* IPv4 addresses (32-bit) */ 00037 #define STRV 2 /* strings/blobs */ 00038 #define EXCV 3 /* exceptions */ 00039 #define TUPLEV 4 /* tuples */ 00040 #define FLOATV 5 /* 32-bit floats */ 00041 #define BOGUSV 6 /* for ops that ignore the tag */ 00042 #define TAG_T int 00043 00044 00045 /* not enough space to put addrs as literals when values are small */ 00046 #ifndef ADDR_IN_HEAP 00047 #define ADDR_IN_HEAP 00048 #endif 00049 00050 #else 00051 typedef enum { 00052 INTV, /* integers (32-bit) */ 00053 ADDRV, /* IPv4 addresses (32-bit) */ 00054 STRV, /* strings/blobs */ 00055 EXCV, /* exceptions */ 00056 TUPLEV, /* tuples */ 00057 FLOATV /* 32-bit floats */ 00058 } value_tag_t; 00059 #define TAG_T value_tag_t 00060 #endif 00061 00062 /* heap objects are strings */ 00063 #define LENTYPE unsigned short 00064 #define MAX_HEAPOBJ_SZ (1 << ((sizeof(unsigned short) * 8))) 00065 typedef struct { 00066 LENTYPE len; /* length of string/exc/tuple in bytes */ 00067 unsigned short flag; /* legal values 00068 0 : non-ptr-containing object 00069 1 : ptr-containing object 00070 4,8,12,... : forwarding offset */ 00071 char s[0]; /* string (maybe not null terminated) */ 00072 } heap_obj; 00073 00074 /* stack value-- has a type tag plus the value itself */ 00075 #ifdef SMALL_VALUES 00076 typedef unsigned int value_t; 00077 #define ZERO_VALUE_T 0 00078 00079 #ifdef SMALL_INSTRS 00080 #define TAGSZ 7 00081 #else 00082 #define TAGSZ 3 00083 #endif 00084 00085 #define MAX_VINT (1 << ((sizeof(unsigned int) * 8-(TAGSZ+1)))) 00086 #define MIN_VINT (- MAX_VINT - 1) 00087 00088 #define GET_TAG(v) ((v) >> (sizeof(unsigned int)*8-TAGSZ)) 00089 #define SET_TAG(v,t) ((v) = (((v) << TAGSZ) >> TAGSZ) | ((t) << (sizeof(unsigned int)*8-TAGSZ))) 00090 00091 #define GET_INT(v) (((int)((v) << TAGSZ)) >> TAGSZ) 00092 #define SET_INT(v,i) ((v) = (((v) >> (sizeof(unsigned int)*8-TAGSZ)) << (sizeof(unsigned int)*8-TAGSZ)) | ((((unsigned int)(i)) << TAGSZ) >> TAGSZ)) 00093 00094 #define GET_OFFS GET_INT 00095 #define SET_OFFS SET_INT 00096 00097 #define COPY_VAL(val1,val2) ((val1) = (val2)) 00098 00099 #define GET_BOXED(res,heap,v,t) \ 00100 { \ 00101 heap_obj *ho1 = (heap_obj *)((heap) + GET_OFFS(v)); \ 00102 DYNCHECK_ADDR_IN_HEAP(ho1); \ 00103 wassert(ho1->len == sizeof(t)); \ 00104 (res) = *((t *)ho1->s); \ 00105 } 00106 00107 #define GET_ADDR(res,h,v) GET_BOXED(res,h,v,uint32_t) 00108 00109 #define GET_FLOAT(res,h,v) GET_BOXED(res,h,v,float32) 00110 00111 #define GET_ADDR_VAL(h,v) (*((uint32_t *)(((heap_obj *)((h) + GET_OFFS(v)))->s))) 00112 00113 #define GET_FLT_VAL(h,v) (*((float32 *)(((heap_obj *)((h) + GET_OFFS(v)))->s))) 00114 00115 #define FLTINTPAIR(f) (int)(f),(int)(((f) - (int)(f)) * 1000000) 00116 00117 #define SET_ADDR(val,a,p) \ 00118 { int hoffset; \ 00119 heap_obj *ho; \ 00120 if (!heap_alloc((p),sizeof(uint32_t),0,&ho,&hoffset)) { \ 00121 *((uint32_t *)ho->s) = (a); \ 00122 SET_OFFS(val,hoffset); \ 00123 } \ 00124 else return -1; \ 00125 } 00126 #define SET_FLOAT(val,a,p) \ 00127 { int hoffset; \ 00128 heap_obj *ho; \ 00129 if (!heap_alloc((p),sizeof(float32),0,&ho,&hoffset)) {\ 00130 *((float32 *)ho->s) = (a); \ 00131 SET_OFFS(val,hoffset); \ 00132 } \ 00133 else return -1; \ 00134 } 00135 #define IS_HEAP_VAL(v) \ 00136 ((GET_TAG(v) == ADDRV) || (GET_TAG(v) == STRV) || \ 00137 (GET_TAG(v) == TUPLEV) || (GET_TAG(v) == FLOATV)) 00138 00139 #else 00140 typedef struct { 00141 TAG_T tag; /* type tag */ 00142 union { 00143 int intval; /* 32-bit integer */ 00144 #ifndef ADDR_IN_HEAP 00145 uint32_t addrval; /* 32-bit IPv4 address */ 00146 float32 floatval; /* 32-bit float */ 00147 #endif 00148 int hoffset; /* offset for a heap object */ 00149 } v; 00150 } value_t; 00151 #define ZERO_VALUE_T { 0, { 0 } } 00152 00153 #define MAX_VINT INT_MAX 00154 #define MIN_VINT INT_MIN 00155 00156 #define GET_TAG(val) ((val).tag) 00157 #define SET_TAG(val,t) ((val).tag = (t)) 00158 00159 #define GET_INT(val) ((val).v.intval) 00160 #define SET_INT(val,i) ((val).v.intval = (i)) 00161 00162 #define GET_OFFS(val) ((val).v.hoffset) 00163 #define SET_OFFS(val,o) ((val).v.hoffset = (o)) 00164 00165 #ifndef ADDR_IN_HEAP 00166 #define GET_ADDR(res,unused,val) ((res) = (val).v.addrval) 00167 #define SET_ADDR(val,a,unused) ((val).v.addrval = (a)) 00168 00169 #define GET_FLOAT(res,unused,val) ((res) = (val).v.floatval) 00170 #define SET_FLOAT(val,a,unused) ((val).v.floatval = (a)) 00171 00172 #define IS_HEAP_VAL(v) \ 00173 ((GET_TAG(v) == STRV) || (GET_TAG(v) == TUPLEV)) 00174 00175 #else 00176 #define GET_BOXED(res,heap,v,t) \ 00177 { \ 00178 heap_obj *ho1 = (heap_obj *)((heap) + GET_OFFS(v)); \ 00179 DYNCHECK_ADDR_IN_HEAP(ho1); \ 00180 wassert(ho1->len == sizeof(t)); \ 00181 (res) = *((t *)ho1->s); \ 00182 } 00183 00184 #define GET_ADDR(res,h,v) GET_BOXED(res,h,v,uint32_t) 00185 #define GET_FLOAT(res,h,v) GET_BOXED(res,h,v,float32) 00186 #define GET_ADDR_VAL(h,v) (*((uint32_t *)(((heap_obj *)((h) + GET_OFFS(v)))->s))) 00187 #define GET_FLT_VAL(h,v) (*((float32 *)(((heap_obj *)((h) + GET_OFFS(v)))->s))) 00188 00189 #define IS_HEAP_VAL(v) \ 00190 ((GET_TAG(v) == STRV) || (GET_TAG(v) == TUPLEV) || \ 00191 (GET_TAG(v) == ADDRV)) 00192 00193 #define FLTINTPAIR(f) (int)(f),(int)(((f) - (int)(f)) * 1000000) 00194 00195 #define SET_ADDR(val,a,p) \ 00196 { int hoffset; \ 00197 heap_obj *ho; \ 00198 if (!heap_alloc((p),sizeof(uint32_t),0,&ho,&hoffset)) { \ 00199 *((uint32_t *)ho->s) = (a); \ 00200 SET_OFFS(val,hoffset); \ 00201 } \ 00202 else return -1; \ 00203 } 00204 00205 #define SET_FLOAT(val,a,p) \ 00206 { int hoffset; \ 00207 heap_obj *ho; \ 00208 if (!heap_alloc((p),sizeof(float32),0,&ho,&hoffset)) {\ 00209 *((float32 *)ho->s) = (a); \ 00210 SET_OFFS(val,hoffset); \ 00211 } \ 00212 else return -1; \ 00213 } 00214 #endif 00215 00216 #define COPY_VAL(val1,val2) ((val1) = (val2)) 00217 00218 #endif 00219 00220 /* opcodes */ 00221 #ifdef SMALL_INSTRS 00222 00223 #define EXIT 0 00224 #define PUSH 1 /* not used */ 00225 #define POP 2 00226 #define POPI 3 00227 #define PULL 4 00228 #define STORE 5 00229 #define PAJ 6 00230 #define TPAJ 7 00231 #define JI 8 00232 #define BEZ 9 00233 #define BNE 10 00234 #define MKTUP 11 00235 #define NTH 12 00236 #define LEN 13 00237 #define ISTUP 14 00238 #define EQ 15 00239 #define EQI 16 /* not used */ 00240 #define NEQ 17 00241 #define NEQI 18 /* not used */ 00242 #define GT 19 00243 #define GTI 20 00244 #define GEQ 21 00245 #define GEQI 22 00246 #define LEQ 23 00247 #define LEQI 24 00248 #define LT 25 00249 #define LTI 26 00250 #define ADD 27 00251 #define ADDI 28 00252 #define SUB 29 00253 #define SUBI 30 00254 #define MULT 31 00255 #define MULTI 32 00256 #define DIV 33 00257 #define DIVI 34 00258 #define MOD 35 00259 #define MODI 36 00260 #define NEG 37 00261 #define NOT 38 00262 #define LNOT 39 00263 #define AND 40 00264 #define ANDI 41 00265 #define OR 42 00266 #define ORI 43 00267 #define LSHL 44 00268 #define LSHLI 45 00269 #define RSHL 46 00270 #define RSHLI 47 00271 #define RSHA 48 00272 #define RSHAI 49 00273 #define XOR 50 00274 #define XORI 51 00275 #define SNET 52 00276 #define SNETI 53 00277 #define BCAST 54 00278 #define BCASTI 55 00279 #define ISX 56 00280 #define GETRB 57 00281 #define GETSRC 58 00282 #define GETDST 60 00283 #define GETSPT 61 00284 #define HERE 62 00285 #define ISHERE 63 00286 #define ROUTE 64 00287 #define RTDEV 65 00288 #define SEND 66 00289 #define HOP 67 00290 /* #define SENDCK 67 */ 00291 /* #define HOPCK 68 */ 00292 #define FORW 69 00293 #define FORWTO 70 00294 #define DEMUX 71 00295 #define DEMUXI 72 00296 #define PRINT 73 00297 00298 #define PINT 74 00299 #define PADDR 75 00300 #define PTUP 76 00301 #define PEXC 77 00302 #define PSTR 78 00303 #define PFLT 79 00304 00305 #define EQINT 80 00306 #define EQADR 81 00307 #define EQTUP 82 00308 #define EQEXC 83 00309 #define EQSTR 84 00310 #define EQFLT 85 00311 00312 #define NQINT 86 00313 #define NQADR 87 00314 #define NQTUP 88 00315 #define NQEXC 89 00316 #define NQSTR 90 00317 #define NQFLT 91 00318 00319 #define SVCV 92 00320 #define CALLS 93 00321 00322 #define FGTI 94 00323 #define FGEQI 95 00324 #define FLEQI 96 00325 #define FLTI 97 00326 #define FADDI 98 00327 #define FSUBI 99 00328 #define FMULI 100 00329 #define FDIVI 101 00330 00331 #define GETLD 102 00332 #define SETXH 103 00333 #define RAISEX 104 00334 00335 /* willem's additions */ 00336 00337 #define DSEND 105 /* direct send (no interpretation on intermediate hops) */ 00338 #define DFORW 106 /* idem for forw */ 00339 #define DFORWTO 107 /* idem for forwto */ 00340 00341 #define STACKEMPTY 108 /* pushes a 1 if the stack is empty, 0 otherwise */ 00342 #define STACKCOUNT 109 /* pushes the number of elements on the stack */ 00343 00344 #define PULLSTACK 110 /* PULL using top stack element as index (this value is removed */ 00345 #define OPCODE_T int 00346 00347 /* operations on literals */ 00348 /* assumes that TAGSZ is set appropriately above */ 00349 00350 #define GET_OP(v) ((v) >> (sizeof(unsigned int)*8-TAGSZ)) 00351 #define SET_OP(v,i) ((v) = (((v) << TAGSZ) >> TAGSZ) | ((i) << (sizeof(unsigned int)*8-TAGSZ))) 00352 00353 #define GET_LIT(l,t,i) ((l) = (((int)((i) << TAGSZ)) >> TAGSZ)) 00354 #define SET_LIT(i,t,l) ((i) = (((i) >> (sizeof(unsigned int)*8-TAGSZ)) << (sizeof(unsigned int)*8-TAGSZ)) | ((((unsigned int)(l)) << TAGSZ) >> TAGSZ)) 00355 00356 #define GET_LIT_VAL(i) (((int)((i) << TAGSZ)) >> TAGSZ) 00357 00358 #define GET_STR_VAL(h,v) (((heap_obj *)((h) + GET_OFFS(v)))->s) 00359 00360 #define NUM_OPS 87 /* total number of (legal) opcodes */ 00361 00362 typedef unsigned int instr_t; 00363 00364 #else 00365 typedef enum { 00366 /* stack and flow control */ 00367 EXIT, 00368 PUSH, /* push a value on the stack */ 00369 POP, /* pop the top value off the stack */ 00370 POPI, /* pop the top n values off the stack */ 00371 PULL, /* push a copy of the nth stack value */ 00372 STORE, /* store the top of the stack into the 00373 nth stack value (thus store 0 is 00374 a no-op) */ 00375 PAJ, /* jump by the value on the top of the 00376 stack (pop and jump) plus the given 00377 immediate value */ 00378 TPAJ, /* jump by the 2nd value on the top of 00379 the stack, plus the immediate 00380 value,if the top value is zero 00381 (test, pop, and jump) */ 00382 JI, /* jump by the immediate value */ 00383 BEZ, /* branch x instrs if the top stack 00384 value is equal to zero */ 00385 BNE, /* branch x instrs if the top stack 00386 value is not zero */ 00387 00388 /* heap operations */ 00389 MKTUP, /* allocates a tuple that holds n 00390 values, where n>0 is an immediate. 00391 Must be followed by n-1 (JI 1) 00392 instructions */ 00393 NTH, /* get's the nTH entry of the tuple 00394 on the top of the stack, where 00395 n is an immediate > 0 */ 00396 LEN, /* returns the length of the tuple, 00397 that is, how many values it 00398 contains. */ 00399 ISTUP, /* is the top value a tuple? */ 00400 00401 /* relational operators */ 00402 EQ, /* are the top two stack values equal? */ 00403 EQI, /* is the top stack value equal to the 00404 immediate argument? */ 00405 NEQ, /* are the top two stack values not equal? */ 00406 NEQI, /* is the top stack value not equal to the 00407 immediate argument? */ 00408 GT, /* comparing top 2 values: v2 > v1 */ 00409 GTI, /* top > immediate */ 00410 GEQ, /* comparing top 2 values: v2 >= v1 */ 00411 GEQI, /* top >= immediate */ 00412 LEQ, /* comparing top 2 values: v2 <= v1 */ 00413 LEQI, /* top <= immediate */ 00414 LT, /* comparing top 2 values: v2 < v1 */ 00415 LTI, /* top < immediate */ 00416 00417 /* arithmetic */ 00418 ADD, /* integer addition */ 00419 ADDI, /* integer addition with immediate */ 00420 SUB, /* integer subtraction */ 00421 SUBI, /* integer subtraction with immediate */ 00422 MULT, /* integer multiplication */ 00423 MULTI, /* integer multiplication with immediate*/ 00424 DIV, /* integer division */ 00425 DIVI, /* integer division with immediate */ 00426 MOD, /* integer modulus */ 00427 MODI, /* integer modulus with immediate */ 00428 NEG, /* integer arithmetic negation */ 00429 NOT, /* integer boolean negation */ 00430 LNOT, /* integer logical negation */ 00431 AND, /* integer logical and */ 00432 ANDI, /* integer logical and with immediate */ 00433 OR, /* integer logical or */ 00434 ORI, /* integer logical or with immediate */ 00435 LSHL, /* integer left shift logical */ 00436 LSHLI, /* integer left shift logical with immediate */ 00437 RSHL, /* integer right shift logical */ 00438 RSHLI, /* integer right shift logical with 00439 immediate */ 00440 RSHA, /* integer right shift arithmetic */ 00441 RSHAI, /* integer right shift arithmetic with 00442 immediate */ 00443 XOR, /* integer logical xor */ 00444 XORI, /* integer logical xor with immediate */ 00445 00446 /* operations on addresses */ 00447 SNET, /* given an address and a subnet mask, 00448 give the subnet address */ 00449 SNETI, /* subnet with immediate mask */ 00450 BCAST, /* given an address and a subnet mask, 00451 give the broadcast address */ 00452 BCASTI, /* broadcast address with immed. mask */ 00453 00454 /* operations on exceptions */ 00455 ISX, /* is the top value an exception? */ 00456 00457 /* core services */ 00458 GETRB, /* get the resource bound field */ 00459 GETSRC, /* get the source field */ 00460 GETDST, /* get the destination field */ 00461 GETSPT, /* get the flow id */ 00462 HERE, /* push an address of the current host */ 00463 ISHERE, /* does the address on top of the 00464 stack belong to the current host? */ 00465 ROUTE, /* determine the next hop to send to */ 00466 RTDEV, /* next hop and outgoing interface */ 00467 SEND, /* OnRemote w/ literal: args are: 00468 entry point, how many values of 00469 stack to take, how much resource 00470 bound, destination. side effects 00471 the header dest and source fields of 00472 outgoing packet */ 00473 HOP, /* OnNeighbor w/ literal: args are: 00474 entry point, 00475 stack amount, 00476 resource bound, 00477 neighbor */ 00478 /* SENDCK, */ /* OnRemote: same as SEND, except 00479 (entrypoint,how much stack) args 00480 replaced with a chunk. */ 00481 /* HOPCK, */ /* OnNeighbor: same as HOP, except 00482 (entrypoint,how much stack) args 00483 replaced with a chunk. */ 00484 FORW, /* if at destination, do nothing. else 00485 forward packet towards destination 00486 and exit */ 00487 FORWTO, /* arg is final destination. if there, 00488 do nothing. else set header's src 00489 and dst appropriately and forward */ 00490 00491 DEMUX, /* application delivery: args are: 00492 UDP port, string */ 00493 DEMUXI, /* same, but port num is immediate */ 00494 PRINT, /* print value to console */ 00495 00496 /* general services */ 00497 SVCV, /* returns (non-function) value with 00498 given name from the service symtab */ 00499 CALLS, /* invokes service routine with given 00500 string */ 00501 00502 /* willem's additions */ 00503 , 00504 DSEND, /* direct send (no interpretation on intermediate hops) */ 00505 DFORW, /* idem for forw */ 00506 DFORWTO, /* idem for forwto */ 00507 00508 STACKEMPTY, /* pushes a 1 if the stack is empty, 0 otherwise */ 00509 STACKCOUNT, /* pushes the number of elements on the stack */ 00510 00511 PULLSTACK /* PULL using top stack element as index (this value is removed */ 00512 } opcode_t; 00513 00514 #define OPCODE_T opcode_t 00515 00516 /* operations on literals */ 00517 00518 #define GET_LIT(l,t,i) \ 00519 DYNCHECK_TAG((i).arg,t); \ 00520 (l) = GET_INT((i).arg); /* assumes this is the same as GET_OFFS */ 00521 00522 #define SET_LIT(i,t,l) \ 00523 SET_INT((i).arg,(l)); /* all ints anyway */ \ 00524 SET_TAG((i).arg,(t)); 00525 00526 #define GET_OP(i) ((i).op) 00527 #define SET_OP(i,t) ((i).op = (t)) 00528 00529 #define NUM_OPS 73 /* total number of opcodes */ 00530 00531 /* instructions are an opcode with an (optional) argument */ 00532 typedef struct { 00533 OPCODE_T op; 00534 value_t arg; 00535 } instr_t; 00536 00537 #endif 00538 00539 #define COPY_LIT(d,t,s) \ 00540 { int _lit; \ 00541 GET_LIT(_lit,t,(s)); \ 00542 SET_INT((d),_lit); \ 00543 SET_TAG((d),t); \ 00544 } 00545 00546 #endif /* _SNAP_BYTECODE_H_ */ |