]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | /* SPDX-License-Identifier: BSD-3-Clause |
2 | * Copyright(C) 2019 Marvell International Ltd. | |
3 | */ | |
4 | ||
5 | #include "l2fwd_poll.h" | |
6 | ||
7 | static inline void | |
8 | l2fwd_poll_simple_forward(struct l2fwd_resources *rsrc, struct rte_mbuf *m, | |
9 | uint32_t portid) | |
10 | { | |
11 | struct rte_eth_dev_tx_buffer *buffer; | |
12 | uint32_t dst_port; | |
13 | int sent; | |
14 | ||
15 | dst_port = rsrc->dst_ports[portid]; | |
16 | ||
17 | if (rsrc->mac_updating) | |
18 | l2fwd_mac_updating(m, dst_port, &rsrc->eth_addr[dst_port]); | |
19 | ||
20 | buffer = ((struct l2fwd_poll_resources *)rsrc->poll_rsrc)->tx_buffer[ | |
21 | dst_port]; | |
22 | sent = rte_eth_tx_buffer(dst_port, 0, buffer, m); | |
23 | if (sent) | |
24 | rsrc->port_stats[dst_port].tx += sent; | |
25 | } | |
26 | ||
27 | /* main poll mode processing loop */ | |
28 | static void | |
29 | l2fwd_poll_main_loop(struct l2fwd_resources *rsrc) | |
30 | { | |
31 | uint64_t prev_tsc, diff_tsc, cur_tsc, drain_tsc; | |
32 | struct l2fwd_poll_resources *poll_rsrc = rsrc->poll_rsrc; | |
33 | struct rte_mbuf *pkts_burst[MAX_PKT_BURST]; | |
34 | struct rte_eth_dev_tx_buffer *buf; | |
35 | struct lcore_queue_conf *qconf; | |
36 | uint32_t i, j, port_id, nb_rx; | |
37 | struct rte_mbuf *m; | |
38 | uint32_t lcore_id; | |
39 | int32_t sent; | |
40 | ||
41 | drain_tsc = (rte_get_tsc_hz() + US_PER_S - 1) / US_PER_S * | |
42 | BURST_TX_DRAIN_US; | |
43 | prev_tsc = 0; | |
44 | ||
45 | lcore_id = rte_lcore_id(); | |
46 | qconf = &poll_rsrc->lcore_queue_conf[lcore_id]; | |
47 | ||
48 | if (qconf->n_rx_port == 0) { | |
49 | printf("lcore %u has nothing to do\n", lcore_id); | |
50 | return; | |
51 | } | |
52 | ||
53 | printf("entering main loop on lcore %u\n", lcore_id); | |
54 | ||
55 | for (i = 0; i < qconf->n_rx_port; i++) { | |
56 | ||
57 | port_id = qconf->rx_port_list[i]; | |
58 | printf(" -- lcoreid=%u port_id=%u\n", lcore_id, port_id); | |
59 | ||
60 | } | |
61 | ||
62 | while (!rsrc->force_quit) { | |
63 | ||
64 | cur_tsc = rte_rdtsc(); | |
65 | ||
66 | /* | |
67 | * TX burst queue drain | |
68 | */ | |
69 | diff_tsc = cur_tsc - prev_tsc; | |
70 | if (unlikely(diff_tsc > drain_tsc)) { | |
71 | for (i = 0; i < qconf->n_rx_port; i++) { | |
72 | port_id = | |
73 | rsrc->dst_ports[qconf->rx_port_list[i]]; | |
74 | buf = poll_rsrc->tx_buffer[port_id]; | |
75 | sent = rte_eth_tx_buffer_flush(port_id, 0, buf); | |
76 | if (sent) | |
77 | rsrc->port_stats[port_id].tx += sent; | |
78 | } | |
79 | ||
80 | prev_tsc = cur_tsc; | |
81 | } | |
82 | ||
83 | /* | |
84 | * Read packet from RX queues | |
85 | */ | |
86 | for (i = 0; i < qconf->n_rx_port; i++) { | |
87 | ||
88 | port_id = qconf->rx_port_list[i]; | |
89 | nb_rx = rte_eth_rx_burst(port_id, 0, pkts_burst, | |
90 | MAX_PKT_BURST); | |
91 | ||
92 | rsrc->port_stats[port_id].rx += nb_rx; | |
93 | ||
94 | for (j = 0; j < nb_rx; j++) { | |
95 | m = pkts_burst[j]; | |
96 | rte_prefetch0(rte_pktmbuf_mtod(m, void *)); | |
97 | l2fwd_poll_simple_forward(rsrc, m, port_id); | |
98 | } | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
103 | static void | |
104 | l2fwd_poll_lcore_config(struct l2fwd_resources *rsrc) | |
105 | { | |
106 | struct l2fwd_poll_resources *poll_rsrc = rsrc->poll_rsrc; | |
107 | struct lcore_queue_conf *qconf = NULL; | |
108 | uint32_t rx_lcore_id = 0; | |
109 | uint16_t port_id; | |
110 | ||
111 | /* Initialize the port/queue configuration of each logical core */ | |
112 | RTE_ETH_FOREACH_DEV(port_id) { | |
113 | /* skip ports that are not enabled */ | |
114 | if ((rsrc->enabled_port_mask & (1 << port_id)) == 0) | |
115 | continue; | |
116 | ||
117 | /* get the lcore_id for this port */ | |
118 | while (rte_lcore_is_enabled(rx_lcore_id) == 0 || | |
119 | rx_lcore_id == rte_get_master_lcore() || | |
120 | poll_rsrc->lcore_queue_conf[rx_lcore_id].n_rx_port == | |
121 | rsrc->rx_queue_per_lcore) { | |
122 | rx_lcore_id++; | |
123 | if (rx_lcore_id >= RTE_MAX_LCORE) | |
124 | rte_panic("Not enough cores\n"); | |
125 | } | |
126 | ||
127 | if (qconf != &poll_rsrc->lcore_queue_conf[rx_lcore_id]) { | |
128 | /* Assigned a new logical core in the loop above. */ | |
129 | qconf = &poll_rsrc->lcore_queue_conf[rx_lcore_id]; | |
130 | } | |
131 | ||
132 | qconf->rx_port_list[qconf->n_rx_port] = port_id; | |
133 | qconf->n_rx_port++; | |
134 | printf("Lcore %u: RX port %u\n", rx_lcore_id, port_id); | |
135 | } | |
136 | } | |
137 | ||
138 | static void | |
139 | l2fwd_poll_init_tx_buffers(struct l2fwd_resources *rsrc) | |
140 | { | |
141 | struct l2fwd_poll_resources *poll_rsrc = rsrc->poll_rsrc; | |
142 | uint16_t port_id; | |
143 | int ret; | |
144 | ||
145 | RTE_ETH_FOREACH_DEV(port_id) { | |
146 | /* Initialize TX buffers */ | |
147 | poll_rsrc->tx_buffer[port_id] = rte_zmalloc_socket("tx_buffer", | |
148 | RTE_ETH_TX_BUFFER_SIZE(MAX_PKT_BURST), 0, | |
149 | rte_eth_dev_socket_id(port_id)); | |
150 | if (poll_rsrc->tx_buffer[port_id] == NULL) | |
151 | rte_panic("Cannot allocate buffer for tx on port %u\n", | |
152 | port_id); | |
153 | ||
154 | rte_eth_tx_buffer_init(poll_rsrc->tx_buffer[port_id], | |
155 | MAX_PKT_BURST); | |
156 | ||
157 | ret = rte_eth_tx_buffer_set_err_callback( | |
158 | poll_rsrc->tx_buffer[port_id], | |
159 | rte_eth_tx_buffer_count_callback, | |
160 | &rsrc->port_stats[port_id].dropped); | |
161 | if (ret < 0) | |
162 | rte_panic("Cannot set error callback for tx buffer on port %u\n", | |
163 | port_id); | |
164 | } | |
165 | } | |
166 | ||
167 | void | |
168 | l2fwd_poll_resource_setup(struct l2fwd_resources *rsrc) | |
169 | { | |
170 | struct l2fwd_poll_resources *poll_rsrc; | |
171 | ||
172 | poll_rsrc = rte_zmalloc("l2fwd_poll_rsrc", | |
173 | sizeof(struct l2fwd_poll_resources), 0); | |
174 | if (poll_rsrc == NULL) | |
175 | rte_panic("Failed to allocate resources for l2fwd poll mode\n"); | |
176 | ||
177 | rsrc->poll_rsrc = poll_rsrc; | |
178 | l2fwd_poll_lcore_config(rsrc); | |
179 | l2fwd_poll_init_tx_buffers(rsrc); | |
180 | ||
181 | poll_rsrc->poll_main_loop = l2fwd_poll_main_loop; | |
182 | } |