[qca-edma] Add PPPoE support for per-precedence stats
Add support to update per-precedence stats for PPPoE packets
Change-Id: I38e881fb82881da2fd7873874de0cca232e43e0a
Signed-off-by: Rakesh Nair <ranair@codeaurora.org>
diff --git a/edma.c b/edma.c
index 3932454..c67be79 100644
--- a/edma.c
+++ b/edma.c
@@ -1149,6 +1149,97 @@
etdr->sw_next_to_fill = start_index;
}
+/* edma_get_v4_precedence()
+ * Function to retrieve precedence for IPv4
+ */
+static inline int edma_get_v4_precedence(struct sk_buff *skb, int nh_offset, u8 *precedence)
+{
+ const struct iphdr *iph;
+ struct iphdr iph_hdr;
+
+ iph = skb_header_pointer(skb, nh_offset, sizeof(iph_hdr), &iph_hdr);
+
+ if (!iph || iph->ihl < 5)
+ return -1;
+
+ *precedence = iph->tos >> EDMA_DSCP_PREC_SHIFT;
+
+ return 0;
+}
+
+/* edma_get_v6_precedence()
+ * Function to retrieve precedence for IPv6
+ */
+static inline int edma_get_v6_precedence(struct sk_buff *skb, int nh_offset, u8 *precedence)
+{
+ const struct ipv6hdr *iph;
+ struct ipv6hdr iph_hdr;
+
+ iph = skb_header_pointer(skb, nh_offset, sizeof(iph_hdr), &iph_hdr);
+
+ if (!iph)
+ return -1;
+
+ *precedence = iph->priority >> EDMA_DSCP6_PREC_SHIFT;
+
+ return 0;
+}
+
+/* edma_get_skb_precedence()
+ * Function to retrieve precedence from skb
+ */
+static int edma_get_skb_precedence(struct sk_buff *skb, u8 *precedence)
+{
+ int nhoff = skb_network_offset(skb);
+ __be16 proto = skb->protocol;
+ int ret;
+ struct pppoeh_proto *pppoeh, ppp_hdr;
+
+ switch(proto) {
+ case __constant_htons(ETH_P_IP): {
+ ret = edma_get_v4_precedence(skb, nhoff, precedence);
+ if (ret)
+ return -1;
+ break;
+ }
+ case __constant_htons(ETH_P_IPV6): {
+ ret = edma_get_v6_precedence(skb, nhoff, precedence);
+ if (ret)
+ return -1;
+ break;
+ }
+ case __constant_htons(ETH_P_PPP_SES): {
+ pppoeh = skb_header_pointer(skb, nhoff, sizeof(ppp_hdr), &ppp_hdr);
+ if (!pppoeh)
+ return -1;
+
+ proto = pppoeh->proto;
+ nhoff += PPPOE_SES_HLEN;
+ switch (proto) {
+ case __constant_htons(PPP_IP): {
+ ret = edma_get_v4_precedence(skb, nhoff, precedence);
+ if (ret)
+ return -1;
+ break;
+ }
+ case __constant_htons(PPP_IPV6): {
+ ret = edma_get_v6_precedence(skb, nhoff, precedence);
+ if (ret)
+ return -1;
+ break;
+ }
+ default:
+ return -1;
+ }
+ break;
+ }
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
/* edma_tx_map_and_fill()
* gets called from edma_xmit_frame
*
@@ -1385,32 +1476,15 @@
/* If sysctl support for per-precedence stats are enabled */
if (edma_per_prec_stats_enable) {
- struct iphdr *ip_hdr = NULL;
- struct ipv6hdr *ip6_hdr = NULL;
- uint8_t precedence = 0xff;
+ uint8_t precedence = 0;
- if (likely(htons(ETH_P_IP) == skb->protocol)) {
- ip_hdr = (struct iphdr *)skb_network_header(skb);
- if (ip_hdr && ((ip_hdr->protocol == IPPROTO_UDP) || (ip_hdr->protocol == IPPROTO_TCP)))
- precedence = ip_hdr->tos >> EDMA_DSCP_PREC_SHIFT;
-
+ if(!edma_get_skb_precedence(skb, &precedence)) {
/* Increment per-precedence counters for tx packets
* and set the precedence in the TPD.
*/
edma_cinfo->edma_ethstats.tx_prec[precedence]++;
edma_cinfo->edma_ethstats.tx_ac[edma_dscp2ac_tbl[precedence]]++;
tpd->word3 |= precedence << EDMA_TPD_PRIO_SHIFT;
- } else if (htons(ETH_P_IPV6) == skb->protocol) {
- ip6_hdr = (struct ipv6hdr *)skb_network_header(skb);
- if (ip6_hdr && ((ip6_hdr->nexthdr == IPPROTO_UDP) || (ip6_hdr->nexthdr == IPPROTO_TCP)))
- precedence = ip6_hdr->priority >> EDMA_DSCP6_PREC_SHIFT;
-
- /* Increment per-precedence counters for tx packets
- * and set the precedence in the TPD for v6 packets.
- */
- edma_cinfo->edma_ethstats.tx_prec[precedence]++;
- edma_cinfo->edma_ethstats.tx_ac[edma_dscp2ac_tbl[precedence]]++;
- tpd->word3 |= precedence << EDMA_TPD_PRIO_SHIFT;
}
}