blob: abe7f101f182d78357ca46325e8fd6e85e6da96e [file] [log] [blame]
developer0fb30d52023-12-04 09:51:36 +08001// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (c) 2023 MediaTek Inc. All Rights Reserved.
4 *
5 * Author: Ren-Ting Wang <ren-ting.wang@mediatek.com>
6 */
7
8#include "tops/internal.h"
9#include "tops/protocol/network/ip.h"
10#include "tops/protocol/transport/udp.h"
11
12int mtk_tops_ip_encap_param_setup(
13 struct sk_buff *skb,
14 struct tops_params *params,
15 int (*tnl_encap_param_setup)(struct sk_buff *skb,
16 struct tops_params *params))
17{
18 struct tops_ip_params *ipp = &params->network.ip;
19 struct iphdr *ip;
20 struct iphdr iph;
21 int ret;
22
23 ip = skb_header_pointer(skb, 0, sizeof(struct iphdr), &iph);
24 if (unlikely(!ip))
25 return -EINVAL;
26
27 if (unlikely(ip->version != IPVERSION)) {
28 TOPS_NOTICE("ip ver: 0x%x invalid\n", ip->version);
29 return -EINVAL;
30 }
31
32 params->network.type = TOPS_NETWORK_IPV4;
33
34 ipp->proto = ip->protocol;
35 ipp->sip = ip->saddr;
36 ipp->dip = ip->daddr;
37 ipp->tos = ip->tos;
38 ipp->ttl = ip->ttl;
39
40 skb_pull(skb, sizeof(struct iphdr));
41
42 switch (ip->protocol) {
43 case IPPROTO_UDP:
44 ret = mtk_tops_udp_encap_param_setup(skb,
45 params,
46 tnl_encap_param_setup);
47 break;
48 case IPPROTO_GRE:
49 ret = tnl_encap_param_setup(skb, params);
50 break;
51 default:
52 ret = -EINVAL;
53 break;
54 };
55
56 skb_push(skb, sizeof(struct iphdr));
57
58 return ret;
59}
60
61int mtk_tops_ip_decap_param_setup(struct sk_buff *skb, struct tops_params *params)
62{
63 struct tops_ip_params *ipp;
64 struct iphdr *ip;
65 struct iphdr iph;
66 int ret;
67
68 skb_push(skb, sizeof(struct iphdr));
69 ip = skb_header_pointer(skb, 0, sizeof(struct iphdr), &iph);
70 if (unlikely(!ip)) {
71 ret = -EINVAL;
72 goto out;
73 }
74
75 if (unlikely(ip->version != IPVERSION)) {
76 ret = -EINVAL;
77 goto out;
78 }
79
80 params->network.type = TOPS_NETWORK_IPV4;
81
82 ipp = &params->network.ip;
83
84 ipp->proto = ip->protocol;
85 ipp->sip = ip->daddr;
86 ipp->dip = ip->saddr;
87 ipp->tos = ip->tos;
88 /*
89 * if encapsulation parameter is already configured, TTL will remain as
90 * encapsulation's data
91 */
92 ipp->ttl = 128;
93
94 ret = mtk_tops_mac_decap_param_setup(skb, params);
95
96out:
97 skb_pull(skb, sizeof(struct iphdr));
98
99 return ret;
100}
101
102static int tops_ip_debug_param_fetch_ip(const char *buf, int *ofs, u32 *ip)
103{
104 int nchar = 0;
105 int ret = 0;
106 u8 tmp[4];
107
108 ret = sscanf(buf + *ofs, "%hhu.%hhu.%hhu.%hhu %n",
109 &tmp[3], &tmp[2], &tmp[1], &tmp[0], &nchar);
110 if (ret != 4)
111 return -EPERM;
112
113 *ip = tmp[3] | tmp[2] << 8 | tmp[1] << 16 | tmp[0] << 24;
114
115 *ofs += nchar;
116
117 return 0;
118}
119
120int mtk_tops_ip_debug_param_setup(const char *buf, int *ofs,
121 struct tops_params *params)
122{
123 char proto[DEBUG_PROTO_LEN] = {0};
124 int ret;
125
126 params->network.type = TOPS_NETWORK_IPV4;
127
128 ret = tops_ip_debug_param_fetch_ip(buf, ofs, &params->network.ip.sip);
129 if (ret)
130 return ret;
131
132 ret = tops_ip_debug_param_fetch_ip(buf, ofs, &params->network.ip.dip);
133 if (ret)
134 return ret;
135
136 ret = mtk_tops_debug_param_proto_peek(buf, *ofs, proto);
137 if (ret < 0)
138 return ret;
139
140 if (!strcmp(proto, DEBUG_PROTO_UDP)) {
141 params->network.ip.proto = IPPROTO_UDP;
142 *ofs += ret;
143 ret = mtk_tops_udp_debug_param_setup(buf, ofs, params);
144 } else if (!strcmp(proto, DEBUG_PROTO_GRETAP)) {
145 params->network.ip.proto = IPPROTO_GRE;
146 ret = 0;
147 } else {
148 ret = -EINVAL;
149 }
150
151 return ret;
152}
153
154void mtk_tops_ip_param_dump(struct seq_file *s, struct tops_params *params)
155{
156 struct tops_ip_params *ipp = &params->network.ip;
157 u32 sip = params->network.ip.sip;
158 u32 dip = params->network.ip.dip;
159
160 seq_puts(s, "\tNetwork Type: IPv4 ");
161 seq_printf(s, "sip: %pI4 dip: %pI4 protocol: 0x%02x tos: 0x%02x ttl: %03u\n",
162 &sip, &dip, ipp->proto, ipp->tos, ipp->ttl);
163}