static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
{
	struct {
		struct tc_u32_sel sel;
		struct tc_u32_key keys[128];
	} sel;
	struct tcmsg *t = NLMSG_DATA(n);
	struct rtattr *tail;
	int sel_ok = 0;
	int sample_ok = 0;
	__u32 htid = 0;
	__u32 order = 0;

	memset(&sel, 0, sizeof(sel));

	if (handle && get_u32_handle(&t->tcm_handle, handle)) {
		fprintf(stderr, "Illegal filter ID\n");
		return -1;
	}

	if (argc == 0)
		return 0;

	tail = (struct rtattr*)(((void*)n)+NLMSG_ALIGN(n->nlmsg_len));
	addattr_l(n, 4096, TCA_OPTIONS, NULL, 0);

	while (argc > 0) {
		if (matches(*argv, "match") == 0) {
			NEXT_ARG();
			if (parse_selector(&argc, &argv, &sel.sel)) {
				fprintf(stderr, "Illegal \"match\"\n");
				return -1;
			}
			sel_ok++;
			continue;
		} else if (matches(*argv, "offset") == 0) {
			NEXT_ARG();
			if (parse_offset(&argc, &argv, &sel.sel)) {
				fprintf(stderr, "Illegal \"offset\"\n");
				return -1;
			}
			continue;
		} else if (matches(*argv, "hashkey") == 0) {
			NEXT_ARG();
			if (parse_hashkey(&argc, &argv, &sel.sel)) {
				fprintf(stderr, "Illegal \"hashkey\"\n");
				return -1;
			}
			continue;
		} else if (matches(*argv, "classid") == 0 ||
			   strcmp(*argv, "flowid") == 0) {
			unsigned handle;
			NEXT_ARG();
			if (get_tc_classid(&handle, *argv)) {
				fprintf(stderr, "Illegal \"classid\"\n");
				return -1;
			}
			addattr_l(n, 4096, TCA_U32_CLASSID, &handle, 4);
			sel.sel.flags |= TC_U32_TERMINAL;
		} else if (matches(*argv, "divisor") == 0) {
			unsigned divisor;
			NEXT_ARG();
			if (get_unsigned(&divisor, *argv, 0) || divisor == 0 ||
			    divisor > 0x100) {
				fprintf(stderr, "Illegal \"divisor\"\n");
				return -1;
			}
			addattr_l(n, 4096, TCA_U32_DIVISOR, &divisor, 4);
		} else if (matches(*argv, "order") == 0) {
			NEXT_ARG();
			if (get_u32(&order, *argv, 0)) {
				fprintf(stderr, "Illegal \"order\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "link") == 0) {
			unsigned handle;
			NEXT_ARG();
			if (get_u32_handle(&handle, *argv)) {
				fprintf(stderr, "Illegal \"link\"\n");
				return -1;
			}
			if (handle && TC_U32_NODE(handle)) {
				fprintf(stderr, "\"link\" must be a hash table.\n");
				return -1;
			}
			addattr_l(n, 4096, TCA_U32_LINK, &handle, 4);
		} else if (strcmp(*argv, "ht") == 0) {
			unsigned handle;
			NEXT_ARG();
			if (get_u32_handle(&handle, *argv)) {
				fprintf(stderr, "Illegal \"ht\"\n");
				return -1;
			}
			if (handle && TC_U32_NODE(handle)) {
				fprintf(stderr, "\"ht\" must be a hash table.\n");
				return -1;
			}
			if (sample_ok)
				htid = (htid&0xFF000)|(handle&0xFFF00000);
			else
				htid = (handle&0xFFFFF000);
		} else if (strcmp(*argv, "sample") == 0) {
			__u32 hash;
			struct {
				struct tc_u32_sel sel;
				struct tc_u32_key keys[4];
			} sel2;
			NEXT_ARG();
			if (parse_selector(&argc, &argv, &sel2.sel)) {
				fprintf(stderr, "Illegal \"sample\"\n");
				return -1;
			}
			if (sel2.sel.nkeys != 1) {
				fprintf(stderr, "\"sample\" must contain exactly ONE key.\n");
				return -1;
			}
			hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask;
			hash ^= hash>>16;
			hash ^= hash>>8;
			htid = ((hash<<12)&0xFF000)|(htid&0xFFF00000);
			sample_ok = 1;
			continue;
#ifdef TC_CONFIG_ALL
		} else if (matches(*argv, "police") == 0) {
static int u32_parse_opt(struct filter_util *qu, char *handle, int argc, char **argv, struct nlmsghdr *n)
{
	struct {
		struct tc_u32_sel sel;
		struct tc_u32_key keys[128];
	} sel;
	struct tcmsg *t = NLMSG_DATA(n);
	struct rtattr *tail;
	int sel_ok = 0;
	int sample_ok = 0;
	__u32 htid = 0;
	__u32 order = 0;

	memset(&sel, 0, sizeof(sel));

//fprintf(stderr, "handle[%s]\n", handle);

	if (handle && get_u32_handle(&t->tcm_handle, handle)) {
		fprintf(stderr, "Illegal filter ID\n");
		return -1;
	}

	if (argc == 0)
		return 0;



	tail = NLMSG_TAIL(n);
	addattr_l(n, MAX_MSG, TCA_OPTIONS, NULL, 0);

	while (argc > 0) {
		if (matches(*argv, "match") == 0) {
			NEXT_ARG();
			if (parse_selector(&argc, &argv, &sel.sel, n)) {
				fprintf(stderr, "Illegal \"match\"\n");
				return -1;
			}
			sel_ok++;
			continue;
		} else if (matches(*argv, "offset") == 0) {
			NEXT_ARG();
			if (parse_offset(&argc, &argv, &sel.sel)) {
				fprintf(stderr, "Illegal \"offset\"\n");
				return -1;
			}
			continue;
		} else if (matches(*argv, "hashkey") == 0) {
			NEXT_ARG();
			if (parse_hashkey(&argc, &argv, &sel.sel)) {
				fprintf(stderr, "Illegal \"hashkey\"\n");
				return -1;
			}
			continue;
		} else if (matches(*argv, "classid") == 0 ||
			   strcmp(*argv, "flowid") == 0) {
			unsigned handle;
			NEXT_ARG();
			if (get_tc_classid(&handle, *argv)) {
				fprintf(stderr, "Illegal \"classid\"\n");
				return -1;
			}
			addattr_l(n, MAX_MSG, TCA_U32_CLASSID, &handle, 4);
			sel.sel.flags |= TC_U32_TERMINAL;
		} else if (matches(*argv, "divisor") == 0) {
			unsigned int divisor;
fprintf(stderr, "parse divisor\n");
			NEXT_ARG();
			if (get_unsigned(&divisor, *argv, 0) || 
			    divisor == 0 ||
			   //divisor > 0x100 || ((divisor - 1) & divisor)) {//richie1124
			   divisor > 0x1000 || ((divisor - 1) & divisor)) {
				fprintf(stderr, "Illegal \"divisor\"\n");
				return -1;
			}
			addattr_l(n, MAX_MSG, TCA_U32_DIVISOR, &divisor, 4);
		} else if (matches(*argv, "order") == 0) {
			NEXT_ARG();
			if (get_u32(&order, *argv, 0)) {
				fprintf(stderr, "Illegal \"order\"\n");
				return -1;
			}
		} else if (strcmp(*argv, "link") == 0) {
			unsigned handle;
			NEXT_ARG();
			if (get_u32_handle(&handle, *argv)) {
				fprintf(stderr, "Illegal \"link\"\n");
				return -1;
			}
			if (handle && TC_U32_NODE(handle)) {
				fprintf(stderr, "\"link\" must be a hash table.\n");
				return -1;
			}
			addattr_l(n, MAX_MSG, TCA_U32_LINK, &handle, 4);
		} else if (strcmp(*argv, "ht") == 0) {
			unsigned handle;
			NEXT_ARG();
			if (get_u32_handle(&handle, *argv)) {
				fprintf(stderr, "Illegal \"ht\"\n");
				return -1;
			}
//fprintf(stderr, "f_u32, handle[%x]\n", handle);
			if (handle && TC_U32_NODE(handle)) {
				fprintf(stderr, "\"ht\" must be a hash table.\n");
				return -1;
			}
			if (sample_ok)
			{
				//htid = (htid&0xFF000)|(handle&0xFFF00000);
				//htid = (htid&0xFFF00)|(handle&0xFFF00000);
				htid = (htid&0xFFF00)|(handle&0xFFF00000);//richie1124
			}
			else
			{
				//htid = (handle&0xFFFFF000);
				htid = (handle&0xFFFFFF00);
				//htid = (handle&0xFFFFFF00);//richie1124
			}
		} else if (strcmp(*argv, "sample") == 0) {
			__u32 hash;
			unsigned divisor = 0x100;

			struct {
				struct tc_u32_sel sel;
				struct tc_u32_key keys[4];
			} sel2;
			memset(&sel2, 0, sizeof(sel2));
			NEXT_ARG();
			if (parse_selector(&argc, &argv, &sel2.sel, n)) {
				fprintf(stderr, "Illegal \"sample\"\n");
				return -1;
			}
			if (sel2.sel.nkeys != 1) {
				fprintf(stderr, "\"sample\" must contain exactly ONE key.\n");
				return -1;
			}
			if (*argv != 0 && strcmp(*argv, "divisor") == 0) {
				NEXT_ARG();
				if (get_unsigned(&divisor, *argv, 0) || divisor == 0 ||
				    divisor > 0x100 || ((divisor - 1) & divisor)) {
					fprintf(stderr, "Illegal sample \"divisor\"\n");
					return -1;
				}
				NEXT_ARG();
			}
			hash = sel2.sel.keys[0].val&sel2.sel.keys[0].mask;
			hash ^= hash>>16;
			hash ^= hash>>8;
			htid = ((hash%divisor)<<12)|(htid&0xFFF00000);
			sample_ok = 1;
			continue;
		} else if (strcmp(*argv, "indev") == 0) {