Commit 54e8c2b9 authored by benjie's avatar benjie

smp merge first step: changed elements that keep counters to use u_atomic32_t instead

parent 683511a6
......@@ -8,9 +8,11 @@
/* Define to 1 since we have Strings. */
#define HAVE_STRING 1
/* EXPORT_ELEMENT, ELEMENT_REQUIRES and ELEMENT_PROVIDES are noops. */
/* EXPORT_ELEMENT, ELEMENT_REQUIRES, ELEMENT_MT_SAFE,
* and ELEMENT_PROVIDES are noops. */
#define ELEMENT_REQUIRES(x)
#define ELEMENT_PROVIDES(x)
#define ELEMENT_MT_SAFE(x)
#define EXPORT_ELEMENT(x)
/* Define if <new.h> exists and works. */
......@@ -73,6 +75,10 @@
/* Define if you have -ldl. */
#undef HAVE_LIBDL
/* Define if click multithread support should be off */
#undef __MTCLICK__
#undef __CLICK_NCPUS__
/* Define if you want to use the stride scheduler. */
#undef HAVE_STRIDE_SCHED
#ifndef HAVE_STRIDE_SCHED
......
......@@ -146,6 +146,24 @@ if test $linuxdir != NONE -a $linuxdir != no -a $enable_linuxmodule = yes; then
fi
AC_SUBST(linuxdir)
dnl
dnl build with multithread support?
dnl
AC_ARG_WITH(mt,
[ --with-mt[=MAX_THREADS] compile with multithread support (max number threads = MAX_THREADS [4])],
[mtnt=$withval; if test -z "$withval" -o "$withval" = yes; then mtnt=4; fi; mtsupport=YES],
mtsupport=NO)
if test $mtsupport = YES; then
AC_DEFINE_UNQUOTED(__CLICK_NCPUS__, $mtnt)
AC_DEFINE_UNQUOTED(__MTCLICK__, 1)
saveflags="$CPPFLAGS"
CPPFLAGS="$saveflags -D__MTCLICK__"
else
AC_DEFINE_UNQUOTED(__CLICK_NCPUS__, 1)
fi
AC_CACHE_CHECK(whether we are compiling for Linux, ac_cv_under_linux,
AC_TRY_RUN([int main(int c, char **v) {
#ifdef __linux__
......
......@@ -40,9 +40,10 @@ const char *CheckICMPHeader::reason_texts[NREASONS] = {
};
CheckICMPHeader::CheckICMPHeader()
: Element(1, 1), _drops(0), _reason_drops(0)
: Element(1, 1), _reason_drops(0)
{
MOD_INC_USE_COUNT;
_drops = 0;
}
CheckICMPHeader::~CheckICMPHeader()
......@@ -72,11 +73,12 @@ CheckICMPHeader::configure(const Vector<String> &conf, ErrorHandler *errh)
_verbose = verbose;
if (details)
_reason_drops = new int[NREASONS];
_reason_drops = new u_atomic32_t[NREASONS];
return 0;
}
Packet *
CheckICMPHeader::drop(Reason reason, Packet *p)
{
......
......@@ -46,7 +46,7 @@ subdivided by error. Only available if the DETAILS keyword argument was true.
=a CheckIPHeader, CheckUDPHeader, MarkIPHeader */
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
class CheckICMPHeader : public Element { public:
......@@ -66,8 +66,8 @@ class CheckICMPHeader : public Element { public:
private:
bool _verbose : 1;
int _drops;
int *_reason_drops;
u_atomic32_t _drops;
u_atomic32_t *_reason_drops;
enum Reason {
NOT_ICMP,
......
......@@ -259,3 +259,5 @@ ICMPError::simple_action(Packet *p)
}
EXPORT_ELEMENT(ICMPError)
ELEMENT_MT_SAFE(ICMPError)
......@@ -82,3 +82,4 @@ ICMPPingResponder::simple_action(Packet *p_in)
}
EXPORT_ELEMENT(ICMPPingResponder)
ELEMENT_MT_SAFE(ICMPPingResponder)
......@@ -105,3 +105,4 @@ ICMPSendPings::run_scheduled()
}
EXPORT_ELEMENT(ICMPSendPings)
......@@ -41,11 +41,12 @@ const char *CheckIPHeader::reason_texts[NREASONS] = {
};
CheckIPHeader::CheckIPHeader()
: _bad_src(0), _drops(0), _reason_drops(0)
: _bad_src(0), _reason_drops(0)
{
MOD_INC_USE_COUNT;
add_input();
add_output();
_drops = 0;
}
CheckIPHeader::~CheckIPHeader()
......@@ -93,7 +94,7 @@ CheckIPHeader::configure(const Vector<String> &conf, ErrorHandler *errh)
_verbose = verbose;
if (details)
_reason_drops = new int[NREASONS];
_reason_drops = new u_atomic32_t[NREASONS];
#ifdef __KERNEL__
// check alignment
......
......@@ -58,7 +58,7 @@ subdivided by error. Only available if the DETAILS keyword argument was true.
=a CheckIPHeader2, MarkIPHeader, SetIPChecksum, StripIPHeader */
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
class CheckIPHeader : public Element { public:
......@@ -84,8 +84,8 @@ class CheckIPHeader : public Element { public:
bool _aligned : 1;
#endif
bool _verbose : 1;
int _drops;
int *_reason_drops;
u_atomic32_t _drops;
u_atomic32_t *_reason_drops;
enum Reason {
MINISCULE_PACKET,
......
......@@ -76,7 +76,7 @@ CheckIPHeader2::configure(const Vector<String> &conf, ErrorHandler *errh)
_verbose = verbose;
if (details)
_reason_drops = new int[NREASONS];
_reason_drops = new u_atomic32_t[NREASONS];
return 0;
}
......
......@@ -27,11 +27,10 @@
#include <click/glue.hh>
DecIPTTL::DecIPTTL()
: _drops(0)
: Element(1, 1)
{
MOD_INC_USE_COUNT;
add_input();
add_output();
_drops = 0;
}
DecIPTTL::~DecIPTTL()
......@@ -105,3 +104,5 @@ DecIPTTL::add_handlers()
}
EXPORT_ELEMENT(DecIPTTL)
ELEMENT_MT_SAFE(DecIPTTL)
......@@ -27,13 +27,10 @@
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
class DecIPTTL : public Element {
class DecIPTTL : public Element { public:
int _drops;
public:
DecIPTTL();
~DecIPTTL();
......@@ -41,7 +38,7 @@ class DecIPTTL : public Element {
const char *processing() const { return "a/ah"; }
void notify_noutputs(int);
int drops() { return _drops; }
u_int32_t drops() { return _drops; }
DecIPTTL *clone() const;
void add_handlers();
......@@ -49,6 +46,10 @@ class DecIPTTL : public Element {
Packet *simple_action(Packet *);
void drop_it(Packet *);
private:
u_atomic32_t _drops;
};
#endif
......@@ -66,9 +66,11 @@ FixIPSrc::fix_it(Packet *p_in)
WritablePacket *p = p_in->uniqueify();
click_ip *ip = p->ip_header();
SET_FIX_IP_SRC_ANNO(p, 0);
#if 0
click_chatter("FixIPSrc changed %x to %x",
ip->ip_src.s_addr,
_my_ip.s_addr);
#endif
ip->ip_src = _my_ip;
int hlen = ip->ip_hl << 2;
ip->ip_sum = 0;
......@@ -86,3 +88,5 @@ FixIPSrc::simple_action(Packet *p)
}
EXPORT_ELEMENT(FixIPSrc)
ELEMENT_MT_SAFE(FixIPSrc)
......@@ -55,3 +55,5 @@ GetIPAddress::simple_action(Packet *p)
}
EXPORT_ELEMENT(GetIPAddress)
ELEMENT_MT_SAFE(GetIPAddress)
......@@ -57,3 +57,5 @@ IPClassifier::configure(const Vector<String> &conf, ErrorHandler *errh)
ELEMENT_REQUIRES(Classifier)
EXPORT_ELEMENT(IPClassifier)
ELEMENT_MT_SAFE(IPClassifier)
......@@ -90,7 +90,7 @@ IPEncap::simple_action(Packet *p_in)
ip->ip_v = 4;
ip->ip_hl = sizeof(click_ip) >> 2;
ip->ip_len = htons(p->length());
ip->ip_id = htons(_id++);
ip->ip_id = htons(_id.read_and_add(1));
ip->ip_p = _ip_p;
ip->ip_src = _ip_src;
ip->ip_dst = _ip_dst;
......@@ -116,3 +116,5 @@ IPEncap::simple_action(Packet *p_in)
}
EXPORT_ELEMENT(IPEncap)
ELEMENT_MT_SAFE(IPEncap)
......@@ -28,6 +28,7 @@
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
#include <click/click_ip.h>
class IPEncap : public Element {
......@@ -39,7 +40,7 @@ class IPEncap : public Element {
bool _aligned;
#endif
short _id;
u_atomic32_t _id;
public:
......
......@@ -29,11 +29,11 @@
#include <click/glue.hh>
IPFragmenter::IPFragmenter()
: _drops(0)
{
MOD_INC_USE_COUNT;
_fragments = 0;
_mtu = 0;
_drops = 0;
add_input();
add_output();
}
......@@ -206,3 +206,5 @@ IPFragmenter::add_handlers()
EXPORT_ELEMENT(IPFragmenter)
ELEMENT_MT_SAFE(IPFragmenter)
......@@ -29,12 +29,13 @@
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
class IPFragmenter : public Element {
unsigned _mtu;
int _drops;
int _fragments;
u_atomic32_t _drops;
u_atomic32_t _fragments;
void fragment(Packet *);
int optcopy(const click_ip *ip1, click_ip *ip2);
......@@ -49,8 +50,8 @@ class IPFragmenter : public Element {
void notify_noutputs(int);
int configure(const Vector<String> &, ErrorHandler *);
int drops() const { return _drops; }
int fragments() const { return _fragments; }
u_int32_t drops() const { return _drops; }
u_int32_t fragments() const { return _fragments; }
IPFragmenter *clone() const;
void add_handlers();
......
......@@ -227,3 +227,5 @@ IPGWOptions::add_handlers()
}
EXPORT_ELEMENT(IPGWOptions)
ELEMENT_MT_SAFE(IPGWOptions)
......@@ -31,10 +31,11 @@
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
class IPGWOptions : public Element {
int _drops;
u_atomic32_t _drops;
struct in_addr _my_ip;
unsigned *_other_ips;
int _n_other_ips;
......@@ -51,7 +52,7 @@ class IPGWOptions : public Element {
IPGWOptions *clone() const;
void add_handlers();
int drops() { return(_drops); }
u_int32_t drops() const { return _drops; }
Packet *handle_options(Packet *);
Packet *simple_action(Packet *);
......
......@@ -32,9 +32,10 @@
#include "elements/standard/alignmentinfo.hh"
IPInputCombo::IPInputCombo()
: _drops(0), _bad_src(0)
: _bad_src(0)
{
MOD_INC_USE_COUNT;
_drops = 0;
add_input();
add_output();
}
......@@ -189,3 +190,5 @@ IPInputCombo::add_handlers()
}
EXPORT_ELEMENT(IPInputCombo)
ELEMENT_MT_SAFE(IPInputCombo)
......@@ -23,10 +23,11 @@
#include <click/element.hh>
#include <click/glue.hh>
#include <click/atomic.hh>
class IPInputCombo : public Element {
int _drops;
u_atomic32_t _drops;
int _color;
int _n_bad_src;
......@@ -43,7 +44,7 @@ class IPInputCombo : public Element {
const char *class_name() const { return "IPInputCombo"; }
const char *processing() const { return AGNOSTIC; }
int drops() const { return _drops; }
u_int32_t drops() const { return _drops; }
IPInputCombo *clone() const;
void add_handlers();
int configure(const Vector<String> &, ErrorHandler *);
......
......@@ -60,3 +60,5 @@ IPMirror::simple_action(Packet *p_in)
}
EXPORT_ELEMENT(IPMirror)
ELEMENT_MT_SAFE(IPMirror)
......@@ -209,3 +209,5 @@ IPOutputCombo::push(int, Packet *p_in)
}
EXPORT_ELEMENT(IPOutputCombo)
ELEMENT_MT_SAFE(IPOutputCombo)
......@@ -29,7 +29,7 @@
#include <click/straccum.hh>
#include <click/error.hh>
#include <click/glue.hh>
#include <click/mplock.hh>
#include <click/sync.hh>
#include <click/llrpc.h>
IPRateMonitor::IPRateMonitor()
......
......@@ -366,11 +366,17 @@ IPRw::Pattern::create_mapping(int ip_p, const IPFlowID &in,
int fport, int rport,
Mapping *fmap, Mapping *rmap)
{
static unsigned _printed = 0;
unsigned short new_sport = 0;
if (_sportl) {
new_sport = find_sport();
if (!new_sport)
if (!new_sport) {
if (!_printed) {
click_chatter("IPRw ran out of ports");
_printed = 1;
}
return false;
}
}
IPFlowID out(in);
......
/*
* lookupiproutemp.{cc,hh} -- element looks up next-hop address in static
* routing table, has processor local cache in SMP mode.
* Robert Morris
*
* Copyright (c) 1999-2000 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Further elaboration of this license, including a DISCLAIMER OF ANY
* WARRANTY, EXPRESS OR IMPLIED, is provided in the LICENSE file, which is
* also accessible at http://www.pdos.lcs.mit.edu/click/license.html
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <click/config.h>
#include <click/package.hh>
#include "lookupiproutemp.hh"
#include <click/ipaddress.hh>
#include <click/confparse.hh>
#include <click/error.hh>
#include <click/glue.hh>
LookupIPRouteMP::LookupIPRouteMP()
{
MOD_INC_USE_COUNT;
add_input();
}
LookupIPRouteMP::~LookupIPRouteMP()
{
MOD_DEC_USE_COUNT;
}
LookupIPRouteMP *
LookupIPRouteMP::clone() const
{
return new LookupIPRouteMP;
}
int
LookupIPRouteMP::configure(const Vector<String> &conf, ErrorHandler *errh)
{
int maxout = -1;
_t.clear();
int before = errh->nerrors();
for (int i = 0; i < conf.size(); i++) {
unsigned int dst, mask, gw;
int output_num;
bool ok = false;
Vector<String> words;
cp_spacevec(conf[i], words);
if ((words.size() == 2 || words.size() == 3)
&& cp_ip_prefix(words[0], (unsigned char *)&dst, (unsigned char *)&mask, true, this) // allow base IP addresses
&& cp_integer(words.back(), &output_num)) {
if (words.size() == 3)
ok = cp_ip_address(words[1], (unsigned char *)&gw, this);
else
ok = true;
}
if (ok && output_num >= 0) {
_t.add(dst, mask, gw, output_num);
if (output_num > maxout)
maxout = output_num;
} else
errh->error("argument %d should be `DADDR/MASK [GATEWAY] OUTPUT'", i+1);
}
if (errh->nerrors() != before)
return -1;
if (maxout < 0)
errh->warning("no routes");
set_noutputs(maxout + 1);
return 0;
}
int
LookupIPRouteMP::initialize(ErrorHandler *)
{
click_chatter("LookupIPRouteMP alignment: %p, %p",
&(_cache[0]._last_addr_1), &(_cache[1]._last_addr_1));
for (int i=0; i<_cache_buckets; i++) {
_cache[i]._last_addr_1 = IPAddress();
_cache[i]._last_addr_2 = IPAddress();
}
return 0;
}
#ifdef __KERNEL__
extern "C" {
#include <linux/sched.h>
}
#endif
void
LookupIPRouteMP::push(int, Packet *p)
{
IPAddress a = p->dst_ip_anno();
unsigned gw = 0;
int ifi = -1;
#ifdef __KERNEL__
int bucket = current->processor % _cache_buckets;
#else
int bucket = 0;
#endif
if (a) {
if (a == _cache[bucket]._last_addr_1) {
if (_cache[bucket]._last_gw_1)
p->set_dst_ip_anno(_cache[bucket]._last_gw_1);
output(_cache[bucket]._last_output_1).push(p);
return;
}
else if (a == _cache[bucket]._last_addr_2) {
if (_cache[bucket]._last_gw_2)
p->set_dst_ip_anno(_cache[bucket]._last_gw_2);
output(_cache[bucket]._last_output_2).push(p);
return;
}
}
if (_t.lookup(a.addr(), gw, ifi) == true) {
_cache[bucket]._last_addr_2 = _cache[bucket]._last_addr_1;
_cache[bucket]._last_gw_2 = _cache[bucket]._last_gw_1;
_cache[bucket]._last_output_2 = _cache[bucket]._last_output_1;
_cache[bucket]._last_addr_1 = a;
_cache[bucket]._last_gw_1 = gw;
_cache[bucket]._last_output_1 = ifi;
if (gw != 0)
p->set_dst_ip_anno(IPAddress(gw));
output(ifi).push(p);
} else {
click_chatter("LookupIPRouteMP: no gw for %x", a.addr());
p->kill();
}
}
EXPORT_ELEMENT(LookupIPRouteMP)
#ifndef LOOKUPIPROUTEMP_HH
#define LOOKUPIPROUTEMP_HH
/*
* =c
* LookupIPRouteMP(DST1/MASK1 [GW1] OUT1, DST2/MASK2 [GW2] OUT2, ...)
* =s
* simple static IP routing table
* V<classification>
* =d
* Interfaces are exactly the same as LookupIPRoute. The only difference is
* when operating in SMP mode, each processor has a processor local cache,
* hence the element is MT SAFE.
*
* =a LookupIPRoute
*/
#include <click/element.hh>
#include <click/iptable.hh>
class LookupIPRouteMP : public Element {
#ifdef __KERNEL__
static const int _cache_buckets = NR_CPUS;
#else
static const int _cache_buckets = 1;
#endif
// XXX a bit annoying that we don't get better alignment =(
int _pad[2];
struct {
IPAddress _last_addr_1;
IPAddress _last_gw_1;
int _last_output_1;
IPAddress _last_addr_2;
IPAddress _last_gw_2;
int _last_output_2;
int pad[2];
} _cache[_cache_buckets];
IPTable _t;
public:
LookupIPRouteMP();
~LookupIPRouteMP();
const char *class_name() const { return "LookupIPRouteMP"; }
const char *processing() const { return AGNOSTIC; }
LookupIPRouteMP *clone() const;
int configure(const Vector<String> &, ErrorHandler *);
int initialize(ErrorHandler *);
void push(int port, Packet *p);
};
#endif
......@@ -62,3 +62,5 @@ MarkIPHeader::simple_action(Packet *p)
}
EXPORT_ELEMENT(MarkIPHeader)
ELEMENT_MT_SAFE(MarkIPHeader)
......@@ -58,3 +58,5 @@ SaveIPFields::simple_action(Packet *p)
ELEMENT_REQUIRES(false)
EXPORT_ELEMENT(SaveIPFields)
ELEMENT_MT_SAFE(SaveIPFields)
......@@ -53,3 +53,5 @@ SetIPAddress::simple_action(Packet *p)
}
EXPORT_ELEMENT(SetIPAddress)
ELEMENT_MT_SAFE(SetIPAddress)
......@@ -70,3 +70,5 @@ SetIPChecksum::simple_action(Packet *p_in)
}
EXPORT_ELEMENT(SetIPChecksum)
ELEMENT_MT_SAFE(SetIPChecksum)
......@@ -111,3 +111,5 @@ SetIPDSCP::add_handlers()
}
EXPORT_ELEMENT(SetIPDSCP)
ELEMENT_MT_SAFE(SetIPDSCP)
......@@ -59,3 +59,5 @@ StoreIPAddress::simple_action(Packet *p)
}
EXPORT_ELEMENT(StoreIPAddress)
ELEMENT_MT_SAFE(StoreIPAddress)
......@@ -44,3 +44,5 @@ StripIPHeader::simple_action(Packet *p)
}
EXPORT_ELEMENT(StripIPHeader)
ELEMENT_MT_SAFE(StripIPHeader)
......@@ -46,3 +46,4 @@ UnstripIPHeader::simple_action(Packet *p)
}
EXPORT_ELEMENT(UnstripIPHeader)
ELEMENT_MT_SAFE(UnstripIPHeader)
/*
* Copyright (c) 1999-2000 Massachusetts Institute of Technology
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Further elaboration of this license, including a DISCLAIMER OF ANY
* WARRANTY, EXPRESS OR IMPLIED, is provided in the LICENSE file, which is
* also accessible at http://www.pdos.lcs.mit.edu/click/license.html
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <click/config.h>
#include <click/package.hh>
#include "cpuswitch.hh"
#include <click/error.hh>
#include <click/confparse.hh>
CPUSwitch::CPUSwitch()
{
MOD_INC_USE_COUNT;
set_ninputs(1);
}
CPUSwitch::~CPUSwitch()
{
MOD_DEC_USE_COUNT;
}