1 #include <stdio.h> 2 #include <string.h> 3 #include <stdint.h> 4 //#include <sys/socket.h> 5 #include <netinet/in.h> 6 #include <arpa/inet.h> 7 #include <stdlib.h> 8 #include <unistd.h> 9 10 //static int num_queue = 4; 11 12 /*-------------------------------------------------------------*/ 13 static void 14 BuildKeyCache(uint32_t *cache, int cache_len) 15 { 16 #define NBBY 8 /* number of bits per byte */ 17 18 // 16bit test set 19 /* 20 static const uint8_t key[] = { 21 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 22 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 23 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 24 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 25 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00 26 }; 27 */ 28 /* 29 static const uint8_t key[] = { 30 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 31 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 32 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 33 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 34 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a, 0x6d, 0x5a 35 }; 36 */ 37 38 /* 39 static const uint8_t key[] = { 40 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 41 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 42 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 43 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 44 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff 45 }; 46 */ 47 48 // 32bit test set 49 /* 50 static const uint8_t key[] = { 51 0x6d, 0x5a, 0x56, 0x25, 0x6d, 0x5a, 0x56, 0x25, 52 0x6d, 0x5a, 0x56, 0x25, 0x6d, 0x5a, 0x56, 0x25, 53 0x6d, 0x5a, 0x56, 0x25, 0x6d, 0x5a, 0x56, 0x25, 54 0x6d, 0x5a, 0x56, 0x25, 0x6d, 0x5a, 0x56, 0x25, 55 0x6d, 0x5a, 0x56, 0x25, 0x6d, 0x5a, 0x56, 0x25 56 }; 57 */ 58 /* ixgbe driver had a different set of keys than that of Microsoft 59 RSS keys */ 60 /* static const uint8_t key[] = { 61 0x3D, 0xD7, 0x91, 0xE2, 62 0x6C, 0xEC, 0x05, 0x18, 63 0x0D, 0xB3, 0x94, 0x2A, 64 0xEC, 0x2B, 0x4F, 0xA5, 65 0x7C, 0xAF, 0x49, 0xEA, 66 0x3D, 0xAD, 0x14, 0xE2, 67 0xBE, 0xAA, 0x55, 0xB8, 68 0xEA, 0x67, 0x3E, 0x6A, 69 0x17, 0x4D, 0x36, 0x14, 70 0x0D, 0x20, 0xED, 0x3B}; 71 */ 72 73 #if 0 74 /* Microsoft RSS keys */ 75 static const uint8_t key[] = { 76 0x6d, 0x5a, 0x56, 0xda, 0x25, 0x5b, 0x0e, 0xc2, 77 0x41, 0x67, 0x25, 0x3d, 0x43, 0xa3, 0x8f, 0xb0, 78 0xd0, 0xca, 0x2b, 0xcb, 0xae, 0x7b, 0x30, 0xb4, 79 0x77, 0xcb, 0x2d, 0xa3, 0x80, 0x30, 0xf2, 0x0c, 80 0x6a, 0x42, 0xb7, 0x3b, 0xbe, 0xac, 0x01, 0xfa 81 }; 82 #endif 83 /* Keys for system testing */ 84 static const uint8_t key[] = { 85 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 86 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 87 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 88 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 89 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05 90 }; 91 92 uint32_t result = (((uint32_t)key[0]) << 24) | (((uint32_t)key[1]) << 16) | (((uint32_t)key[2]) << 8) | ((uint32_t)key[3]); 93 uint32_t idx = 32; 94 int i; 95 96 for (i = 0; i < cache_len; i++, idx++) { 97 uint8_t shift = (idx % NBBY); 98 uint32_t bit; 99 100 cache[i] = result; 101 bit = ((key[idx/NBBY] << shift) & 0x80) ? 1 : 0; 102 result = ((result << 1) | bit); 103 } 104 105 } 106 /*-------------------------------------------------------------*/ 107 static uint32_t 108 GetRSSHash(in_addr_t sip, in_addr_t dip, in_port_t sp, in_port_t dp) 109 { 110 #define MSB32 0x80000000 111 #define MSB16 0x8000 112 #define KEY_CACHE_LEN 96 113 114 uint32_t res = 0; 115 int i; 116 static int first = 1; 117 static uint32_t key_cache[KEY_CACHE_LEN] = {0}; 118 119 if (first) { 120 BuildKeyCache(key_cache, KEY_CACHE_LEN); 121 first = 0; 122 } 123 124 for (i = 0; i < 32; i++) { 125 if (sip & MSB32) 126 res ^= key_cache[i]; 127 sip <<= 1; 128 } 129 for (i = 0; i < 32; i++) { 130 if (dip & MSB32) 131 res ^= key_cache[32+i]; 132 dip <<= 1; 133 } 134 for (i = 0; i < 16; i++) { 135 if (sp & MSB16) 136 res ^= key_cache[64+i]; 137 sp <<= 1; 138 } 139 for (i = 0; i < 16; i++) { 140 if (dp & MSB16) 141 res ^= key_cache[80+i]; 142 dp <<= 1; 143 } 144 return res; 145 } 146 /*-------------------------------------------------------------------*/ 147 /* RSS redirection table is in the little endian byte order (intel) */ 148 /* */ 149 /* idx: 0 1 2 3 | 4 5 6 7 | 8 9 10 11 | 12 13 14 15 | 16 17 18 19 ...*/ 150 /* val: 3 2 1 0 | 7 6 5 4 | 11 10 9 8 | 15 14 13 12 | 19 18 17 16 ...*/ 151 /* qid = val % num_queues */ 152 /*-------------------------------------------------------------------*/ 153 #if 0 154 int 155 GetRSSCPUCore(in_addr_t sip, in_addr_t dip, 156 in_port_t sp, in_port_t dp, int num_queues) 157 { 158 #define RSS_BIT_MASK 0x0000007F 159 160 uint32_t masked = GetRSSHash(sip, dip, sp, dp) & RSS_BIT_MASK; 161 162 #ifndef ENABLE_DPDK 163 static const uint32_t off[4] = {3, 1, -1, -3}; 164 masked += off[masked & 0x3]; 165 #endif 166 return (masked % num_queues); 167 168 } 169 #endif 170 #if _TEST_RSS_ 171 /*-------------------------------------------------------------*/ 172 static void 173 VerifyRSSHash(void) 174 { 175 in_addr_t faddr, laddr; 176 in_port_t fport, lport; 177 char *src[] = {"66.9.149.187", 178 "199.92.111.2", 179 "24.19.198.95", 180 "38.27.205.30", 181 "153.39.163.191"}; 182 char *dest[] = {"161.142.100.80", 183 "65.69.140.83", 184 "12.22.207.184", 185 "209.142.163.6", 186 "202.188.127.2"}; 187 in_port_t src_port[] = {2794, 14230, 12898, 48228, 44251}; 188 in_port_t dest_port[] = {1766, 4739, 38024, 2217, 1303}; 189 uint32_t correct_hash[] = {0x51ccc178, 190 0xc626b0ea, 191 0x5c2b394a, 192 0xafc7327f, 193 0x10e828a2}; 194 int i; 195 196 /* 197 * RSS hash calculation verification example is from 198 * http://msdn.microsoft.com/en-us/library/ff571021%28v=vs.85%29.aspx 199 */ 200 201 for (i = 0; i < 5; i++) { 202 struct in_addr addr; 203 204 if (inet_aton(src[i], &addr) == 0) { 205 fprintf(stderr, "inet_aton error\n"); 206 exit(-1); 207 } 208 faddr = ntohl(addr.s_addr); 209 210 if (inet_aton(dest[i], &addr) == 0) { 211 fprintf(stderr, "inet_aton error\n"); 212 exit(-1); 213 } 214 laddr = ntohl(addr.s_addr); 215 216 fport = src_port[i]; 217 lport = dest_port[i]; 218 219 printf("(%15s %15s %5d %5d) 0x%08x, correct_hash: 0x%08x\n", 220 src[i], dest[i], src_port[i], dest_port[i], 221 GetRSSHash(faddr, laddr, fport, lport), correct_hash[i]); 222 } 223 } 224 225 static unsigned long next = 2192123; 226 unsigned int myrand(void){ 227 next = next * 1103515245 + 12345; 228 return next/65536; 229 } 230 231 static void 232 CheckRSSHash(int cnt, const char* src_ip, const char* dest_ip, int32_t src_port, int32_t dest_port) 233 { 234 235 struct in_addr saddr, daddr; 236 char saddr_str[15], daddr_str[15]; 237 in_port_t sport, dport; 238 long queue_cnt[num_queue]; 239 int queue_idx; 240 241 242 int i; 243 for( i = 0; i < num_queue; i++) 244 { 245 queue_cnt[i] = 0; 246 } 247 248 printf("src\tdest\tqueue_idx\n"); 249 250 for( i =0; i < cnt; i++){ 251 // Only generate src/dest address when no address specified 252 if (src_ip == NULL) { 253 saddr.s_addr = (in_addr_t) myrand(); 254 } else { 255 if (inet_aton(src_ip, &saddr) == 0) saddr.s_addr = (in_addr_t) myrand(); 256 } 257 if (dest_ip == NULL) { 258 daddr.s_addr = (in_addr_t) myrand(); 259 } else { 260 if (inet_aton(dest_ip, &daddr) == 0) daddr.s_addr = (in_addr_t) myrand(); 261 } 262 263 int32_t ports = (int32_t) myrand(); 264 if (src_port > 0) { 265 sport = htons(src_port); 266 } else { 267 sport = ports; 268 } 269 if (dest_port > 0) { 270 dport = htons(dest_port); 271 } else { 272 dport = ports >> 16; 273 } 274 275 //get rss hash 276 queue_idx = GetRSSCPUCore(saddr.s_addr, daddr.s_addr, sport, dport, num_queue); 277 //create logs 278 strncpy(saddr_str, inet_ntoa(saddr), 15); 279 strncpy(daddr_str, inet_ntoa(daddr), 15); 280 printf("%15s:%5d\t%15s:%5d\t%d\n", saddr_str, ntohs(sport), daddr_str, ntohs(dport), queue_idx); 281 282 queue_idx = GetRSSCPUCore(daddr.s_addr, saddr.s_addr, dport, sport, num_queue); 283 printf("%15s:%5d\t%15s:%5d\t%d\n", daddr_str, ntohs(dport), saddr_str, ntohs(sport), queue_idx); 284 285 queue_cnt[queue_idx]++; 286 } 287 288 printf("\n-----summary-----\n"); 289 for( i = 0; i < num_queue; i++) 290 { 291 printf("%ld\n", queue_cnt[i]); 292 } 293 printf("\n"); 294 295 } 296 297 void 298 print_usage(int argc, char** argv){ 299 printf("Usage: %s -c number_of_test_ip [options]\n", argv[0]); 300 printf("Options:\n"); 301 printf(" -r seed(long) : Specifiy random seed\n"); 302 printf(" -s srcIP : Source IP address\n"); 303 printf(" -S srcPort : Source port number\n"); 304 printf(" -d destIP : Destination IP address\n"); 305 printf(" -D destPort : Destination port number\n"); 306 printf("Any of source/destination IP/port could be omitted.\n"); 307 printf("If absent, random generated address is used.\n"); 308 } 309 310 /*-------------------------------------------------------------*/ 311 int 312 main(int argc, char** argv) 313 { 314 int opt; 315 int cnt = -1; 316 long seed = -1; 317 int32_t sport = -1, dport = -1; 318 char *srcIP = 0, *destIP = 0; 319 while ((opt=getopt(argc, argv, "c:r:sS:dD:")) != -1) { 320 switch (opt) { 321 case 'c': 322 cnt = atoi(optarg); 323 break; 324 case 'r': 325 seed = atol(optarg); 326 break; 327 case 's': 328 srcIP = strdup(argv[optind]); 329 break; 330 case 'S': 331 sport = atoi(optarg); 332 break; 333 case 'd': 334 destIP = strdup(argv[optind]); 335 break; 336 case 'D': 337 dport = atoi(optarg); 338 break; 339 } 340 } 341 342 if (cnt < 1) { 343 print_usage(argc, argv); 344 exit(0); 345 } 346 if (seed > 0) next = seed; 347 348 // Test configuration: 349 // 10.10.4.11:X (rock5) -> 10.10.2.10:80 (rock4) 350 CheckRSSHash(cnt, srcIP, destIP, sport, dport); 351 352 if (srcIP) free(srcIP); 353 if (destIP) free(destIP); 354 return 0; 355 } 356 #endif 357