Index: linux-4.1.52/include/uapi/linux/gen_stats.h =================================================================== --- linux-4.1.52.orig/include/uapi/linux/gen_stats.h 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/include/uapi/linux/gen_stats.h 2018-01-22 14:21:12.857630793 +0800 @@ -26,6 +26,9 @@ struct gnet_stats_basic_packed { __u64 bytes; __u32 packets; +#if 1 /* ZyXEL QoS, porting from MSTC */ + __u64 dropbytes; +#endif } __attribute__ ((packed)); /** @@ -36,6 +39,9 @@ struct gnet_stats_rate_est { __u32 bps; __u32 pps; +#if 1 /* ZyXEL QoS, porting from MSTC */ + __u32 dropbps; +#endif }; /** @@ -46,6 +52,9 @@ struct gnet_stats_rate_est64 { __u64 bps; __u64 pps; +#if 1 /* ZyXEL QoS, porting from MSTC */ + __u64 dropbps; +#endif }; /** Index: linux-4.1.52/include/uapi/linux/netfilter/xt_AUTOMAP.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/include/uapi/linux/netfilter/xt_AUTOMAP.h 2018-01-22 14:21:12.857630793 +0800 @@ -0,0 +1,65 @@ +/* x_tables module for setting the IPv4/IPv6 DSCP field + * + * (C) 2002 Harald Welte + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh + * This software is distributed under GNU GPL v2, 1991 + * + * See RFC2474 for a description of the DSCP field within the IP Header. + * + * xt_DSCP.h,v 1.7 2002/03/14 12:03:13 laforge Exp +*/ +#ifndef _XT_AUTOMAP_TARGET_H +#define _XT_AUTOMAP_TARGET_H + +#define XT_AUTO_TYPE 0x1 +//#define XT_AUTO_MARK 0x2 +//#define XT_AUTO_DSCP 0x4 +//#define XT_AUTO_ETHPRI 0x8 + +/*Automapping Type*/ +#define AUTOMAP_TYPE_8021P 0x1 +#define AUTOMAP_TYPE_DSCP 0x2 +#define AUTOMAP_TYPE_PKTLEN 0x4 + +#define DSCP_MASK_SHIFT 5 +#define ETHERPRI_MARK_SHIFT 12 + + /* + Auto Priority Mapping Table + + + DSCP | Packet Length | 802.1P | Queue | + --------------------------------------------- + | | 001 | 0 | + | | | | + | | 010 | 1 | + | | | | + 0x00 | >1100 | 000 | 2 | + | | | | + 0x08 | 250-1100 | 011 | 3 | + | | | | + 0x10 | | 100 | 4 | + | | | | + 0x18 | <250 | 101 | 5 | + | | | | + 0x20,0x28 | | 110 | 6 | + | | | | + 0x30,0x38 | | 111 | 7 | + */ + + +/* accoding to tr181 8021p to DSCP mapping table(upstream) higher value higher priority */ +unsigned short vlan8021pToDSCP[8]= {0x00,0x00,0x00,0x08,0x10,0x18,0x28,0x38}; +unsigned short dscpPrecedenceTo8021p[8] = {0,3,4,5,6,6,7,7}; + +unsigned short vlan8021pToPriorityQueue[8] = {2,0,1,3,4,5,6,7}; +unsigned short dscpPrecedenceToPriorityQueue[8] = {2,3,4,5,6,6,7,7}; + +/* target info */ +struct xt_automap_target_info { + int type; + int marktable[8]; + int flags; +}; + +#endif /* _XT_AUTOMAP_TARGET_H */ Index: linux-4.1.52/include/uapi/linux/netfilter/xt_mark.h =================================================================== --- linux-4.1.52.orig/include/uapi/linux/netfilter/xt_mark.h 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/include/uapi/linux/netfilter/xt_mark.h 2018-01-22 14:21:12.861630793 +0800 @@ -3,8 +3,21 @@ #include +/* Version 1 */ +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ +enum { + XT_MARK_SET=0, + XT_MARK_AND, + XT_MARK_OR, + XT_MARK_VTAG_SET +}; +#endif + struct xt_mark_tginfo2 { __u32 mark, mask; +#if 1 /* ZyXEL QoS, John */ + __u8 mode; +#endif }; struct xt_mark_mtinfo1 { Index: linux-4.1.52/include/uapi/linux/netfilter/xt_policer.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/include/uapi/linux/netfilter/xt_policer.h 2018-01-22 14:21:12.861630793 +0800 @@ -0,0 +1,38 @@ +#ifndef _XT_RATE_H +#define _XT_RATE_H + +#define BITS_PER_BYTE 8 +#define KILO_SCALE 1000 + +struct xt_policerinfo { +#if 1//__MSTC__, Jones For compilation + int policerMode; + + /* For srTCM and trTCM, rate means cRate and burst means cbsBurst. + For srTCM, pbsBurst means ebsBurst. */ + u_int32_t rate, pRate; + u_int32_t burst, pbsBurst; /* Period multiplier for upper limit. */ + + /* Used internally by the kernel */ + unsigned long prev; + + /* For srTCM and trTCM, credit means cbsCredit and creditCap means cbsCreditCap. + For srTCM, pbsCreditCap means ebsCreditCap. */ + u_int32_t credit, pbsCredit; + u_int32_t creditCap, pbsCreditCap; + + struct xt_policerinfo *master; +#else + u_int32_t avg; /* Average secs between packets * scale */ + u_int32_t burst; /* Period multiplier for upper limit. */ + + /* Used internally by the kernel */ + unsigned long prev; + u_int32_t credit; + u_int32_t credit_cap, cost; + + struct xt_policerinfo *master; +#endif +}; + +#endif /*_XT_RATE_H*/ Index: linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_AUTOMAP.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_AUTOMAP.h 2018-01-22 14:21:12.861630793 +0800 @@ -0,0 +1,50 @@ +/* Used by ebt_AUTOMAP.c, MitraStar Jeff, 20110114*/ +#ifndef __LINUX_BRIDGE_EBT_AUTOMAP_H +#define __LINUX_BRIDGE_EBT_AUTOMAP_H + +#define EBT_AUTOMAP_TARGET "AUTOMAP" + +#define AUTOMAP_TYPE_8021P 0x1 +#define AUTOMAP_TYPE_DSCP 0x2 +#define AUTOMAP_TYPE_PKTLEN 0x4 + +#define DSCP_MASK_SHIFT 5 +#define ETHERPRI_MARK_SHIFT 12 + + + /* + Auto Priority Mapping Table + + + DSCP | Packet Length | 802.1P | Queue | + --------------------------------------------- + | | 001 | 0 | + | | | | + | | 010 | 1 | + | | | | + 0x00 | >1100 | 000 | 2 | + | | | | + 0x08 | 250-1100 | 011 | 3 | + | | | | + 0x10 | | 100 | 4 | + | | | | + 0x18 | <250 | 101 | 5 | + | | | | + 0x20,0x28 | | 110 | 6 | + | | | | + 0x30,0x38 | | 111 | 7 | + */ + + +/* accoding to tr181 8021p to DSCP mapping table(upstream), higher value higher priority*/ +unsigned short vlan8021pToPriorityQueue[8] = {2,0,1,3,4,5,6,7}; +unsigned short dscpPrecedenceToPriorityQueue[8] = {2,3,4,5,6,6,7,7}; + + +/* target info */ +struct ebt_automap_t_info { + int type; + int marktable[8]; +}; + +#endif Index: linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_ip.h =================================================================== --- linux-4.1.52.orig/include/uapi/linux/netfilter_bridge/ebt_ip.h 2018-01-22 14:21:12.493630784 +0800 +++ linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_ip.h 2018-01-22 14:21:12.861630793 +0800 @@ -23,6 +23,55 @@ #define EBT_IP_PROTO 0x08 #define EBT_IP_SPORT 0x10 #define EBT_IP_DPORT 0x20 + +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ +#if defined(CONFIG_BCM_KF_NETFILTER) || !defined(CONFIG_BCM_IN_KERNEL) +#define EBT_IP_DSCP 0x40 +#endif +#define EBT_IP_LENGTH 0x80 +#define EBT_IP_TCP_FLAGS 0x100 +#define EBT_IP_DHCP_OPT60 0x200 +#define EBT_IP_DHCP_OPT61 0x400 +#define EBT_IP_DHCP_OPT77 0x800 +#define EBT_IP_DHCP_OPT125 0x1000 +#if defined(CONFIG_BCM_KF_NETFILTER) || !defined(CONFIG_BCM_IN_KERNEL) +#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ + EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_DSCP | EBT_IP_LENGTH | EBT_IP_TCP_FLAGS |\ + EBT_IP_DHCP_OPT60 | EBT_IP_DHCP_OPT61 | EBT_IP_DHCP_OPT77 | EBT_IP_DHCP_OPT125) +#else +#define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ + EBT_IP_SPORT | EBT_IP_DPORT | EBT_IP_LENGTH | EBT_IP_TCP_FLAGS |\ + EBT_IP_DHCP_OPT60 | EBT_IP_DHCP_OPT61 | EBT_IP_DHCP_OPT77 | EBT_IP_DHCP_OPT125) +#endif +#define DHCP_OPTION_MAX_LEN 556 /* IP header(20) + UDP header(8)+ DHCP header(528) */ + +#define DHCP_PADDING 0x00 +#define DHCP_VENDOR 0x3c /*option 60 */ +#define DHCP_CLIENT_ID 0x3d /*option 61 */ +#define DHCP_USER_CLASS_ID 0x4d /*option 77 */ +#define DHCP_VENDOR_IDENTIFYING 0x7d /*option 125 */ +#define DHCP_OPTION_OVER 0x34 +#define DHCP_END 0xFF + +#define OPTION_FIELD 0 +#define FILE_FIELD 1 +#define SNAME_FIELD 2 + + + +/* miscellaneous defines */ +#define OPT_CODE 0 +#define OPT_LEN 1 +#define OPT_DATA 2 + +#define OPTION_MAC_ENTRY 32 + +/* each option data shift length */ +#define DHCP_OPT_LEN_FIELD_LEN 1 +#define DHCP_OPT125_ENTERPRISE_NUM_LEN 4 +#define DHCP_OPT125_DATA_SHIFT DHCP_OPT125_ENTERPRISE_NUM_LEN + DHCP_OPT_LEN_FIELD_LEN + +#else #if defined(CONFIG_BCM_KF_NETFILTER) || !defined(CONFIG_BCM_IN_KERNEL) #define EBT_IP_DSCP 0x40 #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ @@ -31,9 +80,61 @@ #define EBT_IP_MASK (EBT_IP_SOURCE | EBT_IP_DEST | EBT_IP_TOS | EBT_IP_PROTO |\ EBT_IP_SPORT | EBT_IP_DPORT ) #endif +#endif #define EBT_IP_MATCH "ip" /* the same values are used for the invflags */ +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ +struct cfgopt{ + uint8_t len; + char cfgdata[254]; +}; + +struct dhcpMessage { + uint8_t op; + uint8_t htype; + uint8_t hlen; + uint8_t hops; + uint32_t xid; + uint16_t secs; + uint16_t flags; + uint32_t ciaddr; + uint32_t yiaddr; + uint32_t siaddr; + uint32_t giaddr; + uint8_t chaddr[16]; + uint8_t sname[64]; + uint8_t file[128]; + uint32_t cookie; + uint8_t options[308]; /* 312 - cookie */ +}; + +struct ebt_ip_info +{ + __be32 saddr; + __be32 daddr; + __be32 smsk; + __be32 dmsk; + __u8 tos; +#if defined(CONFIG_BCM_KF_NETFILTER) || !defined(CONFIG_BCM_IN_KERNEL) + __u8 dscp; /* brcm */ +#endif + __u8 protocol; + __u16 bitmask; + __u16 invflags; + __u8 tcp_flg_mask; + __u8 tcp_flg_cmp; + __u16 sport[2]; + __u16 dport[2]; + __u16 length[2]; + struct cfgopt cfg60; //option 60 + struct cfgopt cfg61; //option 61 + struct cfgopt cfg77; //option 77 + struct cfgopt cfg125; //option 125 + char SrcMacArray[OPTION_MAC_ENTRY][ETH_ALEN]; +}; +#else +/* the same values are used for the invflags */ struct ebt_ip_info { __be32 saddr; __be32 daddr; @@ -49,5 +150,6 @@ __u16 sport[2]; __u16 dport[2]; }; +#endif #endif Index: linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_ip6.h =================================================================== --- linux-4.1.52.orig/include/uapi/linux/netfilter_bridge/ebt_ip6.h 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_ip6.h 2018-01-22 14:21:12.861630793 +0800 @@ -21,10 +21,19 @@ #define EBT_IP6_SPORT 0x10 #define EBT_IP6_DPORT 0x20 #define EBT_IP6_ICMP6 0x40 +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ +#define EBT_IP6_LENGTH 0x80 +#endif +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ +#define EBT_IP6_MASK (EBT_IP6_SOURCE | EBT_IP6_DEST | EBT_IP6_TCLASS |\ + EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT | \ + EBT_IP6_ICMP6 | EBT_IP6_LENGTH) +#else #define EBT_IP6_MASK (EBT_IP6_SOURCE | EBT_IP6_DEST | EBT_IP6_TCLASS |\ EBT_IP6_PROTO | EBT_IP6_SPORT | EBT_IP6_DPORT | \ EBT_IP6_ICMP6) +#endif #define EBT_IP6_MATCH "ip6" /* the same values are used for the invflags */ @@ -45,6 +54,9 @@ __u16 dport[2]; __u8 icmpv6_code[2]; }; +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + __u16 length[2]; +#endif }; #endif Index: linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_policer.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/include/uapi/linux/netfilter_bridge/ebt_policer.h 2018-01-22 14:21:12.861630793 +0800 @@ -0,0 +1,39 @@ +/* Used by ebt_policer.c, ZyXEL Stan, 20100107*/ +#ifndef __LINUX_BRIDGE_EBT_POLICER_H +#define __LINUX_BRIDGE_EBT_POLICER_H + +#define EBT_POLICER_MATCH "policer" + +#define BITS_PER_BYTE 8 +#define KILO_SCALE 1000 + +struct ebt_policer_info +{ +#if 1//__MSTC__, Jones For compilation + int policerMode; + + /* For srTCM and trTCM, rate means cRate and burst means cbsBurst. + For srTCM, pbsBurst means ebsBurst. */ + u_int32_t rate, pRate; + u_int32_t burst, pbsBurst; /* Period multiplier for upper limit. */ + + /* Used internally by the kernel */ + unsigned long prev; + + /* For srTCM and trTCM, credit means cbsCredit and creditCap means cbsCreditCap. + For srTCM, pbsCreditCap means ebsCreditCap. */ + u_int32_t credit, pbsCredit; + u_int32_t creditCap, pbsCreditCap; +#else + u_int32_t avg; /* Average secs between packets * scale */ + u_int32_t burst; /* Period multiplier for upper limit. */ + + /* Used internally by the kernel */ + unsigned long prev; + u_int32_t credit; + u_int32_t credit_cap, cost; +#endif +}; + +#endif + Index: linux-4.1.52/net/bridge/netfilter/Kconfig =================================================================== --- linux-4.1.52.orig/net/bridge/netfilter/Kconfig 2018-01-22 14:21:12.597630786 +0800 +++ linux-4.1.52/net/bridge/netfilter/Kconfig 2018-01-22 14:21:12.861630793 +0800 @@ -65,6 +65,22 @@ See the man page for ebtables(8). To compile it as a module, choose M here. If unsure, say N. +config BRIDGE_EBT_AUTOMAP + tristate "ebt: auto priority mapping and DSCP marking support" + depends on BRIDGE_NF_EBTABLES + help + This option adds Auto Priority Mapping target on ebtables + + To compile it as a module, choose M here. If unsure, say N. + +config BRIDGE_EBT_POLICER + tristate "ebt: policy rate limit support" + depends on BRIDGE_NF_EBTABLES + help + This option adds the policy rate limit support + + To compile it as a module, choose M here. If unsure, say N. + # # matches # Index: linux-4.1.52/net/bridge/netfilter/Makefile =================================================================== --- linux-4.1.52.orig/net/bridge/netfilter/Makefile 2018-01-22 14:21:12.601630787 +0800 +++ linux-4.1.52/net/bridge/netfilter/Makefile 2018-01-22 14:21:12.861630793 +0800 @@ -49,6 +49,11 @@ obj-$(CONFIG_BRIDGE_EBT_WMM_MARK) += ebt_wmm_mark.o obj-$(CONFIG_BRIDGE_EBT_QOS_MAP) += ebt_qos_map.o obj-$(CONFIG_BRIDGE_EBT_REJECT) += ebt_reject.o +# /* ZyXEL QoS, John (porting from MSTC) */ +obj-$(CONFIG_BRIDGE_EBT_AUTOMAP) += ebt_AUTOMAP.o + +# /* ZyXEL QoS, Mark (porting from MSTC) */ +obj-$(CONFIG_BRIDGE_EBT_POLICER) += ebt_policer.o endif # BCM_KF # CONFIG_BCM_KF_NETFILTER # watchers Index: linux-4.1.52/net/bridge/netfilter/ebt_AUTOMAP.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/net/bridge/netfilter/ebt_AUTOMAP.c 2018-01-22 16:09:59.973788827 +0800 @@ -0,0 +1,149 @@ +/* Kernel module to control the rate in kbps. */ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ +/* MitraStar Jeff, 20110114*/ + +#include +#include +#include +#include + +#include +#include +#include + + +static int getVlanPrioAndIpHeader(struct sk_buff *skb, unsigned char *prio, struct iphdr **iph){ + unsigned short TCI; + unsigned short id; /* VLAN ID, given from frame TCI */ + /* Need to recalculate IP header checksum after altering TOS byte */ + const struct vlan_hdr *fp; + struct vlan_hdr _frame; + struct iphdr *ih = NULL; + + /* get ip header */ + if (skb->protocol == __constant_htons(ETH_P_IP)) + ih = (struct iphdr *)skb_network_header(skb); + else if (skb->protocol == __constant_htons(ETH_P_8021Q)) { + if (*(unsigned short *)(skb_network_header(skb) + VLAN_HLEN - 2) == __constant_htons(ETH_P_IP)) + ih = (struct iphdr *)(skb_network_header(skb) + VLAN_HLEN); + } + *iph = ih; + + if(ntohs(((struct vlan_hdr *)(skb->vlan_header))->h_vlan_encapsulated_proto) == 0){ + if(skb->protocol == ETH_P_8021Q) { + fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame); + if (fp == NULL) + return EBT_CONTINUE; + /* Tag Control Information (TCI) consists of the following elements: + * - User_priority. The user_priority field is three bits in length, + * interpreted as a binary number. + * - Canonical Format Indicator (CFI). The Canonical Format Indicator + * (CFI) is a single bit flag value. Currently ignored. + * - VLAN Identifier (VID). The VID is encoded as + * an unsigned binary number. */ + TCI = ntohs(fp->h_vlan_TCI); + id = TCI & VLAN_VID_MASK; + *prio = (TCI >> 13) & 0x7; + } + //Packet with no VLAN tag + else { + TCI = 0; + id = 0; + //Packet with no VLAN tag will be sent to default queue just like 1p value is 1 + *prio = 1; + } + } + else { + // for new broadcom vlan device + TCI = ntohs(((struct vlan_hdr *)(skb->vlan_header))->h_vlan_TCI); + id = TCI & VLAN_VID_MASK; + *prio = (TCI >> 13) & 0x7; + } + + return 0; +} + + +static unsigned int +ebt_automap_tg(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct ebt_automap_t_info *aminfo = par->targinfo; + struct iphdr *iph = NULL; + unsigned char prio = 0; + unsigned char dscpPrecedence = 0; + + + getVlanPrioAndIpHeader(skb, &prio, &iph); + + switch(aminfo->type){ + case AUTOMAP_TYPE_8021P: + /* mark value for priority queue */ + skb->mark |= vlan8021pToPriorityQueue[prio]; + + /* should mark DSCP here */ + break; + case AUTOMAP_TYPE_DSCP: + + if(iph==NULL) + skb->mark|=0x0; + else { + /* get dscp precedence */ + dscpPrecedence = ((iph->tos)>>5)&0x7; + + /* mark value for priority queue */ + skb->mark |= dscpPrecedenceToPriorityQueue[dscpPrecedence]; + } + break; + case AUTOMAP_TYPE_PKTLEN: + if(iph==NULL) + skb->mark|=0x0; + else { + if(iph->tot_len > 1100){ + skb->mark|=vlan8021pToPriorityQueue[0]; /* queue prio 2 */ + }else if(iph->tot_len < 250){ + skb->mark|=vlan8021pToPriorityQueue[5]; /* queue prio 5 */ + }else{ /*250~1100*/ + skb->mark|=vlan8021pToPriorityQueue[3]; /* queue prio 3 */ + } + } + break; + default: + break; + } + + return EBT_CONTINUE; +} + +/* As a policer rule added, this function will be executed */ +static int ebt_automap_tg_check(const struct xt_tgchk_param *par) +{ + return 0; +} + +static struct xt_target ebt_automap_tg_reg __read_mostly = +{ + .name = EBT_AUTOMAP_TARGET, + .revision = 0, + .family = NFPROTO_BRIDGE, + .target = ebt_automap_tg, + .checkentry = ebt_automap_tg_check, + .targetsize = XT_ALIGN(sizeof(struct ebt_automap_t_info)), + .me = THIS_MODULE, +}; + +static int __init ebt_automap_init(void) +{ + return xt_register_target(&ebt_automap_tg_reg); +} + +static void __exit ebt_automap_fini(void) +{ + xt_unregister_target(&ebt_automap_tg_reg); +} + +module_init(ebt_automap_init); +module_exit(ebt_automap_fini); +MODULE_LICENSE("GPL"); + Index: linux-4.1.52/net/bridge/netfilter/ebt_ip.c =================================================================== --- linux-4.1.52.orig/net/bridge/netfilter/ebt_ip.c 2018-01-22 14:21:12.593630786 +0800 +++ linux-4.1.52/net/bridge/netfilter/ebt_ip.c 2018-01-22 15:46:22.061754496 +0800 @@ -18,12 +18,205 @@ #include #include #include - +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ +#include +#include +#endif struct tcpudphdr { __be16 src; __be16 dst; }; +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + +unsigned char *get_DhcpOption(struct dhcpMessage *packet, int code) +{ + int i, length; + unsigned char *optionptr; + int over = 0, done = 0, curr = OPTION_FIELD; + + optionptr = packet->options; + i = 0; + length = 308; + + while (!done) { + if (i >= length){ + return NULL; + } + if (optionptr[i + OPT_CODE] == code) { + if (i + 1 + optionptr[i + OPT_LEN] >= length) { + return NULL; + } + return optionptr + i + 2; + } + switch (optionptr[i + OPT_CODE]) { + case DHCP_PADDING: + i++; + break; + case DHCP_OPTION_OVER: + if (i + 1 + optionptr[i + OPT_LEN] >= length) { + return NULL; + } + over = optionptr[i + 3]; + i += optionptr[OPT_LEN] + 2; + break; + case DHCP_END: + if (curr == OPTION_FIELD && over & FILE_FIELD) { + optionptr = packet->file; + i = 0; + length = 128; + curr = FILE_FIELD; + } else if (curr == FILE_FIELD && over & SNAME_FIELD) { + optionptr = packet->sname; + i = 0; + length = 64; + curr = SNAME_FIELD; + } else done = 1; + break; + default: + i += optionptr[OPT_LEN + i] + 2; + } + } + return NULL; +} + +/* If match, return value is 0 */ +static int cmp_option60(char *optval60, const struct ebt_ip_info *info) +{ + int len; + char optionData[254]; + const struct cfgopt *cfgptr = NULL; + printk("%s %d\n", __FUNCTION__, __LINE__); + + if (optval60 == NULL) + return false; + + cfgptr = &(info->cfg60); + + /* Compare option data length */ + len = (int)(*((unsigned char *)optval60 - 1)); + if(len != cfgptr->len) + return false; + + /* Compare option data content */ + memset(optionData, 0, 254); + strncpy(optionData, optval60, len); + printk("%s %d: cfgdata[%s] optionData[%s]\n", __FUNCTION__, __LINE__, cfgptr->cfgdata, optionData); + if(strcmp(cfgptr->cfgdata, optionData) == 0) + return true; + + return 1; +} + +/* If match, return value is 0 */ +static int cmp_option61(char *optval61, const struct ebt_ip_info *info) +{ + int len; + char optionData[254]; + const struct cfgopt *cfgptr = NULL; + + + + if (optval61 == NULL) + return false; + + cfgptr = &(info->cfg61); + + /* Compare option data length */ + len = (int)(*((unsigned char *)optval61 - 1)); + + if(len != cfgptr->len) + return false; + + /* Compare option data content */ + memset(optionData, 0, 254); + memcpy(optionData, optval61, len); + + if(!memcmp(cfgptr->cfgdata, optionData, len)) + return true; + + return 1; +} + +/* If match, return value is 0 */ +static int cmp_option77(char *optval77, const struct ebt_ip_info *info) +{ + uint8_t len = 0, total_len = 0, current_len = 0; + char optionData[254]; + const struct cfgopt *cfgptr = NULL; + + + if (optval77 == NULL) + return false; + + cfgptr = &(info->cfg77); + + /* Record option 77 total length */ + total_len = (uint8_t)(*((unsigned char *)optval77 - 1)); + + while(total_len != current_len){ + len = (uint8_t)*((unsigned char *)optval77); /* For option 77, one data length */ + + if(len != cfgptr->len) + return false; + + /* Compare option data content */ + memset(optionData, 0, 254); + memcpy(optionData, optval77 + DHCP_OPT_LEN_FIELD_LEN, len ); + if(!memcmp(cfgptr->cfgdata, optionData, len)) + return true; + + /* shift to next vendor class data in option 125 */ + current_len += (len + DHCP_OPT_LEN_FIELD_LEN); + optval77 += (len + DHCP_OPT_LEN_FIELD_LEN); + } + return false; +} + + +/* If match, return value is 0 */ +static int cmp_option125(char *optval125, const struct ebt_ip_info *info) +{ + int len = 0, total_len = 0, current_len = 0; + char optionData[254]; + const struct cfgopt *cfgptr = NULL; + + if (optval125 == NULL) + return false; + + cfgptr = &(info->cfg125); + + /* Record option 125 total length */ + total_len = (int)(*((unsigned char *)optval125 - 1)); + + while(total_len != current_len){ + + len = (int)(*((unsigned char *)optval125 +DHCP_OPT125_ENTERPRISE_NUM_LEN)); /* For option 125, one data length */ + + + if(len + DHCP_OPT125_DATA_SHIFT != cfgptr->len) /* Add 5 is for enterprise-number(4 bytes) and data length represent(1 byte) */ + return false; + + /* Compare option data content */ + memset(optionData, 0, 254); + memcpy(optionData, optval125, len + DHCP_OPT125_DATA_SHIFT); + + if(!memcmp(cfgptr->cfgdata, optionData, len + DHCP_OPT125_DATA_SHIFT)) + return true; + + /* shift to next vendor class data in option 125 */ + current_len += (len + DHCP_OPT125_DATA_SHIFT); + optval125 += (len + DHCP_OPT125_DATA_SHIFT); + } + return false; + +} + + + + + +#endif static bool ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) { @@ -32,10 +225,112 @@ struct iphdr _iph; const struct tcpudphdr *pptr; struct tcpudphdr _ports; +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + struct tcphdr _tcph, *th; +#endif ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); if (ih == NULL) return false; +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + if((info->bitmask & EBT_IP_DHCP_OPT60)||(info->bitmask & EBT_IP_DHCP_OPT61)|| + (info->bitmask & EBT_IP_DHCP_OPT77)||(info->bitmask & EBT_IP_DHCP_OPT125)){ + unsigned char payload[DHCP_OPTION_MAX_LEN]; + struct dhcpMessage *dhcpPtr; + struct iphdr _iph, *ih; + struct tcpudphdr _ports, *pptr; + int skb_data_len=0, i, LastEntry = -1; + bool OptMatch = 0; + char TmpMac[ETH_ALEN]; + + memset(TmpMac , 0, sizeof(TmpMac)); + + ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); + if (ih == NULL) + return false; + + pptr = skb_header_pointer(skb, ih->ihl*4, sizeof(_ports), &_ports); + + /* not DHCP packet, then try to compared with recoded mac */ + if(pptr->src!=67 && pptr->src!=68 && pptr->dst!=67 && pptr->dst!=68){ + for(i=0;ih_source, info->SrcMacArray[i])){ + /* if match, continue to check other conditions */ + goto CONTINUE; + } + if(!memcmp(TmpMac,info->SrcMacArray[i],ETH_ALEN)){ + break; + } + } + return false; + }else{ + /* If packet is dhcp packet */ + memset(payload, 0, sizeof(payload)); + skb_data_len = skb->len; + + if (skb_copy_bits(skb, 0, payload, skb_data_len)) + printk("Copy packet is failed by ebtables of filtering DHCP Option\n\r"); + + dhcpPtr = (struct dhcpMessage *)(payload + sizeof(struct iphdr) + sizeof(struct udphdr)); + + if(info->bitmask & EBT_IP_DHCP_OPT60){ + char *opt60 = get_DhcpOption(dhcpPtr, DHCP_VENDOR); + if(cmp_option60(opt60, info)^ !!(info->invflags & EBT_IP_DHCP_OPT60)) + OptMatch = 1; + } + + if(info->bitmask & EBT_IP_DHCP_OPT61){ + char *opt61 = get_DhcpOption(dhcpPtr, DHCP_CLIENT_ID); + if(cmp_option61(opt61, info)^ !!(info->invflags & EBT_IP_DHCP_OPT61)) + OptMatch = 1; + } + + if(info->bitmask & EBT_IP_DHCP_OPT77){ + char *opt77 = get_DhcpOption(dhcpPtr, DHCP_USER_CLASS_ID); + if(cmp_option77(opt77, info)^ !!(info->invflags & EBT_IP_DHCP_OPT77)) + OptMatch = 1; + } + + if(info->bitmask & EBT_IP_DHCP_OPT125){ + char *opt125 = get_DhcpOption(dhcpPtr, DHCP_VENDOR_IDENTIFYING); + if(cmp_option125(opt125, info)^ !!(info->invflags & EBT_IP_DHCP_OPT125)) + OptMatch = 1; + } + +// printk("\nOptMatch is %d\n",OptMatch); + + if(OptMatch){ + /* match dhcp option, then record its MAC addr for future filter */ + for(i=0;iSrcMacArray[i],ETH_ALEN)){ + memcpy((void *)(info->SrcMacArray[i]), eth_hdr(skb)->h_source, ETH_ALEN); + break; + }else if(!memcmp(eth_hdr(skb)->h_source, info->SrcMacArray[i], ETH_ALEN)){ + break; + } + } + }else{ + /* not match, need to check current list whether this MAC hace once been matched, if so, clear this entry from this DHCP + option criteria (client might change another vendor information, ex different vendor ID string) */ + for(i=0;iSrcMacArray[i],ETH_ALEN)){ + if(LastEntry!=-1){ + memcpy((void *)(info->SrcMacArray[LastEntry]), info->SrcMacArray[i-1], ETH_ALEN); + memset((void *)(info->SrcMacArray[i-1]), 0, ETH_ALEN); + } + break; + }else if(!memcmp(eth_hdr(skb)->h_source, info->SrcMacArray[i], ETH_ALEN)){ + LastEntry = i;//Record clear entry + } + } + + return false; + } + } + + } +CONTINUE: +#endif if (info->bitmask & EBT_IP_TOS && FWINV(info->tos != ih->tos, EBT_IP_TOS)) return false; @@ -52,11 +347,26 @@ FWINV((ih->daddr & info->dmsk) != info->daddr, EBT_IP_DEST)) return false; +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + if(info->bitmask & EBT_IP_LENGTH) { /* IP Length */ + u16 len = ntohs(ih->tot_len); + if (FWINV(len < info->length[0] || + len > info->length[1], + EBT_IP_LENGTH)) + return false; + } +#endif if (info->bitmask & EBT_IP_PROTO) { if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) return false; +#if 0 /* ZyXEL QoS, John (porting from MSTC) */ if (!(info->bitmask & EBT_IP_DPORT) && !(info->bitmask & EBT_IP_SPORT)) +#else + if (!(info->bitmask & EBT_IP_DPORT) && + !(info->bitmask & EBT_IP_SPORT) && + !(info->bitmask & EBT_IP_TCP_FLAGS)) +#endif return true; if (ntohs(ih->frag_off) & IP_OFFSET) return false; @@ -78,6 +388,19 @@ EBT_IP_SPORT)) return false; } +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + if (info->bitmask & EBT_IP_TCP_FLAGS) { + th = skb_header_pointer(skb, ih->ihl*4, sizeof(_tcph), &_tcph); + if (th == NULL) { + /* We've been asked to examine this packet, and we + can't. Hence, no choice but to drop. */ + printk("Dropping evil TCP offset=0 tinygram.\n"); + return 0; + } + if (FWINV((((unsigned char *)th)[13] & info->tcp_flg_mask) != info->tcp_flg_cmp, EBT_IP_TCP_FLAGS)) + return false; + } +#endif } return true; } @@ -106,6 +429,10 @@ return -EINVAL; if (info->bitmask & EBT_IP_SPORT && info->sport[0] > info->sport[1]) return -EINVAL; +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + if (info->bitmask & EBT_IP_LENGTH && info->length[0] > info->length[1]) + return false; +#endif return 0; } Index: linux-4.1.52/net/bridge/netfilter/ebt_ip6.c =================================================================== --- linux-4.1.52.orig/net/bridge/netfilter/ebt_ip6.c 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/net/bridge/netfilter/ebt_ip6.c 2018-01-22 14:21:12.865630793 +0800 @@ -55,6 +55,15 @@ FWINV(ipv6_masked_addr_cmp(&ih6->daddr, &info->dmsk, &info->daddr), EBT_IP6_DEST))) return false; +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + if(info->bitmask & EBT_IP6_LENGTH) { + u16 len = ntohs(ih6->payload_len); + if (FWINV(len < info->length[0] || + len > info->length[1], + EBT_IP6_LENGTH)) + return false; + } +#endif if (info->bitmask & EBT_IP6_PROTO) { uint8_t nexthdr = ih6->nexthdr; __be16 frag_off; @@ -128,6 +137,10 @@ info->icmpv6_code[0] > info->icmpv6_code[1]) return -EINVAL; } +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ + if (info->bitmask & EBT_IP6_LENGTH && info->length[0] > info->length[1]) + return false; +#endif return 0; } Index: linux-4.1.52/net/bridge/netfilter/ebt_mark.c =================================================================== --- linux-4.1.52.orig/net/bridge/netfilter/ebt_mark.c 2018-01-22 14:21:12.593630786 +0800 +++ linux-4.1.52/net/bridge/netfilter/ebt_mark.c 2018-01-22 14:21:12.865630793 +0800 @@ -65,6 +65,7 @@ frame->h_vlan_TCI = htons(TCI); } +#if 0 /* ZyXEL QoS, change VLAM header process to vlanCtl driver instead of ebtables module, John (porting from MSTC)*/ else { if ((skb_mac_header(skb) - skb->head) < VLAN_HLEN) @@ -97,6 +98,7 @@ } } skb->vtag = 0; +#endif } } #endif // CONFIG_BCM_KF_NETFILTER Index: linux-4.1.52/net/bridge/netfilter/ebt_policer.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/net/bridge/netfilter/ebt_policer.c 2018-01-22 16:22:34.841807103 +0800 @@ -0,0 +1,328 @@ +/* Kernel module to control the rate in kbps. */ +/* This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. */ +/* ZyXEL Stan, 20100105*/ + +#include +#if 1 // __MSTC__, ZyXEL richard, QoS +#include +#endif // __MSTC__, ZyXEL richard, QoS +#include +#include + +#include +#include +#if 1 //__MSTC__, Eric, Qos policer. +#include "skb_defines.h" +#define RED 1 +#define YELLOW 2 +#define GREEN 3 +#endif +#if 1//__MSTC__, Jones For compilation +#define MODE_TBF 0 +#define MODE_SRTCM 1 +#define MODE_TRTCM 2 +#endif +static DEFINE_SPINLOCK(policer_lock); +#if 1//__MSTC__, Jones For compilation +static bool +ebt_policer_match(const struct sk_buff *skb, struct xt_action_param *par) + +{ + struct ebt_policer_info *r = (struct ebt_policer_info *)par->matchinfo; + unsigned long now = jiffies; + unsigned long timePassed = 0; + struct sk_buff *tmp; + u_int32_t cost = 0; + u_int32_t extraCredit = 0; + spin_lock_bh(&policer_lock); + +#if 1 //__OBM__, Jones +#if defined(CONFIG_MIPS_BRCM) && defined(CONFIG_BLOG) + blog_skip((struct sk_buff *)skb, blog_skip_reason_nf_ebt_skiplog); +#endif +#endif + + //printk(KERN_EMERG "111__skb->mark=%x\n\r", skb->mark); + switch(r->policerMode) { + /* Token Bucket Filter (tbf) mode */ + /* The algorithm used is the Simple Token Bucket Filter (TBF) + see net/sched/sch_tbf.c in the linux source tree. */ + case MODE_TBF: + r->credit += (now - xchg(&r->prev, now)) * r->rate; /* Add TBF cerdit */ + if (r->credit > r->creditCap) { + r->credit = r->creditCap; + } + cost = (skb->len + skb->mac_len) * BITS_PER_BYTE; + if (r->credit >= cost) { + /* We're not limited. (Match) */ + r->credit -= cost; /* Take out credit */ + spin_unlock_bh(&policer_lock); + //printk(KERN_EMERG "222__skb->mark=%x\n\r", skb->mark); + return true; + break; + } + /* We're limited. (Not Match) */ + spin_unlock_bh(&policer_lock); + //printk(KERN_EMERG "333__skb->mark=%x\n\r", skb->mark); + return false; + break; + + /* Single Rate Three Color Marker (srTCM) Mode */ + case MODE_SRTCM: + /* Add CBS first */ + r->credit += (now - xchg(&r->prev, now)) * r->rate; /* Add CBS cerdit */ + if (r->credit > r->creditCap) { + extraCredit = r->credit - r->creditCap; + r->credit = r->creditCap; + } + if (r->pbsCredit < r->pbsCreditCap && extraCredit > 0) { + r->pbsCredit += extraCredit; /* Add EBS cerdit */ + if (r->pbsCredit > r->pbsCreditCap) { + r->pbsCredit = r->pbsCreditCap; + } + } + cost = (skb->len + skb->mac_len) * BITS_PER_BYTE; + tmp = (struct sk_buff *)skb; + if (r->credit >= cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , GREEN); /* Green */ + r->credit -= cost; + } + else if (r->pbsCredit >= cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , YELLOW); /* Yellow */ + r->pbsCredit -= cost; + } + else { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , RED); /* Red */ + } + spin_unlock_bh(&policer_lock); + return true; + break; + + /* Two Rate Three Color Marker (srTCM) Mode */ + case MODE_TRTCM: + timePassed = (now - xchg(&r->prev, now)); + r->credit += timePassed * r->rate; /* Add CBS cerdit */ + r->pbsCredit += timePassed * r->pRate; /* Add PBS cerdit */ + if (r->credit > r->creditCap) { + r->credit = r->creditCap; + } + if (r->pbsCredit > r->pbsCreditCap) { + r->pbsCredit = r->pbsCreditCap; + } + cost = (skb->len + skb->mac_len) * BITS_PER_BYTE; + tmp = (struct sk_buff *)skb; + if (r->pbsCredit < cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , RED); /* Red */ + } + else if (r->credit < cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , YELLOW); /* Yellow */ + r->pbsCredit -= cost; + } + else { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , GREEN); /* Green */ + r->pbsCredit -= cost; + r->credit -= cost; + } + spin_unlock_bh(&policer_lock); + return true; + break; + + default: + return false; + } +} +/* end ipt_policer_match */ +#else +#if 0 // __MSTC__, ZyXEL richard, QoS +static int ebt_policer_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const void *data, + unsigned int datalen) +{ + struct ebt_policer_info *info = (struct ebt_policer_info *)data; + unsigned long now = jiffies; + + spin_lock_bh(&policer_lock); + info->credit += (now - xchg(&info->prev, now)) * info->avg; /* Add credit. */ + if (info->credit > info->credit_cap) { + info->credit = info->credit_cap; + } + u_int32_t temp_cost = 0; + temp_cost = (skb->len + skb->mac_len) * info->cost; + if (info->credit >= temp_cost) { + /* We're not limited. */ + info->credit -= temp_cost; /* Take out credit */ + spin_unlock_bh(&policer_lock); + return EBT_MATCH; + } + + spin_unlock_bh(&policer_lock); + return EBT_NOMATCH; +} +#else +static bool ebt_policer_match(const struct sk_buff *skb, const struct xt_match_param *par) +{ + struct ebt_policer_info *info = par->matchinfo; + unsigned long now = jiffies; + + spin_lock_bh(&policer_lock); + info->credit += (now - xchg(&info->prev, now)) * info->avg; /* Add credit. */ + if (info->credit > info->credit_cap) { + info->credit = info->credit_cap; + } + + u_int32_t temp_cost; + temp_cost = (skb->len + skb->mac_len) * info->cost; + if (info->credit >= temp_cost) { + /* We're not limited. */ + info->credit -= temp_cost; /* Take out credit */ + spin_unlock_bh(&policer_lock); + return true; + ////return false; + } + + spin_unlock_bh(&policer_lock); + + return false; + ////return true; +} +#endif // __MSTC__, ZyXEL richard, QoS +#endif + +#if 1//__MSTC__, Jones For compilation +/* Precision saver. */ +/* As a policer rule added, this function will be executed */ +static int ebt_policer_check(const struct xt_mtchk_param *par) +{ + struct ebt_policer_info *r = par->matchinfo; + + /* pRate must be equal or greater than crate. */ + if (r->policerMode == 2) { + if (r->rate > r->pRate) { + return -EINVAL; + } + } + + if (r->creditCap == 0) { /* Check if policer initiate or not. */ + switch(r->policerMode) { + case MODE_TBF: + r->prev = jiffies; + r->creditCap = r->burst * BITS_PER_BYTE * KILO_SCALE; /* TBF Credits full */ + r->credit = r->creditCap; /* TBF Credits full */ + break; + + case MODE_SRTCM: + r->prev = jiffies; + r->creditCap = r->burst * BITS_PER_BYTE * KILO_SCALE; /* CBS Credits full */ + r->credit = r->creditCap; /* CBS Credits full */ + r->pbsCreditCap = r->pbsBurst * BITS_PER_BYTE * KILO_SCALE; /* EBS Credits full */ + r->pbsCredit = r->pbsCreditCap; /* EBS Credits full */ + break; + + case MODE_TRTCM: + r->prev = jiffies; + r->creditCap = r->burst * BITS_PER_BYTE * KILO_SCALE; /* CBS Credits full. */ + r->credit = r->creditCap; /* CBS Credits full. */ + r->pbsCreditCap = r->pbsBurst * BITS_PER_BYTE * KILO_SCALE; /* PBS Credits full. */ + r->pbsCredit = r->pbsCreditCap; /* PBS Credits full. */ + break; + + default: + return -EINVAL; + } + } + return 0; +} +#else +/* Precision saver. */ +/* As a policer rule added, this function will be executed */ +#if 0 // __MSTC__, ZyXEL richard, QoS +static int ebt_policer_check(const char *tablename, + unsigned int hookmask, + const struct ebt_entry *e, + void *data, + unsigned int datalen) +{ + struct ebt_policer_info *info = (struct ebt_policer_info *)data; + + if (datalen != EBT_ALIGN(sizeof(struct ebt_policer_info))) { + return -EINVAL; + } + + info->prev = jiffies; + info->credit_cap = info->burst * BITS_PER_BYTE * KILO_SCALE; /*Credits full.*/ + info->credit = info->burst * BITS_PER_BYTE * KILO_SCALE; /*Credits full.*/ + info->cost = BITS_PER_BYTE; + + return 0; +} +#else +static bool ebt_policer_check(const struct xt_mtchk_param *par) +{ + struct ebt_policer_info *info = par->matchinfo; + + /***if (par->datalen != EBT_ALIGN(sizeof(struct ebt_policer_info))) { + return -EINVAL; + }***/ + + info->prev = jiffies; + info->credit_cap = info->burst * BITS_PER_BYTE * KILO_SCALE; /*Credits full.*/ + info->credit = info->burst * BITS_PER_BYTE * KILO_SCALE; /*Credits full.*/ + info->cost = BITS_PER_BYTE; + + return true; +} +#endif // __MSTC__, ZyXEL richard, QoS +#endif + +#if 0 // __MSTC__, ZyXEL richard, QoS +static struct ebt_match ebt_policer_reg = +#else +static struct xt_match ebt_policer_reg __read_mostly = +#endif +{ + .name = EBT_POLICER_MATCH, +#if 1 // __MSTC__, ZyXEL richard, QoS + .revision = 0, + .family = NFPROTO_BRIDGE, + .match = ebt_policer_match, + .checkentry = ebt_policer_check, + .matchsize = XT_ALIGN(sizeof(struct ebt_policer_info)), +#else + .check = ebt_policer_check, + .match = ebt_policer_match, +#endif // __MSTC__, ZyXEL richard, QoS + .me = THIS_MODULE, +}; + +static int __init ebt_policer_init(void) +{ +#if 0 // __MSTC__, ZyXEL richard, QoS + return ebt_register_match(&ebt_policer_reg); +#else + return xt_register_match(&ebt_policer_reg); +#endif // __MSTC__, ZyXEL richard, QoS +} + +static void __exit ebt_policer_fini(void) +{ +#if 0 // __MSTC__, ZyXEL richard, QoS + ebt_unregister_match(&ebt_policer_reg); +#else + xt_unregister_match(&ebt_policer_reg); +#endif +} + +module_init(ebt_policer_init); +module_exit(ebt_policer_fini); +MODULE_LICENSE("GPL"); + Index: linux-4.1.52/net/bridge/netfilter/ebt_vlan.c =================================================================== --- linux-4.1.52.orig/net/bridge/netfilter/ebt_vlan.c 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/net/bridge/netfilter/ebt_vlan.c 2018-01-22 14:21:12.865630793 +0800 @@ -129,7 +129,9 @@ * Any value of user_priority are acceptable, * but should be ignored according to 802.1Q Std. * So we just drop the prio flag. */ +#if 0 /* ZyXEL QoS, John (porting from MSTC) */ info->bitmask &= ~EBT_VLAN_PRIO; +#endif } /* Else, id=0 (null VLAN ID) => user_priority range (any?) */ } Index: linux-4.1.52/net/bridge/netfilter/ebtables.c =================================================================== --- linux-4.1.52.orig/net/bridge/netfilter/ebtables.c 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/net/bridge/netfilter/ebtables.c 2018-01-22 14:21:12.869630793 +0800 @@ -31,6 +31,10 @@ /* needed for logical [in,out]-dev filtering */ #include "../br_private.h" +#if 1 /* ZyXEL QoS, John */ +#include +#endif + #define BUGPRINT(format, args...) printk("kernel msg: ebtables bug: please "\ "report to author: "format, ## args) /* #define BUGPRINT(format, args...) */ @@ -124,10 +128,16 @@ #define FWINV2(bool, invflg) ((bool) ^ !!(e->invflags & invflg)) /* process standard matches */ -static inline int -ebt_basic_match(const struct ebt_entry *e, const struct sk_buff *skb, + +#if 0 /* ZyXEL QoS, in order to filter VLAN, John (porting from MSTC) */ +static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, + const struct net_device *in, const struct net_device *out) +{ +#else +static inline int ebt_basic_match(struct ebt_entry *e, struct sk_buff *skb, const struct net_device *in, const struct net_device *out) { +#endif const struct ethhdr *h = eth_hdr(skb); const struct net_bridge_port *p; __be16 ethproto; @@ -138,13 +148,29 @@ else ethproto = h->h_proto; +#if 0 /* ZyXEL QoS, in order to filter VLAN, John (porting from MSTC) */ if (e->bitmask & EBT_802_3) { if (FWINV2(ntohs(ethproto) >= ETH_P_802_3_MIN, EBT_IPROTO)) return 1; } else if (!(e->bitmask & EBT_NOPROTO) && FWINV2(e->ethproto != ethproto, EBT_IPROTO)) return 1; - +#else + h = eth_hdr(skb); + if (e->bitmask & EBT_802_3) { + if (FWINV2(ntohs(h->h_proto) >= 1536, EBT_IPROTO)) + return 1; + } else if (!(e->bitmask & EBT_NOPROTO) ){ + if(e->ethproto == ETH_P_8021Q && ethproto!=ETH_P_8021Q) {/*If protocol type of rule is 802.1q and packet header is not 802.1q*/ + /* for new broadcom vlan device */ + if(FWINV2(!(ntohs(((struct vlan_hdr *)(skb->vlan_header))->h_vlan_encapsulated_proto)), EBT_IPROTO)) + return 1; + }else{ + if(FWINV2(e->ethproto != ethproto, EBT_IPROTO)) + return 1; + } + } +#endif if (FWINV2(ebt_dev_check(e->in, in), EBT_IIN)) return 1; if (FWINV2(ebt_dev_check(e->out, out), EBT_IOUT)) @@ -220,9 +246,13 @@ base = private->entries; i = 0; while (i < nentries) { +#if 0 /* ZyXEL QoS, in order to filter VLAN, John(porting from MSTC) */ + if (ebt_basic_match(point, eth_hdr(skb), in, out)) + goto letscontinue; +#else if (ebt_basic_match(point, skb, in, out)) goto letscontinue; - +#endif if (EBT_MATCH_ITERATE(point, ebt_do_match, skb, &acpar) != 0) goto letscontinue; if (acpar.hotdrop) { Index: linux-4.1.52/net/core/gen_estimator.c =================================================================== --- linux-4.1.52.orig/net/core/gen_estimator.c 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/net/core/gen_estimator.c 2018-01-22 16:16:19.589798018 +0800 @@ -86,9 +86,15 @@ spinlock_t *stats_lock; int ewma_log; u64 last_bytes; +#if 1 /* ZyXEL QoS, porting from MSTC */ + u64 last_dropbytes; +#endif u64 avbps; u32 last_packets; u32 avpps; +#if 1 /* ZyXEL QoS, porting from MSTC */ + u32 avdropbps; +#endif struct rcu_head e_rcu; struct rb_node node; struct gnet_stats_basic_cpu __percpu *cpu_bstats; @@ -119,6 +125,9 @@ list_for_each_entry_rcu(e, &elist[idx].list, list) { struct gnet_stats_basic_packed b = {0}; u64 brate; +#if 1 /* ZyXEL QoS, porting from MSTC */ + u64 ndropbytes; +#endif u32 rate; spin_lock(e->stats_lock); @@ -127,12 +136,19 @@ goto skip; __gnet_stats_copy_basic(&b, e->cpu_bstats, e->bstats); - +#if 1 /* ZyXEL QoS, porting from MSTC */ + ndropbytes = e->bstats->dropbytes; +#endif brate = (b.bytes - e->last_bytes)<<(7 - idx); e->last_bytes = b.bytes; e->avbps += (brate >> e->ewma_log) - (e->avbps >> e->ewma_log); e->rate_est->bps = (e->avbps+0xF)>>5; - +#if 1 /* ZyXEL QoS, porting from MSTC */ + rate = (ndropbytes - e->last_dropbytes)<<(7 - idx); + e->last_dropbytes = ndropbytes; + e->avdropbps += ((long)rate - (long)e->avdropbps) >> e->ewma_log; + e->rate_est->dropbps = (e->avdropbps+0xF)>>5; +#endif rate = (b.packets - e->last_packets)<<(12 - idx); e->last_packets = b.packets; e->avpps += (rate >> e->ewma_log) - (e->avpps >> e->ewma_log); Index: linux-4.1.52/net/netfilter/Kconfig =================================================================== --- linux-4.1.52.orig/net/netfilter/Kconfig 2018-01-22 14:21:12.737630790 +0800 +++ linux-4.1.52/net/netfilter/Kconfig 2018-01-22 14:21:12.869630793 +0800 @@ -636,6 +636,21 @@ "Use netfilter MARK value as routing key") and can also be used by other subsystems to change their behavior. +config NETFILTER_XT_TARGET_AUTOMAP + tristate '"AUTOMAP" target support' + depends on NETFILTER_XTABLES + help + + This option adds a `AUTOMAP' target, which allows packet auto mapping to Internal Priority Queue by 8021p value, and automaically mark DSCP value. + + To compile it as a module, choose M here. If unsure, say N. + +config NETFILTER_XT_POLICER + tristate '"policer" rate limit support' + depends on NETFILTER_XTABLES + help + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_CONNMARK tristate 'ctmark target and match support' depends on NF_CONNTRACK Index: linux-4.1.52/net/netfilter/Makefile =================================================================== --- linux-4.1.52.orig/net/netfilter/Makefile 2018-01-22 14:21:12.737630790 +0800 +++ linux-4.1.52/net/netfilter/Makefile 2018-01-22 14:21:12.869630793 +0800 @@ -135,6 +135,10 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TEE) += xt_TEE.o obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o obj-$(CONFIG_NETFILTER_XT_TARGET_IDLETIMER) += xt_IDLETIMER.o +# ZyXEL QoS, John (porting from MSTC) +obj-$(CONFIG_NETFILTER_XT_TARGET_AUTOMAP) += xt_AUTOMAP.o +# ZyXEL QoS, Mark (porting from MSTC) +obj-$(CONFIG_NETFILTER_XT_POLICER) += xt_policer.o ifdef BCM_KF # defined(CONFIG_BCM_KF_NETFILTER) obj-$(CONFIG_NETFILTER_XT_TARGET_SKIPLOG) += xt_SKIPLOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_DC) += xt_DC.o Index: linux-4.1.52/net/netfilter/xt_AUTOMAP.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/net/netfilter/xt_AUTOMAP.c 2018-01-22 14:21:12.873630793 +0800 @@ -0,0 +1,180 @@ +/* x_tables module for setting the IPv4/IPv6 DSCP field, Version 1.8 + * + * (C) 2002 by Harald Welte + * based on ipt_FTOS.c (C) 2000 by Matthew G. Marsh + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * See RFC2474 for a description of the DSCP field within the IP Header. + * + * xt_DSCP.c,v 1.8 2002/08/06 18:41:57 laforge Exp +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +MODULE_LICENSE("GPL"); +MODULE_ALIAS("ipt_AUTOMAP"); +MODULE_ALIAS("ip6t_AUTOMAP"); + +static int getVlanPrioAndIpHeader(struct sk_buff *skb, unsigned char *prio, struct iphdr **iph){ + unsigned short TCI; + unsigned short id; /* VLAN ID, given from frame TCI */ + /* Need to recalculate IP header checksum after altering TOS byte */ + const struct vlan_hdr *fp; + struct vlan_hdr _frame; + struct iphdr *ih = NULL; + + /* get ip header */ + ih = NULL; + ih = ip_hdr(skb); + + *iph = ih; + + /* check VLAN header is parsed or not ? */ + if(ntohs(((struct vlan_hdr *)(skb->vlan_header))->h_vlan_encapsulated_proto) == 0){ + + /* tagged packet */ + if(skb->protocol == ETH_P_8021Q) { + + fp = skb_header_pointer(skb, 0, sizeof(_frame), &_frame); + if (fp == NULL) + return -1; + + /* Tag Control Information (TCI) consists of the following elements: + * - User_priority. The user_priority field is three bits in length, + * interpreted as a binary number. + * - Canonical Format Indicator (CFI). The Canonical Format Indicator + * (CFI) is a single bit flag value. Currently ignored. + * - VLAN Identifier (VID). The VID is encoded as + * an unsigned binary number. + */ + TCI = ntohs(fp->h_vlan_TCI); + id = TCI & VLAN_VID_MASK; + *prio = (TCI >> 13) & 0x7; + + } + else { /* untagged packet */ + TCI = 0; + id = 0; + /* Packet with no VLAN tag will be sent to default queue just like 1p value is 1 */ + *prio = 1; + } + + } + else{ + /* for new broadcom vlan device */ + TCI = ntohs(((struct vlan_hdr *)(skb->vlan_header))->h_vlan_TCI); + id = TCI & VLAN_VID_MASK; + *prio = (TCI >> 13) & 0x7; + } + + return 0; +} + +//static unsigned int target(struct sk_buff **pskb, const struct xt_tgchk_param *par) +static unsigned int AUTOMAP_target_v4(struct sk_buff *skb, const struct xt_action_param *par) + //const struct net_device *in, + //const struct net_device *out, + //unsigned int hooknum, + //const struct xt_target *target, + //const void *targinfo) +{ + const struct xt_automap_target_info *aminfo = par->targinfo; + struct iphdr *iph = NULL; + unsigned char prio = 0; + unsigned char dscp = 0; + unsigned char dscpPrecedence = 0; + + if(aminfo->flags & XT_AUTO_TYPE){ + getVlanPrioAndIpHeader(skb, &prio, &iph); + + switch(aminfo->type){ + case AUTOMAP_TYPE_8021P: + /* mark priority queue */ + skb->mark |= vlan8021pToPriorityQueue[prio]; + + /* lookup upstream 8021p to DSCP value table */ + dscp = vlan8021pToDSCP[prio]; + + /* mark DSCP value */ + if (!skb_make_writable(skb, sizeof(struct iphdr))) + return NF_DROP; + + ipv4_change_dsfield(ip_hdr(skb), (__u8)(~XT_DSCP_MASK), dscp << XT_DSCP_SHIFT); + + break; + case AUTOMAP_TYPE_DSCP: + /* get dscp precedence */ + dscpPrecedence = ((iph->tos)>>5)&0x7; + + /* mark priority queue */ + skb->mark |= dscpPrecedenceToPriorityQueue[dscpPrecedence]; + + /* it should mark 8021p here, TBD */ + + break; + case AUTOMAP_TYPE_PKTLEN: + + if(iph->tot_len > 1100){ + skb->mark|=vlan8021pToPriorityQueue[0]; /* queue priority 2 */ + }else if(iph->tot_len < 250){ + skb->mark|=vlan8021pToPriorityQueue[5]; /* queue priority 5 */ + }else{ /*250~1100*/ + skb->mark|=vlan8021pToPriorityQueue[3]; /* queue priority 3 */ + } + break; + default: + printk("unknown AUTOMAP type: \n"); + break; + } + } + + return XT_CONTINUE; +} + + +static int AUTOMAP_checkentry_v4(const struct xt_tgchk_param *par) +{ + return 0; +} + +static struct xt_target xt_auto_target __read_mostly = { + + .name = "AUTOMAP", + .revision = 0, + .family = NFPROTO_IPV4, + .checkentry = AUTOMAP_checkentry_v4, + .target = AUTOMAP_target_v4, + .targetsize = sizeof(struct xt_automap_target_info), + .table = "mangle", + .me = THIS_MODULE, + +}; + +static int __init xt_automap_target_init(void) +{ + //return xt_register_targets(xt_auto_target, ARRAY_SIZE(xt_auto_target)); + return xt_register_target(&xt_auto_target); +} + +static void __exit xt_automap_target_fini(void) +{ + //xt_unregister_targets(xt_auto_target, ARRAY_SIZE(xt_auto_target)); + xt_unregister_target(&xt_auto_target); +} + +module_init(xt_automap_target_init); +module_exit(xt_automap_target_fini); Index: linux-4.1.52/net/netfilter/xt_mark.c =================================================================== --- linux-4.1.52.orig/net/netfilter/xt_mark.c 2018-01-22 14:21:12.769630791 +0800 +++ linux-4.1.52/net/netfilter/xt_mark.c 2018-01-22 14:21:12.873630793 +0800 @@ -24,6 +24,49 @@ MODULE_ALIAS("ipt_MARK"); MODULE_ALIAS("ip6t_MARK"); +#if 1 /* ZyXEL QoS, John (porting from MSTC) */ +#include "skb_defines.h" +#endif + +#if 1 /* ZyXEL QoS, John */ +static unsigned int +mark_tg(struct sk_buff *skb, const struct xt_action_param *par) +{ + const struct xt_mark_tginfo2 *markinfo = par->targinfo; + int mark = 0; + + switch (markinfo->mode) { + case XT_MARK_SET: + mark = markinfo->mark; + break; + + case XT_MARK_AND: + mark = skb->mark & markinfo->mark; + break; + + case XT_MARK_OR: + mark = skb->mark | markinfo->mark; + break; + + case XT_MARK_VTAG_SET: + mark = skb->mark; + skb->vtag = (unsigned short)(markinfo->mark); + break; + } + +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG_FEATURE) + skb->ipt_check |= IPT_TARGET_MARK; + skb->ipt_log.u32[BLOG_ORIGINAL_MARK_INDEX] = skb->mark; + skb->ipt_log.u32[BLOG_TARGET_MARK_INDEX] = mark; + if ( skb->ipt_check & IPT_TARGET_CHECK ) + return XT_CONTINUE; +#endif + + skb->mark = mark; + return XT_CONTINUE; +} + +#else static unsigned int mark_tg(struct sk_buff *skb, const struct xt_action_param *par) { @@ -41,6 +84,7 @@ skb->mark = (skb->mark & ~info->mask) ^ info->mark; return XT_CONTINUE; } +#endif static bool mark_mt(const struct sk_buff *skb, struct xt_action_param *par) Index: linux-4.1.52/net/netfilter/xt_policer.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-4.1.52/net/netfilter/xt_policer.c 2018-01-22 16:32:14.193821131 +0800 @@ -0,0 +1,382 @@ +/* Kernel module to control the rate in kbps. */ +/* This program is free software; you can redistribute it and/or modify + * * it under the terms of the GNU General Public License version 2 as + * * published by the Free Software Foundation. */ +/* ZyXEL Birken, 20100107. */ + +#include +#include +#include +#include +#include +#include +#if 1 //__MSTC__, Eric, Qos policer. +#include "skb_defines.h" +#define RED 1 +#define YELLOW 2 +#define GREEN 3 +#endif +#if 1//__MSTC__, Jones For compilation +#define MODE_TBF 0 +#define MODE_SRTCM 1 +#define MODE_TRTCM 2 +#endif + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Herve Eychenne "); +MODULE_DESCRIPTION("iptables rate policer match"); +MODULE_ALIAS("ipt_policer"); +MODULE_ALIAS("ip6t_policer"); + +/* The algorithm used is the Simple Token Bucket Filter (TBF) + * * see net/sched/sch_tbf.c in the linux source tree. */ + +static DEFINE_SPINLOCK(policer_lock); + +#if 0 //__MSTC__, richard, QoS +static int +ipt_policer_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset, + unsigned int protoff, + int *hotdrop) +#else +static bool ipt_policer_match(const struct sk_buff *skb, struct xt_action_param *par) +#endif //__MSTC__, richard, QoS +{ +#if 1//__MSTC__, Jones For compilation + struct xt_policerinfo *r = (struct xt_policerinfo *)par->matchinfo; + unsigned long now = jiffies; + unsigned long timePassed = 0; + struct sk_buff *tmp; + u_int32_t cost = 0; + u_int32_t extraCredit = 0; + spin_lock_bh(&policer_lock); + +#if 1 //__OBM__, Jones +#if defined(CONFIG_MIPS_BRCM) && defined(CONFIG_BLOG) + blog_skip((struct sk_buff *)skb, blog_skip_reason_nf_xt_skiplog); +#endif +#endif + switch(r->policerMode) { + /* Token Bucket Filter (tbf) mode */ + /* The algorithm used is the Simple Token Bucket Filter (TBF) + see net/sched/sch_tbf.c in the linux source tree. */ + case MODE_TBF: + r->credit += (now - xchg(&r->prev, now)) * r->rate; /* Add TBF cerdit */ + if (r->credit > r->creditCap) { + r->credit = r->creditCap; + } + cost = (skb->len + skb->mac_len) * BITS_PER_BYTE; + if (r->credit >= cost) { + /* We're not limited. (Match) */ + r->credit -= cost; /* Take out credit */ + spin_unlock_bh(&policer_lock); + return true; + break; + } + /* We're limited. (Not Match) */ + spin_unlock_bh(&policer_lock); + return false; + break; + + /* Single Rate Three Color Marker (srTCM) Mode */ + case MODE_SRTCM: + /* Add CBS first */ + r->credit += (now - xchg(&r->prev, now)) * r->rate; /* Add CBS cerdit */ + if (r->credit > r->creditCap) { + extraCredit = r->credit - r->creditCap; + r->credit = r->creditCap; + } + if (r->pbsCredit < r->pbsCreditCap && extraCredit > 0) { + r->pbsCredit += extraCredit; /* Add EBS cerdit */ + if (r->pbsCredit > r->pbsCreditCap) { + r->pbsCredit = r->pbsCreditCap; + } + } + cost = (skb->len + skb->mac_len) * BITS_PER_BYTE; + tmp = (struct sk_buff *)skb; + if (r->credit >= cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , GREEN); /* Green */ + r->credit -= cost; + } + else if (r->pbsCredit >= cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , YELLOW); /* Yellow */ + r->pbsCredit -= cost; + } + else { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , RED); /* Red */ + } + spin_unlock_bh(&policer_lock); + return true; + break; + + /* Two Rate Three Color Marker (srTCM) Mode */ + case MODE_TRTCM: + timePassed = (now - xchg(&r->prev, now)); + r->credit += timePassed * r->rate; /* Add CBS cerdit */ + r->pbsCredit += timePassed * r->pRate; /* Add PBS cerdit */ + if (r->credit > r->creditCap) { + r->credit = r->creditCap; + } + if (r->pbsCredit > r->pbsCreditCap) { + r->pbsCredit = r->pbsCreditCap; + } + cost = (skb->len + skb->mac_len) * BITS_PER_BYTE; + tmp = (struct sk_buff *)skb; + if (r->pbsCredit < cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , RED); /* Red */ + } + else if (r->credit < cost) { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , YELLOW); /* Yellow */ + r->pbsCredit -= cost; + } + else { + tmp->mark &= ~(SKBMARK_POLICER_M); /* Reset 2 color bit */ + tmp->mark |= SKBMARK_SET_POLICER(0 , GREEN); /* Green */ + r->pbsCredit -= cost; + r->credit -= cost; + } + spin_unlock_bh(&policer_lock); + return true; + break; + + default: + return false; + } +#else +#if 0 //__MSTC__, richard, QoS + struct xt_policerinfo *r = ((struct xt_policerinfo *)matchinfo)->master; +#else + struct xt_policerinfo *r = (struct xt_policerinfo *)par->matchinfo; +#endif //__MSTC__, richard, QoS + + unsigned long now = jiffies; + spin_lock_bh(&policer_lock); + r->credit += (now - xchg(&r->prev, now)) * r->avg; /* Add cerdit */ + if (r->credit > r->credit_cap) { + r->credit = r->credit_cap; + } + u_int32_t temp_cost = 0; + temp_cost = (skb->len + skb->mac_len) * r->cost; + if (r->credit >= temp_cost) { + /* We're not limited. */ + r->credit -= temp_cost; /* Take out credit */ + spin_unlock_bh(&policer_lock); +#if 0 //__MSTC__, richard, QoS + return 1; +#else + return true; + ////return false; +#endif //__MSTC__, richard, QoS + } + spin_unlock_bh(&policer_lock); + +#if 0 //__MSTC__, richard, QoS + return 0; +#else + return false; + ////return true; +#endif //__MSTC__, richard, QoS +#endif +} + + +#if 1//__MSTC__, Jones For compilation +/* Precision saver. */ +/* As a policer rule added, this function will be executed */ +static int +ipt_policer_checkentry(const struct xt_mtchk_param *par) +{ + struct xt_policerinfo *r = (struct xt_policerinfo *)par->matchinfo; + /* For SMP, we only want to use one set of counters. */ + r->master = r; + + /* pRate must be equal or greater than crate. */ + if (r->policerMode == 2) { + if (r->rate > r->pRate) { + return -EINVAL; + } + } + + if (r->creditCap == 0) { /* Check if policer initiate or not. */ + switch(r->policerMode) { + case MODE_TBF: + r->prev = jiffies; + r->creditCap = r->burst * BITS_PER_BYTE * KILO_SCALE; /* TBF Credits full */ + r->credit = r->creditCap; /* TBF Credits full */ + break; + + case MODE_SRTCM: + r->prev = jiffies; + r->creditCap = r->burst * BITS_PER_BYTE * KILO_SCALE; /* CBS Credits full */ + r->credit = r->creditCap; /* CBS Credits full */ + r->pbsCreditCap = r->pbsBurst * BITS_PER_BYTE * KILO_SCALE; /* EBS Credits full */ + r->pbsCredit = r->pbsCreditCap; /* EBS Credits full */ + break; + + case MODE_TRTCM: + r->prev = jiffies; + r->creditCap = r->burst * BITS_PER_BYTE * KILO_SCALE; /* CBS Credits full. */ + r->credit = r->creditCap; /* CBS Credits full. */ + r->pbsCreditCap = r->pbsBurst * BITS_PER_BYTE * KILO_SCALE; /* PBS Credits full. */ + r->pbsCredit = r->pbsCreditCap; /* PBS Credits full. */ + break; + + default: + return -EINVAL; + } + } + return 0; +} +/* end ipt_policer_checkentry */ +#else +/* Precision saver. */ +/* As a policer rule added, this function will be executed */ +#if 0 //__MSTC__, richard, QoS +static int +ipt_policer_checkentry(const char *tablename, + const void *inf, + const struct xt_match *match, + void *matchinfo, + unsigned int hook_mask) +#else +static bool +ipt_policer_checkentry(const struct xt_mtchk_param *par) +#endif //__MSTC__, richard, QoS +{ +#if 0 //__MSTC__, richard, QoS + struct xt_policerinfo *r = matchinfo; +#else + struct xt_policerinfo *r = (struct xt_policerinfo *)par->matchinfo; +#endif //__MSTC__, richard, QoS + + /* For SMP, we only want to use one set of counters. */ + r->master = r; + if (r->cost == 0) { + r->prev = jiffies; + r->credit_cap = r->burst * BITS_PER_BYTE * KILO_SCALE; /*Credits full.*/ + r->credit = r->credit_cap; /*Credits full.*/ + r->cost = BITS_PER_BYTE; + } +#if 0 //__MSTC__, richard, QoS + return 1; +#else + return true; +#endif //__MSTC__, richard, QoS +} +#endif + +////#if 0 /* We do not know what this is for. Comment it temporarily. ZyXEL Birken, 20100107. */ +#ifdef CONFIG_COMPAT +struct compat_xt_rateinfo { + u_int32_t avg; + u_int32_t burst; + + compat_ulong_t prev; + u_int32_t credit; + u_int32_t credit_cap, cost; + + u_int32_t master; +}; + +/* To keep the full "prev" timestamp, the upper 32 bits are stored in the + * * master pointer, which does not need to be preserved. */ +static void compat_from_user(void *dst, void *src) +{ + struct compat_xt_rateinfo *cm = src; + struct xt_policerinfo m = { + .avg = cm->avg, + .burst = cm->burst, + .prev = cm->prev | (unsigned long)cm->master << 32, + .credit = cm->credit, + .credit_cap = cm->credit_cap, + .cost = cm->cost, + }; + memcpy(dst, &m, sizeof(m)); +} + +static int compat_to_user(void __user *dst, void *src) +{ + struct xt_policerinfo *m = src; + struct compat_xt_rateinfo cm = { + .avg = m->avg, + .burst = m->burst, + .prev = m->prev, + .credit = m->credit, +#if 1//__MSTC__, Jones For compilation + .credit_cap = m->creditCap, +#else + .credit_cap = m->credit_cap, +#endif + .cost = m->cost, + .master = m->prev >> 32, + }; + return copy_to_user(dst, &cm, sizeof(cm)) ? -EFAULT : 0; +} +#endif /* CONFIG_COMPAT */ +////#endif + +#if 0 //__MSTC__, richard, QoS +static struct xt_match xt_policer_match[] __read_mostly = { + { +#else +static struct xt_match xt_policer_match __read_mostly = { +#endif //__MSTC__, richard, QoS + .name = "policer", +#if 0 //__MSTC__, richard, QoS + .family = AF_INET, +#else + .family = NFPROTO_UNSPEC, +#endif //__MSTC__, richard, QoS + .checkentry = ipt_policer_checkentry, + .match = ipt_policer_match, + .matchsize = sizeof(struct xt_policerinfo), +#ifdef CONFIG_COMPAT + .compatsize = sizeof(struct compat_xt_rateinfo), + .compat_from_user = compat_from_user, + .compat_to_user = compat_to_user, +#endif + .me = THIS_MODULE, +#if 0 //__MSTC__, richard, QoS + }, + { + .name = "policer", + .family = AF_INET6, + .checkentry = ipt_policer_checkentry, + .match = ipt_policer_match, + .matchsize = sizeof(struct xt_policerinfo), + .me = THIS_MODULE, + }, +#endif //__MSTC__, richard, QoS +}; + +static int __init xt_policer_init(void) +{ +#if 0 //__MSTC__, richard, QoS + return xt_register_matches(xt_policer_match, ARRAY_SIZE(xt_policer_match)); +#else + return xt_register_match(&xt_policer_match); +#endif //__MSTC__, richard, QoS +} + +static void __exit xt_policer_fini(void) +{ +#if 0 //__MSTC__, richard, QoS + xt_unregister_matches(xt_policer_match, ARRAY_SIZE(xt_policer_match)); +#else + xt_unregister_match(&xt_policer_match); +#endif //__MSTC__, richard, QoS +} + +module_init(xt_policer_init); +module_exit(xt_policer_fini); + Index: linux-4.1.52/net/sched/sch_htb.c =================================================================== --- linux-4.1.52.orig/net/sched/sch_htb.c 2018-01-22 14:21:12.785630791 +0800 +++ linux-4.1.52/net/sched/sch_htb.c 2018-01-22 14:21:12.877630793 +0800 @@ -584,6 +584,9 @@ __skb_queue_tail(&q->direct_queue, skb); q->direct_pkts++; } else { +#if 1 /* ZyXEL QoS, porting from MSTC */ + sch->bstats.dropbytes += skb->len; +#endif return qdisc_drop(skb, sch); } #ifdef CONFIG_NET_CLS_ACT @@ -597,6 +600,9 @@ if (net_xmit_drop_count(ret)) { qdisc_qstats_drop(sch); cl->qstats.drops++; +#if 1 /* ZyXEL QoS, porting from MSTC */ + sch->bstats.dropbytes += skb->len; +#endif } return ret; } else { Index: linux-4.1.52/net/sched/sch_sfq.c =================================================================== --- linux-4.1.52.orig/net/sched/sch_sfq.c 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/net/sched/sch_sfq.c 2018-01-22 14:21:12.877630793 +0800 @@ -329,6 +329,9 @@ len = qdisc_pkt_len(skb); slot->backlog -= len; sfq_dec(q, x); +#if 1 /* ZyXEL QoS, porting from MSTC */ + sch->bstats.dropbytes += skb->len; +#endif kfree_skb(skb); sch->q.qlen--; qdisc_qstats_drop(sch); @@ -380,6 +383,9 @@ if (hash == 0) { if (ret & __NET_XMIT_BYPASS) qdisc_qstats_drop(sch); +#if 1 /* ZyXEL QoS, porting from MSTC */ + sch->bstats.dropbytes += skb->len; +#endif kfree_skb(skb); return ret; } @@ -446,6 +452,9 @@ if (slot->qlen >= q->maxdepth) { congestion_drop: +#if 1 /* ZyXEL QoS, porting from MSTC */ + sch->bstats.dropbytes += skb->len; +#endif if (!sfq_headdrop(q)) return qdisc_drop(skb, sch); Index: linux-4.1.52/net/sched/sch_tbf.c =================================================================== --- linux-4.1.52.orig/net/sched/sch_tbf.c 2017-10-17 06:54:53.000000000 +0800 +++ linux-4.1.52/net/sched/sch_tbf.c 2018-01-22 16:24:04.901809284 +0800 @@ -21,6 +21,9 @@ #include #include #include +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) /* ZyXEL QoS, porting from MSTC */ +#include +#endif /* Simple Token Bucket Filter. @@ -202,8 +205,16 @@ } ret = qdisc_enqueue(skb, q->qdisc); if (ret != NET_XMIT_SUCCESS) { +#if 1 /* ZyXEL QoS, porting from MSTC */ if (net_xmit_drop_count(ret)) + { qdisc_qstats_drop(sch); + sch->bstats.dropbytes += skb->len; + } +#else + if (net_xmit_drop_count(ret)) + qdisc_qstats_drop(sch); +#endif return ret; } @@ -266,6 +277,9 @@ sch->q.qlen--; qdisc_unthrottled(sch); qdisc_bstats_update(sch, skb); +#if defined(CONFIG_BCM_KF_BLOG) && defined(CONFIG_BLOG) /* ZyXEL QoS, porting from MSTC */ + blog_skip(skb, blog_skip_reason_sch_htb); +#endif return skb; }