2- There is no need for a specific port for a specific processor. A port
of lwIP needs to handle the OS (if any), and some nice stuff on the
processor architecture that can help making things faster (and some
intricacies of the compiler). As long as there is a port for that core
and that OS (or
The lwIP stack will not work as a router unless you actually write the
routing code yourself. Since in your scenario the non-local address is
the device netif address, that should work. If it were some other host
in that very same network (172...) connected to the lwIP device, it
would not (unless
The recommendations are to use separate pools for rx and tx so they can
not starve each other. Since PBUF_RAM is used for tx, then rx is
expected to use PBUF_POOL. I bet you can also use separate pools but I
don't know how.
Last time I checked, PBUF_RAM allocates a single block of memory. That
is
If you decide to generate checksums on lwIP, you MUST tell the
controller not to generate them.
You must check arg and newpcb in your tcp_accept() callback, follow the
examples.
Your tcpecho source is different from what I can see on lwIP git. I
won't check further.
I won't check the rest of your
OK,
I know Modscan is a Modbus master tool, so I guess you are polling your
device, which happens to be a slave, a server, a TCP listener.
You are trying to implement ModbusTCP where the PC running Modscan (and
I guess Wireshark too) will connect (send SYN) to the lwIP device.
Second issue:
Those
Your scenario is composed of four main pieces of software (to name them
some way). lwIP will handle TCP/IP stuff but will not mess with your
controller. Your driver will. Your driver is not lwIP, it is your
responsibility. I guess you handled it to your vendor and are using
something that is
If your device does not go to the Eth Rx ISR that is because either the
controller is not interrupting anymore or the OS is not accepting the IRQ.
pbuf_alloc() does not control your chip, your driver does.
Your driver should gracefully discard the incoming frame if it can't
accept its contents
I understand your frustration but it is vendor generated, not lwIP's
fault. Say "bye, thanks" to your vendor "docs" (or the lack of them)
and dive here:
https://www.nongnu.org/lwip/2_1_x/ (or the version you're using)
The official source code tree has a directory named "apps" where
If I were to debug this, I would use UDP, you can move a pin when
sending and be sure the msg will at least get to the driver (where we
think it is lost). TCP... well...
Then, every entry to the driver should end with a safe exit and due to
DMA a later "done" interrupt where the driver frees the
Well, perhaps TI was short on examples but you can learn from the apps
section and those in the contrib tree.
> I actually didn't quite understand how to use tcp_sent() since [...]
When you open a connection (think you can be a server), you set the
environment to serve it and then setup an
Nope, I'm sorry, no further ideas on my side.
Since you can't upgrade, perhaps diffing against git commits around that
time or against git head would provide a clue on what to change.
There could be another bug report more related to your problem, I just
didn't find it but I haven't done an
mmm...
The bug I mentioned is on the rx side, I see you are losing frames on
the tx side. There should be a frame between #4206 and #4207 that is
either lost inside your device or on its way to your PC.
The same pattern repeats where you mention, there is a missing frame
between #4315 and #4316.
I
Instead of speculating on a slow receiver, I would see traffic on the
wire and check my tcp_sent() callbacks.
You stuff the TCP buffer with tcp_write() and it will eventually get
sent, you can speed things up as you are doing by calling tcp_output(),
and the stack will let you know when your
OK, I'll try to be more precise.
ST driver code wasn't properly handling receive interrupts from the
Ethernet controller. They just took the first frame in the buffer
without thinking more could have arrived since the interrupt fired.
Those frames remained there sleeping until a new one arrived,
ST driver code wasn't freeing all frames in the Ethernet controller on
ints, do you have the "working" version ? (can't tell you which one)
I particularly don't like watching screen snapshots, if you post a
capture I can try to look and let you know if I see something.
At birdseye, looks like you
I guess this is what I remember... not exactly your problem nor a
helping hand but perhaps you can start digging here:
http://savannah.nongnu.org/bugs/?48328
___
lwip-users mailing list
lwip-users@nongnu.org
mmm... the ACK number..., I think I've seen this one or two years ago,
search the list and or the patches for "one less" or something like that.
I'm not fresh on this, but I think that is the problem, the ACK to the
RST has the wrong number and causes a retransmission. I can't remember
if this is
Your msg is too long for me, I'm too lazy to read it and too dumb to
keep focus at the same time.
Your capture file is long too, but fortunately retransmissions happen
right at the beginning.
I see you are ACKing 100ms later, several frames later.
I see (at least once) that you ACK a frame and ms
You forgot to include your device address. If it is 192.168.1.x it is
fine (unless it coincides with any other device in the network...)
The error callback is called when the connection request is rejected or
lwIP gets tired of waiting for an answer. Do you see the SYN in
wireshark or equivalent
I don't think the same port will run on a preemptive and a
non-preemptive OS, even if it is the same OS.
Did you check your port ? It will surely rely on some semaphores/mutexes
for proper operation; I don't know how they will behave on a cooperative
scenario.
Anyway, your port provider should
lwIP does not care about RMII, that is between your MAC controller and
your PHY controller. Whatever happens there is your driver's business.
Do you have two MAC controllers ? Or are you trying to handle two PHYs
with one MAC ? (Why would you do that ?)
1 IP 1 MAC 2 PHY: beyond my understanding,
Your scenario ? I mean: IP addresses, masks, gateways. Sometimes wrong
configurations "just work".
Your netif setup ?
Your call setup ? How do you initiate your connection ? What does that
function return ? Are you using the RAW API ? The netconn API ? The
socket API ?
Threading rules ?
If you are using the very same driver, it could still have been buggy
and happen to pass unnoticed until something triggered it.
The fact that the data gets lost when you call lpc_low_level_output()
means that it gets lost after it left lwIP. The only way I can see lwIP
running again (and
Yes, I remember analyzing your capture file about 15 days ago and
pointing to that possibility. Glad it was a hit.
"lpc_low_level_output" is not something related to lwIP, it is your
vendor driver code. Ask your vendor.
Want to find it yourself ? Great! Then grab a debugger and place
breakpoints
Unfortunately I only know the RAW API and can't help you further. Did
you check the basics ?:
- core lwIP runs in a single thread. If your Ethernet is handled in
another thread, you don't call any lwIP functions from there, except for
the pbuf allocation/free functions; you queue your packets and
There is no printf in lwIP, that is your own/vendor mechanism, and this
is where you should start checking for the reason triggering the msg.
Ask your vendor if it is not yours.
AFAIK your recv callback is incorrect, if your tcp_close() fails, you
retry later, you don't call tcp_abort() (I guess
lwIP202 v1.1 What is that ? That doesn't look like lwIP versioning scheme.
Where do you get that "message" about being unable to alloc pbuf in
recv_handler" ? There is no recv_handler in lwIP. That looks like a
driver that runs out of memory, as if you are not releasing your alloced
pbufs
Who pings who ? Who is who ?
Assuming both your MTUs are 1500 bytes, greater than 1472 means the
payload will not fit in a single IP datagram over a single Ethernet
frame. (20IP + 8ICMP + 1472payload = 1500)
Your sender will have to fragment and your receiver will have to
reassemble. Perhaps one
What I see is that the slave seems to respond but its response is not in
the capture.
This means that the frame is not getting there, it is getting lost
somewhere in between.
If the slave is an lwIP device, then it is quite likely your driver+port
are losing frames.
Vague questions usually get
If you post a capture file, some people here might want to take a look
at it and diagnose the reason for the retransmissions. Otherwise, we can
not infer much.
Did you closely follow the UPGRADE guide in the 2.x documentation ?
Perhaps your Modbus provider can be a bit more helpful with you ?
Well, this is perhaps pretty obvious, maybe, but did you happen to try
to lookup what those "errors" are ? Are they errors or _warnings_ ?
Do you known the engine in both compilers is different ?
Does your port use compiler extensions ? (You need to change those since
the engines are different...)
Thank you Simon,
Then, if I understand correctly, this is expected behaviour (lwIP is
indeed routing here) and then either both default gateways get to route
both netif addresses or the connection has to be dropped and started
again (in order to be established from the other address).
Since the
So, so far:
When switching default interface with connections open, traffic stops
going out on the former default interface (A) but starts going out on
the new one (B), but using the former address (addrA):
Default interface is A, traffic is going from addrA to addrX outside the
local network,
You have a problem in your port.
If you use NO_SYS=0, then it is "YES SYS", I mean, you need a SYS, an
OS, someone that provides all the system functions, and that includes
timing: sys_now()
http://www.nongnu.org/lwip/2_0_x/group__sys__layer.html
___
lwIP does not route. That is, it does not know how to distribute traffic
among interfaces beyond some simple rules.
I don't know if you can switch default interfaces with sockets
(connections) open... do you just switch or you bring it down and then
up again ?
Can you capture IP traffic on at
You have to find who is eating your pbufs and not releasing them. Are
you using the same pool for input and output ? (I'm lazy enough to skip
scrolling all your lwipopts file)
At first sight, you seem to have a problem in your driver and/or you are
not honoring threading rules.
Tobias, lwIP can handle as many connections as your RAM allows; I guess
you are using the RAW API, but I fail to guess if lwIP is your server or
your client. My best bet is that it is your server.
Did you check your accept callback against the echo or http server in
the examples ? (apps, contrib
There is no modbusTCP on lwIP. Go to the ones who wrote that and ask
them for help.
1.3.2 is a version perhaps older than the STM32 itself, you should get a
more up to date framework for your endeavours.
Before you do that, try to know at least if TCP is connecting. ModbusTCP
is a simple
There is 6LoBLE, perhaps you would do with that.
The Bluetooth world is filled with protocols and profiles but most of
them protocols belong to BT and not to BLE, so you need to check for
something BLE specific.
Whether it is supported on the phone or not... I don't know.
Laurent used to participate on this list. I collaborated with a (very)
small part of the code, post your suggested/required changes on github
and we can follow up from there.
___
lwip-users mailing list
lwip-users@nongnu.org
I fail to see where the problem is.
lwIP does not require an OS, as long as you can compile C code you are fine.
A port is basically what you described, you write your driver, you read
this:
http://www.nongnu.org/lwip/2_1_x/group__sys__layer.html
you modify architecture dependent files, and you
... and did you think on capturing traffic with (for example) Wireshark,
or inspecting (using breakpoints) if the functions are called ? There is
no autostop code in there (at least not in lwIP, but that is surely
vendor code) so you need to check your system if you want to solve your
problem.
A TCP server might handle many incoming connection requests, each one of
them will fire the accept callback.
That callback is responsible for acquiring any memory that it would need
for the application, and then will register callbacks for that instance
of the application. There is one instance
If I guessed correctly, you seem to be talking about the TCP reopen
issue, but your scenario is not clear to me.
You have an lwIP client connecting to a server
Someone closes the connection, or it is lost somehow.
The client retries the connection, does it succeed ? Apparently it does.
If
Perhaps if you could think your actions in terms of OSI layers it would
be easier to understand.
You say "before IP" but you draw "after IP" (well, sort of...), so I
don't really get what you need.
What is it that you are trying to accomplish, do you want to encapsulate
TCP/IP into an "ESP"
OK, now I see.
Well, you _should_ (read _must_) check your port and your driver.
Perhaps your simplest application can do, but you should try one of the
apps in the app subtree or in the contrib tree. Those have been tested
by many users.
I can't help you further, I'm nil on anything other than
I may be wrong since I know nothing on sockets on lwIP, but I think I
remember reading Simon saying you can't have two threads using the same
socket. (or at least that is what I think I see on how the post is
formatted)
What I do know:
Following your capture file is hard; you provide a whole net
You can just check the code yourself, but no, sys_check_timeouts()
should return asap since it is meant to be called as frequently as
possible (afap?) and living in the main loop of many systems.
However, from time to time, something needs to be done, like for example
resending a TCP segment, so
Well, the RAW API is tricky and there is no such thing as half-duplex or
unidirectional communications in TCP, so I'd need to see your code.
You should (read: must) be calling sys_check_timeouts() frequently
enough for TCP to handle its internal timers; and since your current
problem is on the
Completely missed the "20 second" part.
You don't remember wrong, and you know it ;^)
___
lwip-users mailing list
lwip-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users
What you see is the Naggle algorithm.
It is the old trade off, delay or throughput. If your application
requires throughput, you want it. If you do need short delay, it can
usually be minimized by some configuration function/option.
The RAW API lets you tweak mostly at will, but the interface is
OK...
You seem to need a tutorship or a crash course in networking followed by
a study of lwIP.
You need to first get a grasp of the layer model as an abstraction: if
you set things right, that is, if you assign the proper IP address and
open the proper TCP port, you will get a callback with a
You have two interfaces, one in 10.something and another in 192.168.1.
You can communicate with hosts in either network but you can't be the
one letting the WiFi access "the board" nor "the board" access the WiFi,
that is routing, and lwIP does not route.
Somehow you have built a "gateway" in the
Your modem will go into PPP mode once you instruct it to do so. Read
your manuals.
IP-forwarding = Routing
If host-A and lwip-A are in network A, and host-B and lwIP-B are in
network B, then host-A and lwiP-A can talk, and host-B and lwIP-B can
talk, but A and B can't talk to each other.
AFAIK there is no built-in AT send/expect engine, but lwIP does support
PPP over serial interfaces. As long as you manage to setup your whatever
in PPP mode, it will work.
You can have as many interfaces as your memory and drivers can handle,
but don't expect lwIP to route between them (not
So you have a perfectly working Ethernet host and you want WiFi. So you
plan to use another lwIP host as a module.
What I would do is to delegate the netif to the module, so basically the
netif running in the host will take care of delivering via the UART and
receiving from the UART.
However, you
I don't know what you are doing 'cause you don't say, but if you are
using NO_SYS=1 there must be a main loop calling sys_check_timeouts() as
frequently as possible, it takes care of all timeouts.
You should check if your frames carrying your TCP SYNs are being
delivered or get lost in the
Well, besides the fact that one thing is TCP, layer-4, with its Maximum
_Segment_ Size and another is Ethernet, layer-2, with the number of
bytes in a frame, which is what you are seeing in wireshark;
You are on the right track. There are a number of algorithms to
gracefully handle the life of a
Modbus/TCP is Modbus over TCP port 502, with a simple header (MBAP).
A Modbus master is quite simple, and unless you have to support all
intricacies of different brand proprietary stuff, it ends up being just
a couple of functions.
The only tricky part is the word alignment, since registers are
UDP datagrams are carried by Ethernet frames. It is not lwIP but your
driver who allocates memory to hold those frames before handling them to
lwIP, which in turn will deliver to your application. The only way to
stop allocation is there.
Someone could also send pings of death, repeated SYNs...
If
Hi Dirk,
Well, I'm not good with makefiles but I guess I can transform
example_app into what I need. And I can always write a bash script.
Just as long as you keep the tapif and tapif_select(), I can keep going
with minimum effort.
Regards
___
Hi,
I started long ago using 'minimal' for development and teaching.
I need a tap interface and the stack compiled to run as NO_SYS=1, as my
work is on bare metal stuff.
Yes, I use the lib. I guess there is no _need_ for it and I can just
compile lwIP and link to it as in a regular embedded
You got things a bit confused.
lwIP is not a computer OS nor a device, is a TCP/IP stack. It provides
sevices for layer-3+. If you donĀ“t need what rests over IP nor IP
itself, then you don't need lwIP.
Yes, you can use lwIP's "infrastructure" and have layer-2 protocols
coexist with the stack, you
Regarding your image, it didn't get through my mail, "An HTML attachment
was scrubbed..." and I'm too lazy to go dig it. Anyway... it belongs
here now:
http://lists.nongnu.org/archive/html/lwip-users/2018-06/msg00050.html
So you still want two hosts.
And as far as I can see, you need a bridge
(crossposted from the developers' list)
So, summing up, you (the OP) want to have two IP addresses on one
Ethernet (physical) port. This has been asked several times on the list,
under several different subjects, and is perhaps hard to find. I suggest
you do some searches on the list.
Perhaps we
I don't know what you mean by "lwIP tun ARP table", lwIP is oblivious to
tun/tap.
I guess you have an lwIP port running in a Linux machine, "connected" to
a tun/tap interface.
If you want to see the lwIP ARP table you go one place (e.g:
src/core/ipv4/etharp.c and discover the existence of static
When you use the tun/tap interface in Linux, you have a tun/tap
interface in Linux. Nothing from lwIPland, just Linuxland.
As per my (sort of) expertise, you get what looks like another Ethernet
card attached to a network. There is your plain trusty old linux machine
on one side, there is your
Yes, "ethernetif" is sort of the generic name used in the skeleton,
internals for a netif belong to the developer (that's the reason for my
'driveroutputfunction' comment on that line).
Well, if I'm not missing something important, it looks like you have a
problem on the driver/wire side. Try to
OK, so it seems you are correctly calling lwIP in the loop, and your
networking parameters look good.
However, I failed to ask how do you setup your netif. You don't tell.
You should do something like this before actually calling tcp_connect():
IP4_ADDR(, 192,168,100,1);
IP4_ADDR(,
That may or may not work depending on what your _magic function_
"delay_ms" does. If it is blocking, you are busted.
A main loop is a main loop, you need to rx and you need to check
timeouts. Your accept callback will be called after the SYN is SYNACKed
and the SYNACK is ACKed back. For that, you
Well, that is usually a "don't!". However, if you actually do know what
you are doing and properly handle the blocking, I guess you might get
away with that. I personally don't know how, wait for one of the top
guys like Simon.
However, I find it easier to run everything under the same context.
No need to bind(), you are a client, you connect().
What is the value returned by tcp_connect() ? It should be ERR_OK
What do you do after that ? Do you properly call sys_check_timeouts() on
the main loop or you just sit waiting things to magically happen ?
TCP is a state machine, you just
Looks like you've got yourself a lot to read before you can actually do
some networking with your hardware. Good luck.
I suggest you start here:
https://en.wikipedia.org/wiki/Point-to-Point_Protocol
Then, small pieces of advice:
- your device is a host in a network that does not belong to you. You
Please stay in one thread.
What is that you cannot ping ? What are you trying to do ?
Where are "you" ? What is your scenario ? (device, computer, where ?)
I seem to gather that your lwIP device is behind a GSM module, in
Istambul, Turkey, connecting to some operator, Turkcell/Trabzon, that
gives
I guess you refer to "url_decode".
Here's the one I used in my web server:
#define TOUPPER(c) (((c>='a')&&(c<='z'))? (c-('a'-'A')):(c))
#define HEXNUMBER(c) c)<'0')||((c)>'F')||(((c)>'9')&&((c)<'A')))? 0
:((c)>='
A')?((c)-('0'+7)):((c)-'0'))
void cgi_urldecode(char *text)
{
char *ptr = text;
lwIP is a TCP/IP stack
802.1X is an authentication mechanism for LAN or WLAN.
AFAIK, all that would be handled at the interface level, you only pass
IP related stuff to the stack
What is exactly your need ?
AFAIK, all WiFi authentication related stuff in the "small" embedded
world is handled by a
BTW, there is an http_client in the apps subtree...
Perhaps your problem is solved ? Regards
___
lwip-users mailing list
lwip-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users
Concerns for just GETting: well, the server might return anything other
than 200 due to a number of reasons. Besides what Ajay himself mentions,
if I'm correct, 'host' is not an HTTP/1.0 header, and so behaviour would
be implementation dependent.
If you can manage the server you can make sure you
You can do whatever you want.
The question is probably not what can you do but what do you have
available to obtain what you need with lesser effort.
There are FTP clients around, I've collaborated in one of them using the
RAW API, search the list.
FTP is sometimes tricky and can give you some
Usually the driver asks for PBUF_POOL, while TCP takes from PBUF_RAM.
Whatever you free in rx callbacks shouldn't mess with tx since they use
different areas.
PBUF_POOL is allocated as memp_malloc(MEMP_PBUF_POOL), which takes
memory from a pool of pbufs defined in the MEMP_ are of lwipopts
First things first.
Maybe we've already talked about this, but I don't remember everyone in
the list...
Are you calling all lwIP RAW API functions from the same context ?
Either main loop or interrupts but only one of them and always the same one.
Did you run a known-good application long enough
Check this answer:
http://lists.nongnu.org/archive/html/lwip-users/2016-08/msg00093.html
I guess your option is to play with the backlog
___
lwip-users mailing list
lwip-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users
All Ethernet frames must be at least 64 bytes long, in order to
guarantee for a collision to be detected on the longest possible
extension (4-repeaters joining 5 10base5 sections, iirc) where colliding
stations are at opposite ends.
That is total Ethernet frame length including preamble, actual
Hi Johan,
similar issues have been asked in the list, and in some responses there
have been pointers to great texts where it is explained that due to
parallel paths and retransmissions and etcetera, sockets must remain
open for some time after the user wants them closed.
This is normal behaviour
Take a look at frame #22, my Wireshark says "previous segment info not
captured" and its SEQ is 216.
Previous device frame in capture is #19 with SEQ 178 and len 21, which
is consistent with the PC ACKing 199 in frames #20/21.
There is a missing frame with SEQ 199 and len 17 that was supposedly
Daniel,
can you please attach or post a link to a capture file where we can see
what's going on ?
___
lwip-users mailing list
lwip-users@nongnu.org
https://lists.nongnu.org/mailman/listinfo/lwip-users
My best guess for a Sunday is that you are missing frames while you are
busy writing your flash.
Your Ethernet chip can only hold a limited number of frames and if you
don't empty it frequently enough, or your driver runs out of pbufs to
store incoming frames, you'll lose them.
Try to enable
I've been lurking in listen-only mode since I don't know the netconn API.
The PC is sending as fast as it can, but the device is synchronized to
the storage speed, so incoming data needs to be buffered and eventually
slowed down, and that is what TCP tries to do.
However, your packet loss is a
Summing up:
Yes, you can avoid writing apps, but you have to host a web page
somewhere. Either a CGI on the server or a javascript on the browser
will connect to the database (or the broker if you just need realtime
and no history, that is: no persistence)
No, some of these services are free for
My personal opinion follows:
Do you absolutely need HTTP ?
As long as we don't have IPv6 (and fixed addresses), we have to go DDNS
and port forwarding. Yes, this requires an end user holding a PhD or at
least the techie ones. So... the whole purpose of "the cloud" probably
started with this, and
There is a port in the contrib tree, you can use it yourself if you will.
I mainly use it as a prototype area, it is quite easier (for me) to
debug applications (and to teach how to use lwIP RAW API) running them
on a computer. I can also easily trace "Ethernet" frames with Wireshark
without all
The "ping" does not call the application, the GET does.
I would argument your memory is getting freed slower than it is alloced,
but there have been numerous bug fixes and way so many enhancements in
the web server since 1.4.1 that you should really try git head.
Strange things can happen if
> BTW: curl wants "HTTP/1.0 100 Continue\r\n\r\n" in the reply.
> "HTTP/1.0 100 Continue\r\n\" leads to confusion.
I guess you mean curl wants "HTTP/1.1 100 Continue\r\n\r\n"; and that is
because 100 Continue belongs to the 1.1 spec, there is no such thing on
the HTTP specification 1.0
I don't think I follow you completely.
An HTTP server, like the one in lwIP, will let you build your user
interface. You can send data to the server and you can get data from the
server. The server can also be instructed to run some code of your own,
a CGI, when some URLs are requested.
Hi,
you have three things to worry about:
- the port
- the netif driver
- the initialization sequence
For the initialization sequence, afaik the right function to call in
1.4.1+ (for NO_SYS=0) is tcpip_init(), not just tcp_init().
Well, I wrote a driver some years ago, and did port to generic Cortex-M
using CMSIS.
I wrote my driver as a generic piece of firmware and did all my tests
there. All the stack stuff is responsibility of the stack maintainers
(and they do quite a good job), so my responsibility is that my driver
Besides the advice given by Simon, have you even tried the obvious and
basics of networking ?
The way you phrase makes me think you are not comfortable with the
secret arts of networking, so...
If your devices are on different subnets, they are in different
networks. Subnet or no subnet, when
You should compare what you actually do against what you should do.
Have you actually checked the echo server code, for example ?
You must call tcp_accepted(pcbreturnedwhencallingtcp_new) inside your
tcp_accept callback.
( and you have to check for the return value of tcp_listen(), it might
I guess this is quite probably off-topic, feel free to contact me by pm
if you want to chat on this.
My bet is that you have a hw/driver issue, I initially thought of an
auto-negotiation issue but since "sometimes" or "under certain
conditions" it works, I think you forgot to setup some bit in
How is your main loop ? Are you calling sys_check_timeouts() frequently
enough ?
Have you tried a small, easily debuggable app like echo or netio before
jumping into httpd ?
___
lwip-users mailing list
lwip-users@nongnu.org
1 - 100 of 533 matches
Mail list logo