11154SN/A/*
21762SN/A * Copyright (c) 2004-2005 The Regents of The University of Michigan
31154SN/A * All rights reserved.
41154SN/A *
51154SN/A * Redistribution and use in source and binary forms, with or without
61154SN/A * modification, are permitted provided that the following conditions are
71154SN/A * met: redistributions of source code must retain the above copyright
81154SN/A * notice, this list of conditions and the following disclaimer;
91154SN/A * redistributions in binary form must reproduce the above copyright
101154SN/A * notice, this list of conditions and the following disclaimer in the
111154SN/A * documentation and/or other materials provided with the distribution;
121154SN/A * neither the name of the copyright holders nor the names of its
131154SN/A * contributors may be used to endorse or promote products derived from
141154SN/A * this software without specific prior written permission.
151154SN/A *
161154SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
171154SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
181154SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
191154SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
201154SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
211154SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
221154SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
231154SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
241154SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
251154SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
261154SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665SN/A *
282665SN/A * Authors: Nathan Binkert
291154SN/A */
301154SN/A
3111263Sandreas.sandberg@arm.com#ifndef __DEV_NET_PKTFIFO_HH__
3211263Sandreas.sandberg@arm.com#define __DEV_NET_PKTFIFO_HH__
331154SN/A
341154SN/A#include <iosfwd>
351154SN/A#include <list>
361154SN/A#include <string>
371154SN/A
3812334Sgabeblack@google.com#include "base/logging.hh"
3911263Sandreas.sandberg@arm.com#include "dev/net/etherpkt.hh"
401154SN/A#include "sim/serialize.hh"
411154SN/A
421154SN/Aclass Checkpoint;
435483SN/A
445483SN/Astruct PacketFifoEntry
455483SN/A{
465483SN/A    EthPacketPtr packet;
475483SN/A    uint64_t number;
486227SN/A    unsigned slack;
495483SN/A    int priv;
505483SN/A
515483SN/A    PacketFifoEntry()
525483SN/A    {
535483SN/A        clear();
545483SN/A    }
555483SN/A
565483SN/A    PacketFifoEntry(const PacketFifoEntry &s)
575483SN/A        : packet(s.packet), number(s.number), slack(s.slack), priv(s.priv)
585483SN/A    {
595483SN/A    }
605483SN/A
615483SN/A    PacketFifoEntry(EthPacketPtr p, uint64_t n)
625483SN/A        : packet(p), number(n), slack(0), priv(-1)
635483SN/A    {
645483SN/A    }
655483SN/A
665483SN/A    void clear()
675483SN/A    {
685483SN/A        packet = NULL;
695483SN/A        number = 0;
705483SN/A        slack = 0;
715483SN/A        priv = -1;
725483SN/A    }
735483SN/A
7410905SN/A    void serialize(const std::string &base, CheckpointOut &cp) const;
7510905SN/A    void unserialize(const std::string &base, CheckpointIn &cp);
765483SN/A};
775483SN/A
781154SN/Aclass PacketFifo
791154SN/A{
802007SN/A  public:
815483SN/A
825483SN/A    typedef std::list<PacketFifoEntry> fifo_list;
832007SN/A    typedef fifo_list::iterator iterator;
8411006SN/A    typedef fifo_list::const_iterator const_iterator;
852007SN/A
861154SN/A  protected:
875483SN/A    std::list<PacketFifoEntry> fifo;
885483SN/A    uint64_t _counter;
896227SN/A    unsigned _maxsize;
906227SN/A    unsigned _size;
916227SN/A    unsigned _reserved;
921154SN/A
931154SN/A  public:
945483SN/A    explicit PacketFifo(int max)
955483SN/A        : _counter(0), _maxsize(max), _size(0), _reserved(0) {}
961154SN/A    virtual ~PacketFifo() {}
971154SN/A
986227SN/A    unsigned packets() const { return fifo.size(); }
996227SN/A    unsigned maxsize() const { return _maxsize; }
1006227SN/A    unsigned size() const { return _size; }
1016227SN/A    unsigned reserved() const { return _reserved; }
1026227SN/A    unsigned avail() const { return _maxsize - _size - _reserved; }
1031214SN/A    bool empty() const { return size() <= 0; }
1041214SN/A    bool full() const { return avail() <= 0; }
1051205SN/A
1066227SN/A    unsigned
1076227SN/A    reserve(unsigned len = 0)
1081205SN/A    {
10911294Sandreas.hansson@arm.com        assert(avail() >= len);
1101205SN/A        _reserved += len;
1111205SN/A        return _reserved;
1121205SN/A    }
1131154SN/A
1142007SN/A    iterator begin() { return fifo.begin(); }
1152007SN/A    iterator end() { return fifo.end(); }
1162007SN/A
11711006SN/A    const_iterator begin() const { return fifo.begin(); }
11811006SN/A    const_iterator end() const { return fifo.end(); }
11911006SN/A
1205483SN/A    EthPacketPtr front() { return fifo.begin()->packet; }
1212007SN/A
1222566SN/A    bool push(EthPacketPtr ptr)
1231154SN/A    {
1242007SN/A        assert(ptr->length);
1251205SN/A        assert(_reserved <= ptr->length);
1261205SN/A        if (avail() < ptr->length - _reserved)
1271154SN/A            return false;
1281154SN/A
1291154SN/A        _size += ptr->length;
1305483SN/A
1315483SN/A        PacketFifoEntry entry;
1325483SN/A        entry.packet = ptr;
1335483SN/A        entry.number = _counter++;
1345483SN/A        fifo.push_back(entry);
1351205SN/A        _reserved = 0;
1361154SN/A        return true;
1371154SN/A    }
1381154SN/A
1391154SN/A    void pop()
1401154SN/A    {
1411154SN/A        if (empty())
1421154SN/A            return;
1431154SN/A
1445483SN/A        iterator entry = fifo.begin();
1455483SN/A        _size -= entry->packet->length;
1465483SN/A        _size -= entry->slack;
1475483SN/A        entry->packet = NULL;
1481154SN/A        fifo.pop_front();
1491154SN/A    }
1501154SN/A
1511154SN/A    void clear()
1521154SN/A    {
1532007SN/A        for (iterator i = begin(); i != end(); ++i)
1545483SN/A            i->clear();
1551154SN/A        fifo.clear();
1561154SN/A        _size = 0;
1571214SN/A        _reserved = 0;
1581154SN/A    }
1591154SN/A
1602007SN/A    void remove(iterator i)
1612007SN/A    {
1622007SN/A        if (i != fifo.begin()) {
1632010SN/A            iterator prev = i;
1642010SN/A            --prev;
1652010SN/A            assert(prev != fifo.end());
1665483SN/A            prev->slack += i->packet->length;
1675483SN/A            prev->slack += i->slack;
1682007SN/A        } else {
1695483SN/A            _size -= i->packet->length;
1705483SN/A            _size -= i->slack;
1712007SN/A        }
1722007SN/A
1735483SN/A        i->clear();
1742007SN/A        fifo.erase(i);
1752007SN/A    }
1762007SN/A
1776227SN/A    bool copyout(void *dest, unsigned offset, unsigned len);
1782186SN/A
17911006SN/A    int countPacketsBefore(const_iterator i) const
1802186SN/A    {
1815483SN/A        if (i == fifo.end())
1825483SN/A            return 0;
1835483SN/A        return i->number - fifo.begin()->number;
1842186SN/A    }
1852186SN/A
18611006SN/A    int countPacketsAfter(const_iterator i) const
1872186SN/A    {
18811006SN/A        auto end = fifo.end();
1895483SN/A        if (i == end)
1905483SN/A            return 0;
1915483SN/A        return (--end)->number - i->number;
1922186SN/A    }
1932186SN/A
19411006SN/A    void check() const
1955483SN/A    {
1966227SN/A        unsigned total = 0;
19711006SN/A        for (auto i = begin(); i != end(); ++i)
1985483SN/A            total += i->packet->length + i->slack;
1995483SN/A
2005483SN/A        if (total != _size)
2015483SN/A            panic("total (%d) is not == to size (%d)\n", total, _size);
2025483SN/A    }
2032186SN/A
2041154SN/A/**
2051154SN/A * Serialization stuff
2061154SN/A */
2071154SN/A  public:
20810905SN/A    void serialize(const std::string &base, CheckpointOut &cp) const;
20910905SN/A    void unserialize(const std::string &base, CheckpointIn &cp);
2101154SN/A};
2111154SN/A
21211263Sandreas.sandberg@arm.com#endif // __DEV_NET_PKTFIFO_HH__
213