int GetLWSessionKey(Packet *p, SessionKey *key) { u_int16_t sport; u_int16_t dport; int proto; /* Because the key is going to be used for hash lookups, * the lower of the values of the IP address field is * stored in the key->ip_l and the port for that ip is * stored in key->port_l. */ if (!key) return 0; #ifdef SUP_IP6 if (IS_IP4(p)) { u_int32_t *src; u_int32_t *dst; proto = p->iph->ip_proto; switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: sport = p->sp; dport = p->dp; break; case IPPROTO_ICMP: default: sport = dport = 0; break; } src = p->ip4h.ip_src.ip32; dst = p->ip4h.ip_dst.ip32; /* These comparisons are done in this fashion for performance reasons */ if (*src < *dst) { COPY4(key->ip_l, src); COPY4(key->ip_h, dst); key->port_l = sport; key->port_h = dport; } else if (*src == *dst) { COPY4(key->ip_l, src); COPY4(key->ip_h, dst); if (sport < dport) { key->port_l = sport; key->port_h = dport; } else { key->port_l = dport; key->port_h = sport; } } else { COPY4(key->ip_l, dst); key->port_l = dport; COPY4(key->ip_h, src); key->port_h = sport; } #ifdef MPLS if(pv.overlapping_IP && (p->mpls) && isPrivateIP(*src) && isPrivateIP(*dst) ) { key->mplsLabel = p->mplsHdr.label; } else { key->mplsLabel = 0; } #endif } else { /* IPv6 */ sfip_t *src; sfip_t *dst; proto = p->ip6h.next; switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: sport = p->sp; dport = p->dp; break; case IPPROTO_ICMP: default: sport = dport = 0; break; } src = &p->ip6h.ip_src; dst = &p->ip6h.ip_dst; if (sfip_fast_lt6(src, dst)) { COPY4(key->ip_l, src->ip32); key->port_l = sport; COPY4(key->ip_h, dst->ip32); key->port_h = dport; } else if (sfip_fast_eq6(src, dst)) { COPY4(key->ip_l, src->ip32); COPY4(key->ip_h, dst->ip32); if (sport < dport) { key->port_l = sport; key->port_h = dport; } else { key->port_l = dport; key->port_h = sport; } } else { COPY4(key->ip_l, dst->ip32); key->port_l = dport; COPY4(key->ip_h, src->ip32); key->port_h = sport; } #ifdef MPLS if(pv.overlapping_IP && (p->mpls)) { key->mplsLabel = p->mplsHdr.label; } else { key->mplsLabel = 0; } #endif } #else proto = p->iph->ip_proto; switch (proto) { case IPPROTO_TCP: case IPPROTO_UDP: sport = p->sp; dport = p->dp; break; case IPPROTO_ICMP: default: sport = dport = 0; break; } /* These comparisons are done in this fashion for performance reasons */ if (IP_LESSER(GET_SRC_IP(p), GET_DST_IP(p))) { IP_COPY_VALUE(key->ip_l, GET_SRC_IP(p)); key->port_l = sport; IP_COPY_VALUE(key->ip_h, GET_DST_IP(p)); key->port_h = dport; } else if (IP_EQUALITY(GET_SRC_IP(p), GET_DST_IP(p))) { IP_COPY_VALUE(key->ip_l, GET_SRC_IP(p)); IP_COPY_VALUE(key->ip_h, GET_DST_IP(p)); if (sport < dport) { key->port_l = sport; key->port_h = dport; } else { key->port_l = dport; key->port_h = sport; } } else { IP_COPY_VALUE(key->ip_l, GET_DST_IP(p)); key->port_l = dport; IP_COPY_VALUE(key->ip_h, GET_SRC_IP(p)); key->port_h = sport; } #ifdef MPLS if(pv.overlapping_IP && (p->mpls) && isPrivateIP(key->ip_l) && isPrivateIP(key->ip_h)) { key->mplsLabel = p->mplsHdr.label; } else { key->mplsLabel = 0; } #endif #endif key->protocol = proto; if (p->vh) key->vlan_tag = (u_int16_t)VTH_VLAN(p->vh); else key->vlan_tag = 0; key->pad = 0; #ifdef MPLS key->mplsPad = 0; #endif return 1; }
/* Set the fragment, texenv (constant), and texture colors for all the * machine's texture units. */ static void setup_colors(void) { static const float frag_color[4] = {0.00, 0.25, 0.50, 0.75}; static const float env_colors[][4] = {{0.25, 0.50, 0.75, 1.00}, {0.50, 0.75, 1.00, 0.00}, {0.75, 1.00, 0.00, 0.25}, {1.00, 0.00, 0.25, 0.50}}; static const float tex_colors[][8] = { {1.00, 0.00, 0.25, 0.50}, {0.75, 1.00, 0.00, 0.25}, {0.50, 0.75, 1.00, 0.00}, {0.25, 0.50, 0.75, 1.00}, /* extra colors that'll only be used for crossbar test */ {0.00, 0.00, 0.00, 0.00}, {0.25, 0.50, 0.50, 0.00}, {0.50, 0.25, 0.75, 0.25}, {0.75, 1.00, 0.25, 0.00}}; COPY4(machine.frag_color, frag_color); glColor4fv(frag_color); for (int u = 0; u < num_tex_units; u++) { if (num_tex_units > 1) glActiveTexture(GL_TEXTURE0 + u); glBindTexture(GL_TEXTURE_2D, textures[u]); glEnable(GL_TEXTURE_2D); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT); machine.env_color[u][0] = env_colors[u % 4][0]; machine.env_color[u][1] = env_colors[u % 4][1]; machine.env_color[u][2] = env_colors[u % 4][2]; machine.env_color[u][3] = env_colors[u % 4][3]; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_colors[u % 4]); const float *tex_col = tex_colors[u % 8]; /* Setup texture color, according to texture format */ switch (machine.tex_format[u]) { case GL_RGBA: machine.tex_color[u][0] = tex_col[0]; machine.tex_color[u][1] = tex_col[1]; machine.tex_color[u][2] = tex_col[2]; machine.tex_color[u][3] = tex_col[3]; break; case GL_RGB: machine.tex_color[u][0] = tex_col[0]; machine.tex_color[u][1] = tex_col[1]; machine.tex_color[u][2] = tex_col[2]; machine.tex_color[u][3] = 1.0; break; case GL_ALPHA: machine.tex_color[u][0] = 0.0; machine.tex_color[u][1] = 0.0; machine.tex_color[u][2] = 0.0; machine.tex_color[u][3] = tex_col[3]; break; case GL_LUMINANCE: machine.tex_color[u][0] = tex_col[0]; machine.tex_color[u][1] = tex_col[0]; machine.tex_color[u][2] = tex_col[0]; machine.tex_color[u][3] = 1.0; break; case GL_LUMINANCE_ALPHA: machine.tex_color[u][0] = tex_col[0]; machine.tex_color[u][1] = tex_col[0]; machine.tex_color[u][2] = tex_col[0]; machine.tex_color[u][3] = tex_col[3]; break; case GL_INTENSITY: machine.tex_color[u][0] = tex_col[0]; machine.tex_color[u][1] = tex_col[0]; machine.tex_color[u][2] = tex_col[0]; machine.tex_color[u][3] = tex_col[0]; break; default: problem("bad texture format"); return; } /* Make a 4x4 solid color texture */ float image[16][4]; for (int i = 0; i < 16; i++) { image[i][0] = tex_colors[u % 8][0]; image[i][1] = tex_colors[u % 8][1]; image[i][2] = tex_colors[u % 8][2]; image[i][3] = tex_colors[u % 8][3]; } glTexImage2D(GL_TEXTURE_2D, 0, machine.tex_format[u], 4, 4, 0, GL_RGBA, GL_FLOAT, image); } }
/* Test texenv-combine with multiple texture units. */ static bool run_multi_texture_test(void) { static const GLenum combine_modes[10] = { GL_REPLACE, GL_ADD, GL_ADD_SIGNED_EXT, GL_MODULATE, GL_INTERPOLATE_EXT, GL_DOT3_RGB_EXT, GL_DOT3_RGBA_EXT, GL_MODULATE_ADD_ATI, GL_MODULATE_SIGNED_ADD_ATI, GL_MODULATE_SUBTRACT_ATI }; const int num_modes = have_dot3 ? (have_combine3 ? 10 : 7) : 5; /* four texture units is enough to test */ if (num_tex_units > 4) num_tex_units = 4; const int num_tests = count_multi_texture_test_combinations(); setup_colors(); for (int test_num = 0; test_num < num_tests; test_num += test_stride) { /* 0. Set up texture units */ reset_machine(); int divisor = 1; for (int u = 0; u < num_tex_units; u++) { const int m = (test_num / divisor) % num_modes; const GLenum mode = combine_modes[m]; /* Set GL_COMBINE_RGB_EXT and GL_COMBINE_ALPHA_EXT */ tex_env(u, GL_COMBINE_RGB_EXT, mode); tex_env(u, GL_COMBINE_ALPHA_EXT, (mode == GL_DOT3_RGB_EXT || mode == GL_DOT3_RGBA_EXT) ? GL_REPLACE : mode); tex_env(u, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); tex_env(u, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); tex_env(u, GL_SOURCE2_RGB_EXT, GL_TEXTURE); tex_env(u, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); tex_env(u, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); tex_env(u, GL_SOURCE2_ALPHA_EXT, GL_TEXTURE); tex_env(u, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); tex_env(u, GL_OPERAND1_RGB_EXT, GL_ONE_MINUS_SRC_COLOR); tex_env(u, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); tex_env(u, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); tex_env(u, GL_OPERAND1_ALPHA_EXT, GL_ONE_MINUS_SRC_ALPHA); tex_env(u, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA); tex_env(u, GL_RGB_SCALE_EXT, 1); tex_env(u, GL_ALPHA_SCALE, 1); divisor *= num_modes; } /* 1. Render with OpenGL */ /* use texcoord (0,0) for all vertices */ for (int u = 0; u < num_tex_units; u++) glMultiTexCoord2f(GL_TEXTURE0 + u, 0, 0); piglit_draw_rect(-1, -1, 2, 2); /* 2. Compute expected result */ float prev_color[4]; float expected[4] = {0}; COPY4(prev_color, machine.frag_color); for (int u = 0; u < num_tex_units; u++) { compute_tex_combine(u, prev_color, expected); COPY4(prev_color, expected); } /* 3. Compare rendered result to expected result */ if (!piglit_probe_pixel_rgba(0, 0, expected)) { printf("Multi-texture test %d\n", test_num); return false; } } return true; }
/* We do a really short, simple test for GL_ARB_texture_env_crossbar since the * preceeding tests are pretty comprehensive and the crossbar feature is just * an incremental addition. Basically, if we have N texture units we run N * tests. For test [i] we set texture unit [i] to fetch the texture color * from unit [num_units - i - 1]. For units != i we use the constant color * (0,0,0,0). We use GL_ADD mode to compute the sum over all units. So * effectively, the result of texture combine is simply the incoming fragment * color plus unit [num_units - test - 1]'s texture color. */ static bool run_crossbar_test() { glGetIntegerv(GL_MAX_TEXTURE_UNITS, &num_tex_units); /* Set up constant texture state for all tests */ setup_colors(); reset_machine(); for (int unit = 0; unit < num_tex_units; unit++) { tex_env(unit, GL_COMBINE_RGB_EXT, GL_ADD); tex_env(unit, GL_COMBINE_ALPHA_EXT, GL_ADD); tex_env(unit, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); tex_env(unit, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); /* SOURCE1_RGB/ALPHA is set below, per test */ tex_env(unit, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); tex_env(unit, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); tex_env(unit, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); tex_env(unit, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); tex_env(unit, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); tex_env(unit, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA); tex_env(unit, GL_RGB_SCALE_EXT, 1); tex_env(unit, GL_ALPHA_SCALE, 1); machine.env_color[unit][0] = 0.0; machine.env_color[unit][1] = 0.0; machine.env_color[unit][2] = 0.0; machine.env_color[unit][3] = 0.0; glActiveTexture(GL_TEXTURE0 + unit); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, machine.env_color[unit]); } for (int test = 0; test < num_tex_units; test++) { /* 1. Set up texture state */ for (int unit = 0; unit < num_tex_units; unit++) { if (unit == test) { const int revUnit = num_tex_units - unit - 1; tex_env(unit, GL_SOURCE1_RGB_EXT, GL_TEXTURE0 + revUnit); tex_env(unit, GL_SOURCE1_ALPHA_EXT, GL_TEXTURE0 + revUnit); } else { tex_env(unit, GL_SOURCE1_RGB_EXT, GL_CONSTANT_EXT); tex_env(unit, GL_SOURCE1_ALPHA_EXT, GL_CONSTANT_EXT); } } /* 2. Render with OpenGL */ /* texcoord (0,) for all vertices is OK */ for (int unit = 0; unit < num_tex_units; unit++) glMultiTexCoord2f(GL_TEXTURE0 + unit, 0, 0); piglit_draw_rect(-1, -1, 2, 2); /* 3. Compute expected result */ float prev_color[4]; float expected[4]; COPY4(prev_color, machine.frag_color); for (int unit = 0; unit < num_tex_units; unit++) { compute_tex_combine(unit, prev_color, expected); COPY4(prev_color, expected); } /* 4. Compare rendered result to expected result */ if (!piglit_probe_pixel_rgba(0, 0, expected)) { printf("Texture crossbar test %d\n", test); return false; } } return true; }
static int ProcessIcmpUnreach(Packet *p) { /* Handle ICMP unreachable */ SessionKey skey; SessionControlBlock *ssn = NULL; uint16_t sport; uint16_t dport; sfip_t *src; sfip_t *dst; /* No "orig" IP Header */ if (!p->orig_iph) return 0; /* Get TCP/UDP/ICMP session from original protocol/port info * embedded in the ICMP Unreach message. This is already decoded * in p->orig_foo. TCP/UDP ports are decoded as p->orig_sp/dp. */ skey.protocol = GET_ORIG_IPH_PROTO(p); sport = p->orig_sp; dport = p->orig_dp; src = GET_ORIG_SRC(p); dst = GET_ORIG_DST(p); if (sfip_fast_lt6(src, dst)) { COPY4(skey.ip_l, src->ip32); skey.port_l = sport; COPY4(skey.ip_h, dst->ip32); skey.port_h = dport; } else if (IP_EQUALITY(GET_ORIG_SRC(p), GET_ORIG_DST(p))) { COPY4(skey.ip_l, src->ip32); COPY4(skey.ip_h, skey.ip_l); if (sport < dport) { skey.port_l = sport; skey.port_h = dport; } else { skey.port_l = dport; skey.port_h = sport; } } else { COPY4(skey.ip_l, dst->ip32); COPY4(skey.ip_h, src->ip32); skey.port_l = dport; skey.port_h = sport; } if (p->vh) skey.vlan_tag = (uint16_t)VTH_VLAN(p->vh); else skey.vlan_tag = 0; switch (skey.protocol) { case IPPROTO_TCP: /* Lookup a TCP session */ ssn = GetLWTcpSession(&skey); break; case IPPROTO_UDP: /* Lookup a UDP session */ ssn = GetLWUdpSession(&skey); break; case IPPROTO_ICMP: /* Lookup a ICMP session */ ssn = session_api->get_session_by_key(icmp_lws_cache, &skey); break; } if (ssn) { /* Mark this session as dead. */ DEBUG_WRAP(DebugMessage(DEBUG_STREAM_STATE, "Marking session as dead, per ICMP Unreachable!\n");); ssn->ha_state.session_flags |= SSNFLAG_DROP_CLIENT; ssn->ha_state.session_flags |= SSNFLAG_DROP_SERVER; ssn->session_state |= STREAM_STATE_UNREACH; }